feat(Form): add superstruct validation (#2363)

Co-authored-by: Benjamin Canac <canacb1@gmail.com>
Co-authored-by: Romain Hamel <rom.hml@gmail.com>
This commit is contained in:
rizkyyy
2024-10-19 19:07:22 +07:00
committed by GitHub
parent 7802aacf3f
commit 5385944359
10 changed files with 166 additions and 5 deletions

View File

@@ -35,7 +35,7 @@ export interface FormSlots {
import { provide, inject, nextTick, ref, onUnmounted, onMounted, computed, useId, readonly } from 'vue'
import { useEventBus } from '@vueuse/core'
import { formOptionsInjectionKey, formInputsInjectionKey, formBusInjectionKey, formLoadingInjectionKey } from '../composables/useFormField'
import { getYupErrors, isYupSchema, getValibotErrors, isValibotSchema, getZodErrors, isZodSchema, getJoiErrors, isJoiSchema, getStandardErrors, isStandardSchema } from '../utils/form'
import { getYupErrors, isYupSchema, getValibotErrors, isValibotSchema, getZodErrors, isZodSchema, getJoiErrors, isJoiSchema, getStandardErrors, isStandardSchema, getSuperStructErrors, isSuperStructSchema } from '../utils/form'
import { FormValidationException } from '../types/form'
const props = withDefaults(defineProps<FormProps<T>>(), {
@@ -113,6 +113,8 @@ async function getErrors(): Promise<FormErrorWithId[]> {
errs = errs.concat(await getJoiErrors(props.state, props.schema))
} else if (isValibotSchema(props.schema)) {
errs = errs.concat(await getValibotErrors(props.state, props.schema))
} else if (isSuperStructSchema(props.schema)) {
errs = errs.concat(await getSuperStructErrors(props.state, props.schema))
} else if (isStandardSchema(props.schema)) {
errs = errs.concat(await getStandardErrors(props.state, props.schema))
} else {

View File

@@ -5,6 +5,7 @@ import type { Schema as JoiSchema } from 'joi'
import type { ObjectSchema as YupObjectSchema } from 'yup'
import type { GenericSchema as ValibotSchema, GenericSchemaAsync as ValibotSchemaAsync, SafeParser as ValibotSafeParser, SafeParserAsync as ValibotSafeParserAsync } from 'valibot'
import type { GetObjectField } from './utils'
import type { Struct as SuperstructSchema } from 'superstruct'
export interface Form<T> {
validate (opts?: { name: string | string[], silent?: false, nested?: boolean }): Promise<T | false>
@@ -19,9 +20,12 @@ export interface Form<T> {
export type FormSchema<T extends Record<string, any>> =
| ZodSchema
| YupObjectSchema<T>
| ValibotSchema | ValibotSchemaAsync
| ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>
| ValibotSchema
| ValibotSchemaAsync
| ValibotSafeParser<any, any>
| ValibotSafeParserAsync<any, any>
| JoiSchema<T>
| SuperstructSchema<any, any>
| StandardSchema
export type FormInputEvents = 'input' | 'blur' | 'change'

View File

@@ -3,6 +3,7 @@ import type { ZodSchema } from 'zod'
import type { ValidationError as JoiError, Schema as JoiSchema } from 'joi'
import type { ObjectSchema as YupObjectSchema, ValidationError as YupError } from 'yup'
import type { GenericSchema as ValibotSchema, GenericSchemaAsync as ValibotSchemaAsync, SafeParser as ValibotSafeParser, SafeParserAsync as ValibotSafeParserAsync } from 'valibot'
import type { Struct } from 'superstruct'
import type { FormError } from '../types/form'
export function isYupSchema(schema: any): schema is YupObjectSchema<any> {
@@ -29,6 +30,15 @@ export async function getYupErrors(state: any, schema: YupObjectSchema<any>): Pr
}
}
export function isSuperStructSchema(schema: any): schema is Struct<any, any> {
return (
'schema' in schema
&& typeof schema.coercer === 'function'
&& typeof schema.validator === 'function'
&& typeof schema.refiner === 'function'
)
}
export function isZodSchema(schema: any): schema is ZodSchema {
return schema.parse !== undefined
}
@@ -98,3 +108,15 @@ export async function getStandardErrors(
message: issue.message
})) || []
}
export async function getSuperStructErrors(state: any, schema: Struct<any, any>): Promise<FormError[]> {
const [err] = schema.validate(state)
if (err) {
const errors = err.failures()
return errors.map(error => ({
message: error.message,
name: error.path.join('.')
}))
}
return []
}