mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-14 12:14:41 +01:00
refactor(Form)!: drop explicit support for zod and valibot (#3618)
This commit is contained in:
@@ -21,7 +21,7 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<UForm :schema="v.safeParser(schema)" :state="state" class="space-y-4" @submit="onSubmit">
|
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
|
||||||
<UFormGroup label="Email" name="email">
|
<UFormGroup label="Email" name="email">
|
||||||
<UInput v-model="state.email" />
|
<UInput v-model="state.email" />
|
||||||
</UFormGroup>
|
</UFormGroup>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ It works with the [FormGroup](/components/form-group) component to display error
|
|||||||
|
|
||||||
The form component requires two props:
|
The form component requires two props:
|
||||||
- `state` - a reactive object holding the form's state.
|
- `state` - a reactive object holding the form's state.
|
||||||
- `schema` - a schema object from a validation library like [Yup](https://github.com/jquense/yup), [Zod](https://github.com/colinhacks/zod), [Joi](https://github.com/hapijs/joi), [Valibot](https://github.com/fabian-hiller/valibot) or [Superstruct](https://github.com/ianstormtaylor/superstruct).
|
- `schema` - any [Standard Schema](https://standardschema.dev/) or a schema from [Yup](https://github.com/jquense/yup), [Joi](https://github.com/hapijs/joi) or [Superstruct](https://github.com/ianstormtaylor/superstruct).
|
||||||
|
|
||||||
::callout{icon="i-heroicons-light-bulb"}
|
::callout{icon="i-heroicons-light-bulb"}
|
||||||
Note that **no validation library is included** by default, so ensure you **install the one you need**.
|
Note that **no validation library is included** by default, so ensure you **install the one you need**.
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"ufo": "^1.5.4",
|
"ufo": "^1.5.4",
|
||||||
"v-calendar": "^3.1.2",
|
"v-calendar": "^3.1.2",
|
||||||
"valibot": "^0.42.1",
|
"valibot": "^1.0.0",
|
||||||
"yup": "^1.6.1",
|
"yup": "^1.6.1",
|
||||||
"zod": "^3.24.2"
|
"zod": "^3.24.2"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,9 +69,7 @@
|
|||||||
"release-it": "^18.1.2",
|
"release-it": "^18.1.2",
|
||||||
"superstruct": "^2.0.2",
|
"superstruct": "^2.0.2",
|
||||||
"typescript": "^5.6.3",
|
"typescript": "^5.6.3",
|
||||||
"valibot": "^0.42.1",
|
"valibot": "^1.0.0",
|
||||||
"valibot30": "npm:valibot@0.30.0",
|
|
||||||
"valibot31": "npm:valibot@0.31.0",
|
|
||||||
"vitest": "^3.0.9",
|
"vitest": "^3.0.9",
|
||||||
"vitest-environment-nuxt": "^1.0.1",
|
"vitest-environment-nuxt": "^1.0.1",
|
||||||
"vue-tsc": "^2.1.10",
|
"vue-tsc": "^2.1.10",
|
||||||
|
|||||||
30
pnpm-lock.yaml
generated
30
pnpm-lock.yaml
generated
@@ -123,14 +123,8 @@ importers:
|
|||||||
specifier: 5.6.3
|
specifier: 5.6.3
|
||||||
version: 5.6.3
|
version: 5.6.3
|
||||||
valibot:
|
valibot:
|
||||||
specifier: ^0.42.1
|
specifier: ^1.0.0
|
||||||
version: 0.42.1(typescript@5.6.3)
|
version: 1.0.0(typescript@5.6.3)
|
||||||
valibot30:
|
|
||||||
specifier: npm:valibot@0.30.0
|
|
||||||
version: valibot@0.30.0
|
|
||||||
valibot31:
|
|
||||||
specifier: npm:valibot@0.31.0
|
|
||||||
version: valibot@0.31.0
|
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^3.0.9
|
specifier: ^3.0.9
|
||||||
version: 3.0.9(@types/debug@4.1.12)(@types/node@22.13.10)(happy-dom@17.4.4)(jiti@2.4.2)(terser@5.39.0)(yaml@2.7.0)
|
version: 3.0.9(@types/debug@4.1.12)(@types/node@22.13.10)(happy-dom@17.4.4)(jiti@2.4.2)(terser@5.39.0)(yaml@2.7.0)
|
||||||
@@ -213,8 +207,8 @@ importers:
|
|||||||
specifier: ^3.1.2
|
specifier: ^3.1.2
|
||||||
version: 3.1.2(@popperjs/core@2.11.8)(vue@3.5.13(typescript@5.6.3))
|
version: 3.1.2(@popperjs/core@2.11.8)(vue@3.5.13(typescript@5.6.3))
|
||||||
valibot:
|
valibot:
|
||||||
specifier: ^0.42.1
|
specifier: ^1.0.0
|
||||||
version: 0.42.1(typescript@5.6.3)
|
version: 1.0.0(typescript@5.6.3)
|
||||||
yup:
|
yup:
|
||||||
specifier: ^1.6.1
|
specifier: ^1.6.1
|
||||||
version: 1.6.1
|
version: 1.6.1
|
||||||
@@ -6409,14 +6403,8 @@ packages:
|
|||||||
'@popperjs/core': ^2.0.0
|
'@popperjs/core': ^2.0.0
|
||||||
vue: ^3.2.0
|
vue: ^3.2.0
|
||||||
|
|
||||||
valibot@0.30.0:
|
valibot@1.0.0:
|
||||||
resolution: {integrity: sha512-5POBdbSkM+3nvJ6ZlyQHsggisfRtyT4tVTo1EIIShs6qCdXJnyWU5TJ68vr8iTg5zpOLjXLRiBqNx+9zwZz/rA==}
|
resolution: {integrity: sha512-1Hc0ihzWxBar6NGeZv7fPLY0QuxFMyxwYR2sF1Blu7Wq7EnremwY2W02tit2ij2VJT8HcSkHAQqmFfl77f73Yw==}
|
||||||
|
|
||||||
valibot@0.31.0:
|
|
||||||
resolution: {integrity: sha512-bleS8aVFpRGTUgbMoXzsRJhpxJGiZ3MG1nuNSORuDvio+sI1EyT1+lQHg+77Pfnlxz+25Uj5HiwdaklcDcYdiQ==}
|
|
||||||
|
|
||||||
valibot@0.42.1:
|
|
||||||
resolution: {integrity: sha512-3keXV29Ar5b//Hqi4MbSdV7lfVp6zuYLZuA9V1PvQUsXqogr+u5lvLPLk3A4f74VUXDnf/JfWMN6sB+koJ/FFw==}
|
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: 5.6.3
|
typescript: 5.6.3
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
@@ -14429,11 +14417,7 @@ snapshots:
|
|||||||
vue: 3.5.13(typescript@5.6.3)
|
vue: 3.5.13(typescript@5.6.3)
|
||||||
vue-screen-utils: 1.0.0-beta.13(vue@3.5.13(typescript@5.6.3))
|
vue-screen-utils: 1.0.0-beta.13(vue@3.5.13(typescript@5.6.3))
|
||||||
|
|
||||||
valibot@0.30.0: {}
|
valibot@1.0.0(typescript@5.6.3):
|
||||||
|
|
||||||
valibot@0.31.0: {}
|
|
||||||
|
|
||||||
valibot@0.42.1(typescript@5.6.3):
|
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
typescript: 5.6.3
|
typescript: 5.6.3
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,6 @@
|
|||||||
"lockFileMaintenance": {
|
"lockFileMaintenance": {
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
"ignoreDeps": [
|
|
||||||
"valibot30",
|
|
||||||
"valibot31"
|
|
||||||
],
|
|
||||||
"baseBranches": ["v2", "v3"],
|
"baseBranches": ["v2", "v3"],
|
||||||
"packageRules": [{
|
"packageRules": [{
|
||||||
"matchBaseBranches": ["v3"],
|
"matchBaseBranches": ["v3"],
|
||||||
|
|||||||
@@ -7,12 +7,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { provide, ref, type PropType, defineComponent, onUnmounted, onMounted, readonly } from 'vue'
|
import { provide, ref, type PropType, defineComponent, onUnmounted, onMounted, readonly } from 'vue'
|
||||||
import { useEventBus } from '@vueuse/core'
|
import { useEventBus } from '@vueuse/core'
|
||||||
import type { ZodSchema } from 'zod'
|
|
||||||
import type { ValidationError as JoiError, Schema as JoiSchema } from 'joi'
|
import type { ValidationError as JoiError, Schema as JoiSchema } from 'joi'
|
||||||
import type { ObjectSchema as YupObjectSchema, ValidationError as YupError } from 'yup'
|
import type { ObjectSchema as YupObjectSchema, ValidationError as YupError } from 'yup'
|
||||||
import type { BaseSchema as ValibotSchema30, BaseSchemaAsync as ValibotSchemaAsync30 } from 'valibot30'
|
|
||||||
import type { GenericSchema as ValibotSchema31, GenericSchemaAsync as ValibotSchemaAsync31, SafeParser as ValibotSafeParser31, SafeParserAsync as ValibotSafeParserAsync31 } from 'valibot31'
|
|
||||||
import type { GenericSchema as ValibotSchema, GenericSchemaAsync as ValibotSchemaAsync, SafeParser as ValibotSafeParser, SafeParserAsync as ValibotSafeParserAsync } from 'valibot'
|
|
||||||
import type { StandardSchemaV1 } from '@standard-schema/spec'
|
import type { StandardSchemaV1 } from '@standard-schema/spec'
|
||||||
import type { Struct } from 'superstruct'
|
import type { Struct } from 'superstruct'
|
||||||
import type { FormError, FormEvent, FormEventType, FormSubmitEvent, FormErrorEvent, Form, ValidateReturnSchema } from '../../types/form'
|
import type { FormError, FormEvent, FormEventType, FormSubmitEvent, FormErrorEvent, Form, ValidateReturnSchema } from '../../types/form'
|
||||||
@@ -26,15 +22,10 @@ class FormException extends Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Schema = PropType<ZodSchema>
|
type Schema = PropType<StandardSchemaV1>
|
||||||
| PropType<YupObjectSchema<any>>
|
| PropType<YupObjectSchema<any>>
|
||||||
|
| PropType<Struct<any, any>>
|
||||||
| PropType<JoiSchema>
|
| PropType<JoiSchema>
|
||||||
| PropType<ValibotSchema30 | ValibotSchemaAsync30>
|
|
||||||
| PropType<ValibotSchema31 | ValibotSchemaAsync31>
|
|
||||||
| PropType<ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any>>
|
|
||||||
| PropType<ValibotSchema | ValibotSchemaAsync>
|
|
||||||
| PropType<ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>> | PropType<Struct<any, any>>
|
|
||||||
| PropType<StandardSchemaV1>
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
@@ -214,14 +205,6 @@ function isJoiError(error: any): error is JoiError {
|
|||||||
return error.isJoi === true
|
return error.isJoi === true
|
||||||
}
|
}
|
||||||
|
|
||||||
function isValibotSchema(schema: any): schema is ValibotSchema30 | ValibotSchemaAsync30 | ValibotSchema31 | ValibotSchemaAsync31 | ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any> | ValibotSchema | ValibotSchemaAsync | ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any> {
|
|
||||||
return '_parse' in schema || '_run' in schema || (typeof schema === 'function' && 'schema' in schema)
|
|
||||||
}
|
|
||||||
|
|
||||||
function isZodSchema(schema: any): schema is ZodSchema {
|
|
||||||
return schema.parse !== undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isStandardSchema(schema: any): schema is StandardSchemaV1 {
|
export function isStandardSchema(schema: any): schema is StandardSchemaV1 {
|
||||||
return '~standard' in schema
|
return '~standard' in schema
|
||||||
}
|
}
|
||||||
@@ -251,35 +234,6 @@ export async function validateStandardSchema(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function validateValibotSchema(
|
|
||||||
state: any,
|
|
||||||
schema: ValibotSchema30 | ValibotSchemaAsync30 | ValibotSchema31 | ValibotSchemaAsync31 | ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any> | ValibotSchema | ValibotSchemaAsync | ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>
|
|
||||||
): Promise<ValidateReturnSchema<typeof state>> {
|
|
||||||
const result = await ('_parse' in schema ? schema._parse(state) : '_run' in schema ? schema._run({ typed: false, value: state }, {}) : schema(state))
|
|
||||||
|
|
||||||
if (!result.issues || result.issues.length === 0) {
|
|
||||||
const output = ('output' in result
|
|
||||||
? result.output
|
|
||||||
: 'value' in result
|
|
||||||
? result.value
|
|
||||||
: null)
|
|
||||||
return {
|
|
||||||
errors: null,
|
|
||||||
result: output
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const errors = result.issues.map(issue => ({
|
|
||||||
path: issue.path?.map(item => item.key).join('.') || '',
|
|
||||||
message: issue.message
|
|
||||||
}))
|
|
||||||
|
|
||||||
return {
|
|
||||||
errors,
|
|
||||||
result: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function validateJoiSchema(
|
async function validateJoiSchema(
|
||||||
state: any,
|
state: any,
|
||||||
schema: JoiSchema
|
schema: JoiSchema
|
||||||
@@ -307,28 +261,6 @@ async function validateJoiSchema(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function validateZodSchema(
|
|
||||||
state: any,
|
|
||||||
schema: ZodSchema
|
|
||||||
): Promise<ValidateReturnSchema<typeof state>> {
|
|
||||||
const result = await schema.safeParseAsync(state)
|
|
||||||
if (result.success === false) {
|
|
||||||
const errors = result.error.issues.map(issue => ({
|
|
||||||
path: issue.path.join('.'),
|
|
||||||
message: issue.message
|
|
||||||
}))
|
|
||||||
|
|
||||||
return {
|
|
||||||
errors,
|
|
||||||
result: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
result: result.data,
|
|
||||||
errors: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function validateSuperstructSchema(state: any, schema: Struct<any, any>): Promise<ValidateReturnSchema<typeof state>> {
|
async function validateSuperstructSchema(state: any, schema: Struct<any, any>): Promise<ValidateReturnSchema<typeof state>> {
|
||||||
const [err, result] = schema.validate(state)
|
const [err, result] = schema.validate(state)
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -379,12 +311,8 @@ async function validateYupSchema(
|
|||||||
function parseSchema(state: any, schema: Schema): Promise<ValidateReturnSchema<typeof state>> {
|
function parseSchema(state: any, schema: Schema): Promise<ValidateReturnSchema<typeof state>> {
|
||||||
if (isStandardSchema(schema)) {
|
if (isStandardSchema(schema)) {
|
||||||
return validateStandardSchema(state, schema)
|
return validateStandardSchema(state, schema)
|
||||||
} else if (isZodSchema(schema)) {
|
|
||||||
return validateZodSchema(state, schema)
|
|
||||||
} else if (isJoiSchema(schema)) {
|
} else if (isJoiSchema(schema)) {
|
||||||
return validateJoiSchema(state, schema)
|
return validateJoiSchema(state, schema)
|
||||||
} else if (isValibotSchema(schema)) {
|
|
||||||
return validateValibotSchema(state, schema)
|
|
||||||
} else if (isYupSchema(schema)) {
|
} else if (isYupSchema(schema)) {
|
||||||
return validateYupSchema(state, schema)
|
return validateYupSchema(state, schema)
|
||||||
} else if (isSuperStructSchema(schema)) {
|
} else if (isSuperStructSchema(schema)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user