feat(Form): add standard schema support (#2880)

This commit is contained in:
Gerben Mulder
2025-02-05 09:27:51 +01:00
committed by GitHub
parent 0462edb84e
commit 9c36d37b84
3 changed files with 43 additions and 1 deletions

View File

@@ -58,6 +58,7 @@
"devDependencies": { "devDependencies": {
"@nuxt/eslint-config": "^1.0.0", "@nuxt/eslint-config": "^1.0.0",
"@nuxt/module-builder": "^0.8.4", "@nuxt/module-builder": "^0.8.4",
"@standard-schema/spec": "^1.0.0",
"@nuxt/test-utils": "^3.15.4", "@nuxt/test-utils": "^3.15.4",
"@release-it/conventional-changelog": "^10.0.0", "@release-it/conventional-changelog": "^10.0.0",
"@vue/test-utils": "^2.4.6", "@vue/test-utils": "^2.4.6",

8
pnpm-lock.yaml generated
View File

@@ -95,6 +95,9 @@ importers:
'@release-it/conventional-changelog': '@release-it/conventional-changelog':
specifier: ^10.0.0 specifier: ^10.0.0
version: 10.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.0.0)(release-it@18.1.2(@types/node@22.13.0)(typescript@5.6.3)) version: 10.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.0.0)(release-it@18.1.2(@types/node@22.13.0)(typescript@5.6.3))
'@standard-schema/spec':
specifier: ^1.0.0
version: 1.0.0
'@vue/test-utils': '@vue/test-utils':
specifier: ^2.4.6 specifier: ^2.4.6
version: 2.4.6 version: 2.4.6
@@ -1678,6 +1681,9 @@ packages:
'@socket.io/component-emitter@3.1.2': '@socket.io/component-emitter@3.1.2':
resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==}
'@standard-schema/spec@1.0.0':
resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==}
'@stylistic/eslint-plugin@3.0.1': '@stylistic/eslint-plugin@3.0.1':
resolution: {integrity: sha512-rQ3tcT5N2cynofJfbjUsnL4seoewTaOVBLyUEwtNldo7iNMPo3h/GUQk+Cl3iHEWwRxjq2wuH6q0FufQrbVL1A==} resolution: {integrity: sha512-rQ3tcT5N2cynofJfbjUsnL4seoewTaOVBLyUEwtNldo7iNMPo3h/GUQk+Cl3iHEWwRxjq2wuH6q0FufQrbVL1A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -8547,6 +8553,8 @@ snapshots:
'@socket.io/component-emitter@3.1.2': {} '@socket.io/component-emitter@3.1.2': {}
'@standard-schema/spec@1.0.0': {}
'@stylistic/eslint-plugin@3.0.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.6.3)': '@stylistic/eslint-plugin@3.0.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.6.3)':
dependencies: dependencies:
'@typescript-eslint/utils': 8.22.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.6.3) '@typescript-eslint/utils': 8.22.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.6.3)

View File

@@ -13,6 +13,7 @@ import type { ObjectSchema as YupObjectSchema, ValidationError as YupError } fro
import type { BaseSchema as ValibotSchema30, BaseSchemaAsync as ValibotSchemaAsync30 } from 'valibot30' 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 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 { GenericSchema as ValibotSchema, GenericSchemaAsync as ValibotSchemaAsync, SafeParser as ValibotSafeParser, SafeParserAsync as ValibotSafeParserAsync } from 'valibot'
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'
import { useId } from '#imports' import { useId } from '#imports'
@@ -33,6 +34,7 @@ type Schema = PropType<ZodSchema>
| PropType<ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any>> | PropType<ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any>>
| PropType<ValibotSchema | ValibotSchemaAsync> | PropType<ValibotSchema | ValibotSchemaAsync>
| PropType<ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>> | PropType<Struct<any, any>> | PropType<ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>> | PropType<Struct<any, any>>
| PropType<StandardSchemaV1>
export default defineComponent({ export default defineComponent({
props: { props: {
@@ -220,6 +222,35 @@ function isZodSchema(schema: any): schema is ZodSchema {
return schema.parse !== undefined return schema.parse !== undefined
} }
export function isStandardSchema(schema: any): schema is StandardSchemaV1 {
return '~standard' in schema
}
export async function validateStandardSchema(
state: any,
schema: StandardSchemaV1
): Promise<ValidateReturnSchema<typeof state>> {
const result = await schema['~standard'].validate(state)
if (!result.issues || result.issues.length === 0) {
const output = ('value' in result ? result.value : null)
return {
errors: null,
result: output
}
}
const errors = result.issues.map(issue => ({
path: issue.path?.map(item => typeof item === 'object' ? item.key : item).join('.') || '',
message: issue.message
}))
return {
errors,
result: null
}
}
async function validateValibotSchema( async function validateValibotSchema(
state: any, state: any,
schema: ValibotSchema30 | ValibotSchemaAsync30 | ValibotSchema31 | ValibotSchemaAsync31 | ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any> | ValibotSchema | ValibotSchemaAsync | ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any> schema: ValibotSchema30 | ValibotSchemaAsync30 | ValibotSchema31 | ValibotSchemaAsync31 | ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any> | ValibotSchema | ValibotSchemaAsync | ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>
@@ -346,7 +377,9 @@ async function validateYupSchema(
} }
function parseSchema(state: any, schema: Schema): Promise<ValidateReturnSchema<typeof state>> { function parseSchema(state: any, schema: Schema): Promise<ValidateReturnSchema<typeof state>> {
if (isZodSchema(schema)) { if (isStandardSchema(schema)) {
return validateStandardSchema(state, schema)
} else if (isZodSchema(schema)) {
return validateZodSchema(state, schema) return validateZodSchema(state, schema)
} else if (isJoiSchema(schema)) { } else if (isJoiSchema(schema)) {
return validateJoiSchema(state, schema) return validateJoiSchema(state, schema)