diff --git a/.changeset/fix-5110-arktype-compat.md b/.changeset/fix-5110-arktype-compat.md new file mode 100644 index 000000000..b195a9b26 --- /dev/null +++ b/.changeset/fix-5110-arktype-compat.md @@ -0,0 +1,5 @@ +--- +"vee-validate": patch +--- + +Fix standard schema validation compatibility with arktype (#5110) diff --git a/packages/vee-validate/src/utils/assertions.ts b/packages/vee-validate/src/utils/assertions.ts index 9e177abbc..c790d163a 100644 --- a/packages/vee-validate/src/utils/assertions.ts +++ b/packages/vee-validate/src/utils/assertions.ts @@ -10,7 +10,11 @@ export function isLocator(value: unknown): value is Locator { } export function isStandardSchema(value: unknown): value is StandardSchemaV1 { - return isObject(value) && '~standard' in (value as unknown as StandardSchemaV1); + return ( + !!value && + (typeof value === 'object' || typeof value === 'function') && + '~standard' in (value as Record) + ); } export function hasCheckedAttr(type: unknown) { diff --git a/packages/vee-validate/tests/utils/assertions.spec.ts b/packages/vee-validate/tests/utils/assertions.spec.ts index ad6b9122c..7ed7e1030 100644 --- a/packages/vee-validate/tests/utils/assertions.spec.ts +++ b/packages/vee-validate/tests/utils/assertions.spec.ts @@ -1,4 +1,4 @@ -import { isEqual } from 'packages/vee-validate/src/utils'; +import { isEqual, isStandardSchema } from 'packages/vee-validate/src/utils'; describe('assertions', () => { test('equal objects are equal', () => { @@ -229,3 +229,60 @@ describe('assertions', () => { expect(isEqual(a6, b2)).toBe(false); }); }); + +// #5110 - arktype compatibility +describe('isStandardSchema', () => { + test('detects a plain object with ~standard property as a standard schema', () => { + const schema = { + '~standard': { + version: 1, + vendor: 'test', + validate: (value: unknown) => ({ value }), + }, + }; + + expect(isStandardSchema(schema)).toBe(true); + }); + + test('detects a callable object with ~standard property as a standard schema (like arktype)', () => { + // Arktype schemas are functions that also have the ~standard property + const callableSchema = Object.assign( + function (value: unknown) { + return value; + }, + { + '~standard': { + version: 1, + vendor: 'arktype', + validate: (value: unknown) => ({ value }), + }, + }, + ); + + expect(isStandardSchema(callableSchema)).toBe(true); + }); + + test('returns false for a plain function without ~standard', () => { + const fn = (value: unknown) => value; + expect(isStandardSchema(fn)).toBe(false); + }); + + test('returns false for primitive values', () => { + expect(isStandardSchema(null)).toBe(false); + expect(isStandardSchema(undefined)).toBe(false); + expect(isStandardSchema('')).toBe(false); + expect(isStandardSchema('required')).toBe(false); + expect(isStandardSchema(0)).toBe(false); + expect(isStandardSchema(true)).toBe(false); + }); + + test('returns false for arrays', () => { + expect(isStandardSchema([])).toBe(false); + expect(isStandardSchema([() => true])).toBe(false); + }); + + test('returns false for plain objects without ~standard', () => { + expect(isStandardSchema({})).toBe(false); + expect(isStandardSchema({ required: true })).toBe(false); + }); +});