Перейти до основного вмісту

Валідатор

інформація

Валідатор - документ, який відповідає за опис структур валідації даних. Методи обробки даних можуть бути використанні при створенні форм представлень, валідації вихідних параметрів взаємодії по API.

порада

X-Fiber не вимагає обов'язкового створення валідації як для вхідних, так і для вихідних параметрів. Однак здійснювати валідацію як для вхідних, так і для вихідних параметрів є гарною практикою. Перевірка вхідних параметрів має відбуватися під час обробки вхідних даних з форм. У випадку помилок валідації вихідних параметрів при отриманні по API рекомендується створювати alerting, щоб оперативно реагувати та виправляти невідповідності валідованих даних вже на стороні веб-сервера.

Архітектура

Першочергово валідатор повинен бути зареєстрований в предметній області, яка повинна бути зареєстрована у відповідному сервісі. При запуску веб-застосунку відбувається завантаження бізнес-схеми в ядро відображень, формуючи знімок бізнес-схеми. В разі використання представлень на сторінці з якою взаємодіє користувач - валідація буде здійснюватись згідно її залучення в представлені при зверненні до цього представлення користувачем.

інформація

За основу роботи провайдера кожного методу валідації даних відповідає бібліотека Joi.

Склад

Валідатор відображає структуру даних у форматі "ключ-значення", де кожен ключ відображає назву функції, а йому відповідає власне сама функція. Цей підхід дозволяє зручно організувати та керувати функціональними можливостями системи, забезпечуючи швидкий доступ до потрібного функціоналу через ім'я функції як ключ.

import joi from 'joi'

type ValidateErrors = Array<{
message: string;
key?: string;
value?: string;
}>;

export type Localization = {
// readonly supportedLanguages
// readonly defaultLanguages
// getResource
// getAnotherResource
};

type ValidateSchema = {}
type Handler<I = any> = (
provider: joi.Root,
localization: Localization,
data: I
) => ValidateErrors | null;


type Structure<T extends Record<string, any>> = {
[K in keyof T]: T[K] extends infer I ? Handler<I> : T[K];
}

де:

  • ValidateErrors - структура типу масиву помилок валідації даних.
  • Localization - тип обʼєкта локалізації з переліком методів по роботі з перекладами.
  • Handler - тип обробника валідації даних.
    • I - тип структури даних, яка буде передана в обробник, та яку необхідно буде валідувати.
    • joi.Root - набер методів валідації, які надаються бібліотекою joi.
  • Structure - структура валідатора, яка представляє собою обʼєкт з переліком функцій валідації даних.
    • K - назва функції строкового типу.
    • T - тіло функції.
    • I - тип структури даних, яку необхідно провалідувати, дорівнює типу I Handler.

Реалізація

import {setValidator} from '@x-fiber/display';

type Provider = {
// ... list of methods
}
type Localization = {
// ... list of methods
}
type ValidateErrors = Array<{
// ... error structure
}>

type v1SignupParams = {
firstName: string;
lastName: string;
login: string;
phone?: string;
email?: string;
password: string;
confirmPassword: string;
};
type Validator = {
v1SignupParams: v1SignupParams
};

export const BusUsersAuthSpecValidator = setValidator<Validator>({
v1SignupParams: (p: Provider, localization: Localization, data: v1SignupParams): ValidateErrors | null => {
const schema = p.object<v1SignupParams>({
firstName: p.string().min(3).max(50).required(),
lastName: p.string().min(3).max(50).required(),
email: p.string().min(3).max(320).email(),
phone: p.string().min(13).max(13),
password: p.string().min(3).required(),
confirmPassword: p.string().valid(p.ref("password")).required(),
});

const result = schema.validate(data);

if (!result.error) return null;

return result.error.details.map((d: any) => {
return {
message: d.message,
key: d.path,
value: d.type,
};
});
},
})

Реєстрація

Для використання валідацій необхідно зареєструвати документ "Валідатор" в точці входу в предметну область pointer. Наприклад, для модуля BusUsersAgg, необхідно використовувати функцію setPointer для встановлення посилання на валідатор та інші компоненти модуля.

import {setPointer} from "@x-fiber/display";
import {BusUsersAggValidator} from "./BusUsers.agg.validator";

type BusDomains = 'BusUsersAgg' | 'BusUsersAuthSpec'

export const BusUsersAggPointer = setPointer<BusDomains>("BusUsersAgg", {
validator: BusUsersAggValidator,
// ... other documents
});