Skip to content

Commit

Permalink
feat(validation): Add noValidate helper (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
JoseLion authored Aug 12, 2023
1 parent 4ebef58 commit 33e69d6
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 6 deletions.
24 changes: 20 additions & 4 deletions packages/core/src/lib/helpers/adapters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { get } from "dot-prop-immutable";
import { ObjectSchema, ValidationError, isSchema, reach } from "yup";
import { ZodError, ZodObject, ZodSchema, ZodType } from "zod";

import type { Path, Struct } from "../Form.context";
import type { Optional, Path, Struct, ValueByPath } from "../Form.context";

/**
* A result type used to represent either a success or an error value.
Expand All @@ -20,8 +20,9 @@ export type Result<S, E> = { success: S; } | { error: E; };
*/
export interface Adapter<T extends Struct> {
/**
* Should return `true` if the `path` parameter is required in the validation
* schema. E.i., when the field cannot be `null` or `undefined`.
* Should return `true` if the field in the `path` is required in the
* validation schema. I.e., whenever the field cannot be `null`,
* `undefined`, non-empty, etc.
*
* @param path the path to check if it's requried
* @returns wether a path is required or not
Expand Down Expand Up @@ -51,7 +52,22 @@ export interface Adapter<T extends Struct> {
* @param value the value to validate against
* @returns a promise with the `Result<S, E>` of the validation
*/
validateAt: <V>(path: Path<T>, value: V) => Promise<Result<true, string>>;
validateAt: <K extends Path<T>>(path: K, value: Optional<ValueByPath<T, K>>) => Promise<Result<true, string>>;
}

/**
* Helper function that creates an {@link Adapter|Adapter\<T\>} to bypass the
* form validation.
*
* @param T struct type of the form values
* @returns an adapter to bypass validation
*/
export function noValidate<T extends Struct>(): Adapter<T> {
return {
required: () => false,
validate: values => Promise.resolve({ success: values as T }),
validateAt: () => Promise.resolve({ success: true }),
};
}

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/lib/hooks/useField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { get, set } from "dot-prop-immutable";
import { Dispatch, SetStateAction, useCallback, useEffect, useMemo } from "react";
import { useContextSelector } from "use-context-selector";

import { Optional, Path, Struct, safeFormContext } from "../Form.context";
import { Optional, Path, Struct, ValueByPath, safeFormContext } from "../Form.context";
import { getAdapter, handleResult } from "../helpers/adapters";
import { isFunctionAction } from "../helpers/commons";

Expand Down Expand Up @@ -81,7 +81,7 @@ export function useField<
if (touched || submitted) {
const { validateAt } = getAdapter(validation);

validateAt(path, value)
validateAt(path, value as ValueByPath<T, Path<T>>)
.then(
handleResult(
() => setViolations(prev => {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export {
export {
type Adapter,
type Result,
noValidate,
} from "./lib/helpers/adapters";

export {
Expand Down
1 change: 1 addition & 0 deletions packages/core/test/integration/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ describe("[Integration] main.test.tsx", () => {
"FormProvider",
"arrayFieldOf",
"fieldOf",
"noValidate",
"useArrayField",
"useField",
"useFieldValidation",
Expand Down

0 comments on commit 33e69d6

Please sign in to comment.