Frontend Enhancements: - Complete React TypeScript frontend with modern UI components - Distributed workflows management interface with real-time updates - Socket.IO integration for live agent status monitoring - Agent management dashboard with cluster visualization - Project management interface with metrics and task tracking - Responsive design with proper error handling and loading states Backend Infrastructure: - Distributed coordinator for multi-agent workflow orchestration - Cluster management API with comprehensive agent operations - Enhanced database models for agents and projects - Project service for filesystem-based project discovery - Performance monitoring and metrics collection - Comprehensive API documentation and error handling Documentation: - Complete distributed development guide (README_DISTRIBUTED.md) - Comprehensive development report with architecture insights - System configuration templates and deployment guides The platform now provides a complete web interface for managing the distributed AI cluster with real-time monitoring, workflow orchestration, and agent coordination capabilities. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
795 lines
22 KiB
Markdown
795 lines
22 KiB
Markdown
<div align="center">
|
|
<p align="center">
|
|
<a href="https://react-hook-form.com" title="React Hook Form - Simple React forms validation">
|
|
<img src="https://raw.githubusercontent.com/bluebill1049/react-hook-form/master/docs/logo.png" alt="React Hook Form Logo - React hook custom hook for form validation" />
|
|
</a>
|
|
</p>
|
|
</div>
|
|
|
|
<p align="center">Performant, flexible and extensible forms with easy to use validation.</p>
|
|
|
|
<div align="center">
|
|
|
|
[](https://www.npmjs.com/package/@hookform/resolvers)
|
|
[](https://www.npmjs.com/package/@hookform/resolvers)
|
|
[](https://bundlephobia.com/result?p=@hookform/resolvers)
|
|
|
|
</div>
|
|
|
|
## Install
|
|
|
|
npm install @hookform/resolvers
|
|
|
|
## Links
|
|
|
|
- [React-hook-form validation resolver documentation ](https://react-hook-form.com/api/useform/#resolver)
|
|
|
|
### Supported resolvers
|
|
|
|
- [Install](#install)
|
|
- [Links](#links)
|
|
- [Supported resolvers](#supported-resolvers)
|
|
- [API](#api)
|
|
- [Quickstart](#quickstart)
|
|
- [Yup](#yup)
|
|
- [Zod](#zod)
|
|
- [Superstruct](#superstruct)
|
|
- [Joi](#joi)
|
|
- [Vest](#vest)
|
|
- [Class Validator](#class-validator)
|
|
- [io-ts](#io-ts)
|
|
- [Nope](#nope)
|
|
- [computed-types](#computed-types)
|
|
- [typanion](#typanion)
|
|
- [Ajv](#ajv)
|
|
- [TypeBox](#typebox)
|
|
- [With `ValueCheck`](#with-valuecheck)
|
|
- [With `TypeCompiler`](#with-typecompiler)
|
|
- [ArkType](#arktype)
|
|
- [Valibot](#valibot)
|
|
- [TypeSchema](#typeschema)
|
|
- [effect-ts](#effect-ts)
|
|
- [VineJS](#vinejs)
|
|
- [fluentvalidation-ts](#fluentvalidation-ts)
|
|
- [Backers](#backers)
|
|
- [Sponsors](#sponsors)
|
|
- [Contributors](#contributors)
|
|
|
|
## API
|
|
|
|
```
|
|
type Options = {
|
|
mode: 'async' | 'sync',
|
|
raw?: boolean
|
|
}
|
|
|
|
resolver(schema: object, schemaOptions?: object, resolverOptions: Options)
|
|
```
|
|
|
|
| | type | Required | Description |
|
|
| --------------- | -------- | -------- | --------------------------------------------- |
|
|
| schema | `object` | ✓ | validation schema |
|
|
| schemaOptions | `object` | | validation library schema options |
|
|
| resolverOptions | `object` | | resolver options, `async` is the default mode |
|
|
|
|
## Quickstart
|
|
|
|
### [Yup](https://github.com/jquense/yup)
|
|
|
|
Dead simple Object schema validation.
|
|
|
|
[](https://bundlephobia.com/result?p=yup)
|
|
|
|
```typescript jsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { yupResolver } from '@hookform/resolvers/yup';
|
|
import * as yup from 'yup';
|
|
|
|
const schema = yup
|
|
.object()
|
|
.shape({
|
|
name: yup.string().required(),
|
|
age: yup.number().required(),
|
|
})
|
|
.required();
|
|
|
|
const App = () => {
|
|
const { register, handleSubmit } = useForm({
|
|
resolver: yupResolver(schema),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((d) => console.log(d))}>
|
|
<input {...register('name')} />
|
|
<input type="number" {...register('age')} />
|
|
<input type="submit" />
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
### [Zod](https://github.com/vriad/zod)
|
|
|
|
TypeScript-first schema validation with static type inference
|
|
|
|
[](https://bundlephobia.com/result?p=zod)
|
|
|
|
> ⚠️ Example below uses the `valueAsNumber`, which requires `react-hook-form` v6.12.0 (released Nov 28, 2020) or later.
|
|
|
|
```tsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
import * as z from 'zod';
|
|
|
|
const schema = z.object({
|
|
name: z.string().min(1, { message: 'Required' }),
|
|
age: z.number().min(10),
|
|
});
|
|
|
|
const App = () => {
|
|
const {
|
|
register,
|
|
handleSubmit,
|
|
formState: { errors },
|
|
} = useForm({
|
|
resolver: zodResolver(schema),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((d) => console.log(d))}>
|
|
<input {...register('name')} />
|
|
{errors.name?.message && <p>{errors.name?.message}</p>}
|
|
<input type="number" {...register('age', { valueAsNumber: true })} />
|
|
{errors.age?.message && <p>{errors.age?.message}</p>}
|
|
<input type="submit" />
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
### [Superstruct](https://github.com/ianstormtaylor/superstruct)
|
|
|
|
A simple and composable way to validate data in JavaScript (or TypeScript).
|
|
|
|
[](https://bundlephobia.com/result?p=superstruct)
|
|
|
|
```typescript jsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { superstructResolver } from '@hookform/resolvers/superstruct';
|
|
import { object, string, number } from 'superstruct';
|
|
|
|
const schema = object({
|
|
name: string(),
|
|
age: number(),
|
|
});
|
|
|
|
const App = () => {
|
|
const { register, handleSubmit } = useForm({
|
|
resolver: superstructResolver(schema),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((d) => console.log(d))}>
|
|
<input {...register('name')} />
|
|
<input type="number" {...register('age', { valueAsNumber: true })} />
|
|
<input type="submit" />
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
### [Joi](https://github.com/sideway/joi)
|
|
|
|
The most powerful data validation library for JS.
|
|
|
|
[](https://bundlephobia.com/result?p=joi)
|
|
|
|
```typescript jsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { joiResolver } from '@hookform/resolvers/joi';
|
|
import Joi from 'joi';
|
|
|
|
const schema = Joi.object({
|
|
name: Joi.string().required(),
|
|
age: Joi.number().required(),
|
|
});
|
|
|
|
const App = () => {
|
|
const { register, handleSubmit } = useForm({
|
|
resolver: joiResolver(schema),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((d) => console.log(d))}>
|
|
<input {...register('name')} />
|
|
<input type="number" {...register('age')} />
|
|
<input type="submit" />
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
### [Vest](https://github.com/ealush/vest)
|
|
|
|
Vest 🦺 Declarative Validation Testing.
|
|
|
|
[](https://bundlephobia.com/result?p=vest)
|
|
|
|
```typescript jsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { vestResolver } from '@hookform/resolvers/vest';
|
|
import { create, test, enforce } from 'vest';
|
|
|
|
const validationSuite = create((data = {}) => {
|
|
test('username', 'Username is required', () => {
|
|
enforce(data.username).isNotEmpty();
|
|
});
|
|
|
|
test('password', 'Password is required', () => {
|
|
enforce(data.password).isNotEmpty();
|
|
});
|
|
});
|
|
|
|
const App = () => {
|
|
const { register, handleSubmit, errors } = useForm({
|
|
resolver: vestResolver(validationSuite),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((data) => console.log(data))}>
|
|
<input {...register('username')} />
|
|
<input type="password" {...register('password')} />
|
|
<input type="submit" />
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
### [Class Validator](https://github.com/typestack/class-validator)
|
|
|
|
Decorator-based property validation for classes.
|
|
|
|
[](https://bundlephobia.com/result?p=class-validator)
|
|
|
|
> ⚠️ Remember to add these options to your `tsconfig.json`!
|
|
|
|
```
|
|
"strictPropertyInitialization": false,
|
|
"experimentalDecorators": true
|
|
```
|
|
|
|
```tsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { classValidatorResolver } from '@hookform/resolvers/class-validator';
|
|
import { Length, Min, IsEmail } from 'class-validator';
|
|
|
|
class User {
|
|
@Length(2, 30)
|
|
username: string;
|
|
|
|
@IsEmail()
|
|
email: string;
|
|
}
|
|
|
|
const resolver = classValidatorResolver(User);
|
|
|
|
const App = () => {
|
|
const {
|
|
register,
|
|
handleSubmit,
|
|
formState: { errors },
|
|
} = useForm<User>({ resolver });
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((data) => console.log(data))}>
|
|
<input type="text" {...register('username')} />
|
|
{errors.username && <span>{errors.username.message}</span>}
|
|
<input type="text" {...register('email')} />
|
|
{errors.email && <span>{errors.email.message}</span>}
|
|
<input type="submit" value="Submit" />
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
### [io-ts](https://github.com/gcanti/io-ts)
|
|
|
|
Validate your data with powerful decoders.
|
|
|
|
[](https://bundlephobia.com/result?p=io-ts)
|
|
|
|
```typescript jsx
|
|
import React from 'react';
|
|
import { useForm } from 'react-hook-form';
|
|
import { ioTsResolver } from '@hookform/resolvers/io-ts';
|
|
import t from 'io-ts';
|
|
// you don't have to use io-ts-types, but it's very useful
|
|
import tt from 'io-ts-types';
|
|
|
|
const schema = t.type({
|
|
username: t.string,
|
|
age: tt.NumberFromString,
|
|
});
|
|
|
|
const App = () => {
|
|
const { register, handleSubmit } = useForm({
|
|
resolver: ioTsResolver(schema),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((d) => console.log(d))}>
|
|
<input {...register('username')} />
|
|
<input type="number" {...register('age')} />
|
|
<input type="submit" />
|
|
</form>
|
|
);
|
|
};
|
|
|
|
export default App;
|
|
```
|
|
|
|
### [Nope](https://github.com/bvego/nope-validator)
|
|
|
|
A small, simple, and fast JS validator
|
|
|
|
[](https://bundlephobia.com/result?p=nope-validator)
|
|
|
|
```typescript jsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { nopeResolver } from '@hookform/resolvers/nope';
|
|
import Nope from 'nope-validator';
|
|
|
|
const schema = Nope.object().shape({
|
|
name: Nope.string().required(),
|
|
age: Nope.number().required(),
|
|
});
|
|
|
|
const App = () => {
|
|
const { register, handleSubmit } = useForm({
|
|
resolver: nopeResolver(schema),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((d) => console.log(d))}>
|
|
<input {...register('name')} />
|
|
<input type="number" {...register('age')} />
|
|
<input type="submit" />
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
### [computed-types](https://github.com/neuledge/computed-types)
|
|
|
|
TypeScript-first schema validation with static type inference
|
|
|
|
[](https://bundlephobia.com/result?p=computed-types)
|
|
|
|
```tsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { computedTypesResolver } from '@hookform/resolvers/computed-types';
|
|
import Schema, { number, string } from 'computed-types';
|
|
|
|
const schema = Schema({
|
|
username: string.min(1).error('username field is required'),
|
|
age: number,
|
|
});
|
|
|
|
const App = () => {
|
|
const {
|
|
register,
|
|
handleSubmit,
|
|
formState: { errors },
|
|
} = useForm({
|
|
resolver: computedTypesResolver(schema),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((d) => console.log(d))}>
|
|
<input {...register('name')} />
|
|
{errors.name?.message && <p>{errors.name?.message}</p>}
|
|
<input type="number" {...register('age', { valueAsNumber: true })} />
|
|
{errors.age?.message && <p>{errors.age?.message}</p>}
|
|
<input type="submit" />
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
### [typanion](https://github.com/arcanis/typanion)
|
|
|
|
Static and runtime type assertion library with no dependencies
|
|
|
|
[](https://bundlephobia.com/result?p=typanion)
|
|
|
|
```tsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { typanionResolver } from '@hookform/resolvers/typanion';
|
|
import * as t from 'typanion';
|
|
|
|
const isUser = t.isObject({
|
|
username: t.applyCascade(t.isString(), [t.hasMinLength(1)]),
|
|
age: t.applyCascade(t.isNumber(), [
|
|
t.isInteger(),
|
|
t.isInInclusiveRange(1, 100),
|
|
]),
|
|
});
|
|
|
|
const App = () => {
|
|
const {
|
|
register,
|
|
handleSubmit,
|
|
formState: { errors },
|
|
} = useForm({
|
|
resolver: typanionResolver(isUser),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((d) => console.log(d))}>
|
|
<input {...register('name')} />
|
|
{errors.name?.message && <p>{errors.name?.message}</p>}
|
|
<input type="number" {...register('age')} />
|
|
{errors.age?.message && <p>{errors.age?.message}</p>}
|
|
<input type="submit" />
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
### [Ajv](https://github.com/ajv-validator/ajv)
|
|
|
|
The fastest JSON validator for Node.js and browser
|
|
|
|
[](https://bundlephobia.com/result?p=ajv)
|
|
|
|
```tsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { ajvResolver } from '@hookform/resolvers/ajv';
|
|
|
|
// must use `minLength: 1` to implement required field
|
|
const schema = {
|
|
type: 'object',
|
|
properties: {
|
|
username: {
|
|
type: 'string',
|
|
minLength: 1,
|
|
errorMessage: { minLength: 'username field is required' },
|
|
},
|
|
password: {
|
|
type: 'string',
|
|
minLength: 1,
|
|
errorMessage: { minLength: 'password field is required' },
|
|
},
|
|
},
|
|
required: ['username', 'password'],
|
|
additionalProperties: false,
|
|
};
|
|
|
|
const App = () => {
|
|
const {
|
|
register,
|
|
handleSubmit,
|
|
formState: { errors },
|
|
} = useForm({
|
|
resolver: ajvResolver(schema),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((data) => console.log(data))}>
|
|
<input {...register('username')} />
|
|
{errors.username && <span>{errors.username.message}</span>}
|
|
<input {...register('password')} />
|
|
{errors.password && <span>{errors.password.message}</span>}
|
|
<button type="submit">submit</button>
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
### [TypeBox](https://github.com/sinclairzx81/typebox)
|
|
|
|
JSON Schema Type Builder with Static Type Resolution for TypeScript
|
|
|
|
[](https://bundlephobia.com/result?p=@sinclair/typebox)
|
|
|
|
#### With `ValueCheck`
|
|
|
|
```typescript jsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { typeboxResolver } from '@hookform/resolvers/typebox';
|
|
import { Type } from '@sinclair/typebox';
|
|
|
|
const schema = Type.Object({
|
|
username: Type.String({ minLength: 1 }),
|
|
password: Type.String({ minLength: 1 }),
|
|
});
|
|
|
|
const App = () => {
|
|
const { register, handleSubmit } = useForm({
|
|
resolver: typeboxResolver(schema),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((d) => console.log(d))}>
|
|
<input {...register('username')} />
|
|
<input type="password" {...register('password')} />
|
|
<input type="submit" />
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
#### With `TypeCompiler`
|
|
|
|
A high-performance JIT of `TypeBox`, [read more](https://github.com/sinclairzx81/typebox#typecompiler)
|
|
|
|
```typescript jsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { typeboxResolver } from '@hookform/resolvers/typebox';
|
|
import { Type } from '@sinclair/typebox';
|
|
import { TypeCompiler } from '@sinclair/typebox/compiler';
|
|
|
|
const schema = Type.Object({
|
|
username: Type.String({ minLength: 1 }),
|
|
password: Type.String({ minLength: 1 }),
|
|
});
|
|
|
|
const typecheck = TypeCompiler.Compile(schema);
|
|
|
|
const App = () => {
|
|
const { register, handleSubmit } = useForm({
|
|
resolver: typeboxResolver(typecheck),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((d) => console.log(d))}>
|
|
<input {...register('username')} />
|
|
<input type="password" {...register('password')} />
|
|
<input type="submit" />
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
### [ArkType](https://github.com/arktypeio/arktype)
|
|
|
|
TypeScript's 1:1 validator, optimized from editor to runtime
|
|
|
|
[](https://bundlephobia.com/result?p=arktype)
|
|
|
|
```typescript jsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { arktypeResolver } from '@hookform/resolvers/arktype';
|
|
import { type } from 'arktype';
|
|
|
|
const schema = type({
|
|
username: 'string>1',
|
|
password: 'string>1',
|
|
});
|
|
|
|
const App = () => {
|
|
const { register, handleSubmit } = useForm({
|
|
resolver: arktypeResolver(schema),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((d) => console.log(d))}>
|
|
<input {...register('username')} />
|
|
<input type="password" {...register('password')} />
|
|
<input type="submit" />
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
### [Valibot](https://github.com/fabian-hiller/valibot)
|
|
|
|
The modular and type safe schema library for validating structural data
|
|
|
|
[](https://bundlephobia.com/result?p=valibot)
|
|
|
|
```typescript jsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { valibotResolver } from '@hookform/resolvers/valibot';
|
|
import * as v from 'valibot';
|
|
|
|
const schema = v.object({
|
|
username: v.pipe(
|
|
v.string('username is required'),
|
|
v.minLength(3, 'Needs to be at least 3 characters'),
|
|
v.endsWith('cool', 'Needs to end with `cool`'),
|
|
),
|
|
password: v.string('password is required'),
|
|
});
|
|
|
|
const App = () => {
|
|
const { register, handleSubmit } = useForm({
|
|
resolver: valibotResolver(schema),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((d) => console.log(d))}>
|
|
<input {...register('username')} />
|
|
<input type="password" {...register('password')} />
|
|
<input type="submit" />
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
### [TypeSchema](https://typeschema.com)
|
|
|
|
Universal adapter for schema validation, compatible with [any validation library](https://typeschema.com/#coverage)
|
|
|
|
[](https://bundlephobia.com/result?p=@typeschema/main)
|
|
|
|
```typescript jsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { typeschemaResolver } from '@hookform/resolvers/typeschema';
|
|
import * as z from 'zod';
|
|
|
|
// Use your favorite validation library
|
|
const schema = z.object({
|
|
username: z.string().min(1, { message: 'Required' }),
|
|
password: z.number().min(1, { message: 'Required' }),
|
|
});
|
|
|
|
const App = () => {
|
|
const { register, handleSubmit } = useForm({
|
|
resolver: typeschemaResolver(schema),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((d) => console.log(d))}>
|
|
<input {...register('username')} />
|
|
<input type="password" {...register('password')} />
|
|
<input type="submit" />
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
### [effect-ts](https://github.com/Effect-TS/effect)
|
|
|
|
A powerful TypeScript framework that provides a fully-fledged functional effect system with a rich standard library.
|
|
|
|
[](https://bundlephobia.com/result?p=effect)
|
|
|
|
```typescript jsx
|
|
import React from 'react';
|
|
import { useForm } from 'react-hook-form';
|
|
import { effectTsResolver } from '@hookform/resolvers/effect-ts';
|
|
import { Schema } from 'effect';
|
|
|
|
const schema = Schema.Struct({
|
|
username: Schema.String.pipe(
|
|
Schema.nonEmpty({ message: () => 'username required' }),
|
|
),
|
|
password: Schema.String.pipe(
|
|
Schema.nonEmpty({ message: () => 'password required' }),
|
|
),
|
|
});
|
|
|
|
type FormData = typeof schema.Type;
|
|
|
|
interface Props {
|
|
onSubmit: (data: FormData) => void;
|
|
}
|
|
|
|
function TestComponent({ onSubmit }: Props) {
|
|
const {
|
|
register,
|
|
handleSubmit,
|
|
formState: { errors },
|
|
// provide generic if TS has issues inferring types
|
|
} = useForm<FormData>({
|
|
resolver: effectTsResolver(schema),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit(onSubmit)}>
|
|
<input {...register('username')} />
|
|
{errors.username && <span role="alert">{errors.username.message}</span>}
|
|
|
|
<input {...register('password')} />
|
|
{errors.password && <span role="alert">{errors.password.message}</span>}
|
|
|
|
<button type="submit">submit</button>
|
|
</form>
|
|
);
|
|
}
|
|
```
|
|
|
|
### [VineJS](https://github.com/vinejs/vine)
|
|
|
|
VineJS is a form data validation library for Node.js
|
|
|
|
[](https://bundlephobia.com/result?p=@vinejs/vine)
|
|
|
|
```typescript jsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { vineResolver } from '@hookform/resolvers/vine';
|
|
import vine from '@vinejs/vine';
|
|
|
|
const schema = vine.compile(
|
|
vine.object({
|
|
username: vine.string().minLength(1),
|
|
password: vine.string().minLength(1),
|
|
}),
|
|
);
|
|
|
|
const App = () => {
|
|
const { register, handleSubmit } = useForm({
|
|
resolver: vineResolver(schema),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((d) => console.log(d))}>
|
|
<input {...register('username')} />
|
|
{errors.username && <span role="alert">{errors.username.message}</span>}
|
|
<input {...register('password')} />
|
|
{errors.password && <span role="alert">{errors.password.message}</span>}
|
|
<button type="submit">submit</button>
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
|
|
### [fluentvalidation-ts](https://github.com/AlexJPotter/fluentvalidation-ts)
|
|
|
|
A TypeScript-first library for building strongly-typed validation rules
|
|
|
|
[](https://bundlephobia.com/result?p=@vinejs/vine)
|
|
|
|
```typescript jsx
|
|
import { useForm } from 'react-hook-form';
|
|
import { fluentValidationResolver } from '@hookform/resolvers/fluentvalidation-ts';
|
|
import { Validator } from 'fluentvalidation-ts';
|
|
|
|
class FormDataValidator extends Validator<FormData> {
|
|
constructor() {
|
|
super();
|
|
|
|
this.ruleFor('username')
|
|
.notEmpty()
|
|
.withMessage('username is a required field');
|
|
this.ruleFor('password')
|
|
.notEmpty()
|
|
.withMessage('password is a required field');
|
|
}
|
|
}
|
|
|
|
const App = () => {
|
|
const { register, handleSubmit } = useForm({
|
|
resolver: fluentValidationResolver(new FormDataValidator()),
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit((d) => console.log(d))}>
|
|
<input {...register('username')} />
|
|
{errors.username && <span role="alert">{errors.username.message}</span>}
|
|
<input {...register('password')} />
|
|
{errors.password && <span role="alert">{errors.password.message}</span>}
|
|
<button type="submit">submit</button>
|
|
</form>
|
|
);
|
|
};
|
|
```
|
|
|
|
## Backers
|
|
|
|
Thanks go to all our backers! [[Become a backer](https://opencollective.com/react-hook-form#backer)].
|
|
|
|
<a href="https://opencollective.com/react-hook-form#backers">
|
|
<img src="https://opencollective.com/react-hook-form/backers.svg?width=950" />
|
|
</a>
|
|
|
|
## Contributors
|
|
|
|
Thanks go to these wonderful people! [[Become a contributor](CONTRIBUTING.md)].
|
|
|
|
<a href="https://github.com/react-hook-form/react-hook-form/graphs/contributors">
|
|
<img src="https://opencollective.com/react-hook-form/contributors.svg?width=950" />
|
|
</a>
|