diff --git a/package.json b/package.json index 64642a17..e8881d88 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "joi": "^17.13.3", "nuxt": "^3.12.2", "release-it": "^17.4.0", - "valibot": "^0.30.0", + "valibot": "^0.33.0", "vitest": "^1.6.0", "vitest-environment-nuxt": "^1.0.0", "vue-tsc": "^2.0.22", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8316ad29..f4c52796 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -90,8 +90,8 @@ importers: specifier: ^17.4.0 version: 17.4.0(typescript@5.5.2) valibot: - specifier: ^0.30.0 - version: 0.30.0 + specifier: ^0.33.0 + version: 0.33.3 vitest: specifier: ^1.6.0 version: 1.6.0(@types/node@20.14.9)(happy-dom@14.12.3)(lightningcss@1.25.1)(sass@1.77.6)(terser@5.31.1) @@ -7010,6 +7010,9 @@ packages: valibot@0.30.0: resolution: {integrity: sha512-5POBdbSkM+3nvJ6ZlyQHsggisfRtyT4tVTo1EIIShs6qCdXJnyWU5TJ68vr8iTg5zpOLjXLRiBqNx+9zwZz/rA==} + valibot@0.33.3: + resolution: {integrity: sha512-/fuY1DlX8uiQ7aphlzrrI2DbG0YJk84JMgvz2qKpUIdXRNsS53varfo4voPjSrjUr5BSV2K0miSEJUOlA5fQFg==} + validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} @@ -16316,6 +16319,8 @@ snapshots: valibot@0.30.0: {} + valibot@0.33.3: {} + validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 diff --git a/src/runtime/types/form.ts b/src/runtime/types/form.ts index 9d33bc79..b189b57a 100644 --- a/src/runtime/types/form.ts +++ b/src/runtime/types/form.ts @@ -2,7 +2,7 @@ import type { ComputedRef, Ref } from 'vue' import type { ZodSchema } from 'zod' import type { Schema as JoiSchema } from 'joi' import type { ObjectSchema as YupObjectSchema } from 'yup' -import type { ObjectSchemaAsync as ValibotObjectSchema } from 'valibot' +import type { GenericSchema as ValibotSchema, GenericSchemaAsync as ValibotSchemaAsync, SafeParser as ValibotSafeParser, SafeParserAsync as ValibotSafeParserAsync } from 'valibot' import type { GetObjectField } from './utils' export interface Form { @@ -18,7 +18,8 @@ export interface Form { export type FormSchema> = | ZodSchema | YupObjectSchema - | ValibotObjectSchema + | ValibotSchema | ValibotSchemaAsync + | ValibotSafeParser | ValibotSafeParserAsync | JoiSchema export type FormInputEvents = 'input' | 'blur' | 'change' diff --git a/src/runtime/utils/form.ts b/src/runtime/utils/form.ts index cfa30778..0c76345b 100644 --- a/src/runtime/utils/form.ts +++ b/src/runtime/utils/form.ts @@ -1,7 +1,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 { ObjectSchemaAsync as ValibotObjectSchema } from 'valibot' +import type { GenericSchema as ValibotSchema, GenericSchemaAsync as ValibotSchemaAsync, SafeParser as ValibotSafeParser, SafeParserAsync as ValibotSafeParserAsync } from 'valibot' import type { FormError } from '../types/form' export function isYupSchema(schema: any): schema is YupObjectSchema { @@ -67,17 +67,18 @@ export async function getJoiErrors(state: any, schema: JoiSchema): Promise { - return schema._parse !== undefined +export function isValibotSchema(schema: any): schema is ValibotSchema | ValibotSchemaAsync | ValibotSafeParser | ValibotSafeParserAsync { + return '_run' in schema || (typeof schema === 'function' && 'schema' in schema) } -export async function getValibotError(state: any, schema: ValibotObjectSchema): Promise { - const result = await schema._parse(state) - if (result.issues) { - return result.issues.map(issue => ({ - name: issue.path?.map(p => p.key).join('.') || '', - message: issue.message - })) - } - return [] +export async function getValibotError( + state: any, + schema: ValibotSchema | ValibotSchemaAsync | ValibotSafeParser | ValibotSafeParserAsync +): Promise { + const result = await ('_run' in schema ? schema._run({ typed: false, value: state }, {}) : schema(state)) + return result.issues?.map(issue => ({ + // We know that the key for a form schema is always a string or a number + name: issue.path?.map((item: any) => item.key).join('.') || '', + message: issue.message + })) || [] } diff --git a/test/components/Form.spec.ts b/test/components/Form.spec.ts index a2c21f8b..77368213 100644 --- a/test/components/Form.spec.ts +++ b/test/components/Form.spec.ts @@ -106,14 +106,19 @@ describe('Form', () => { } ], ['valibot', { - schema: valibot.objectAsync({ + schema: valibot.object({ email: valibot.string(), - password: valibot.string([ - valibot.minLength(8, 'Must be at least 8 characters') - ]) + password: valibot.pipe(valibot.string(), valibot.minLength(8, 'Must be at least 8 characters')) }) } ], + ['valibot safeParser', { + schema: valibot.safeParser(valibot.object({ + email: valibot.string(), + password: valibot.pipe(valibot.string(), valibot.minLength(8, 'Must be at least 8 characters')) + })) + } + ], ['custom', { async validate(state: any) { const errs = [] diff --git a/test/components/__snapshots__/Form.spec.ts.snap b/test/components/__snapshots__/Form.spec.ts.snap index 7c4ae5d8..15d28f78 100644 --- a/test/components/__snapshots__/Form.spec.ts.snap +++ b/test/components/__snapshots__/Form.spec.ts.snap @@ -128,6 +128,68 @@ exports[`Form > renders with default slot correctly 1`] = `"
"`; +exports[`Form > valibot safeParser validation works > with error 1`] = ` +"
+
+
+ + +
+
+
+ + +
+ +
+
+
+
+ + +
+
+
+ + +
+

Must be at least 8 characters

+
+
+
" +`; + +exports[`Form > valibot safeParser validation works > without error 1`] = ` +"
+
+
+ + +
+
+
+ + +
+ +
+
+
+
+ + +
+
+
+ + +
+ +
+
+
" +`; + exports[`Form > valibot validation works > with error 1`] = ` "