|
| 1 | +import type { StandardSchemaV1 } from '@standard-schema/spec' |
1 | 2 | import * as v from 'valibot' |
2 | 3 | import { describe, expect, it } from 'vitest' |
3 | 4 | import { argsToJsonSchema, returnToJsonSchema } from '../to-json-schema' |
4 | 5 |
|
5 | 6 | const PERMISSIVE = { type: 'object', additionalProperties: true } |
6 | 7 |
|
| 8 | +/** A Standard Schema that also implements the Standard JSON Schema converter (like zod 4). */ |
| 9 | +function withJsonSchema(json: Record<string, unknown>): StandardSchemaV1 { |
| 10 | + return { |
| 11 | + '~standard': { |
| 12 | + version: 1, |
| 13 | + vendor: 'test', |
| 14 | + validate: (value: unknown) => ({ value }), |
| 15 | + jsonSchema: { |
| 16 | + input: () => json, |
| 17 | + output: () => json, |
| 18 | + }, |
| 19 | + } as StandardSchemaV1['~standard'], |
| 20 | + } |
| 21 | +} |
| 22 | + |
7 | 23 | describe('argsToJsonSchema', () => { |
8 | | - it('returns an empty object schema when no args', async () => { |
9 | | - const { schema, unwrapped } = await argsToJsonSchema(undefined) |
| 24 | + it('returns an empty object schema when no args', () => { |
| 25 | + const { schema, unwrapped } = argsToJsonSchema(undefined) |
10 | 26 | expect(unwrapped).toBe(false) |
11 | 27 | expect(schema).toEqual({ type: 'object', properties: {} }) |
12 | 28 | }) |
13 | 29 |
|
14 | | - it('advertises each positional arg under arg0/arg1/... with precise per-vendor conversion', async () => { |
15 | | - const { schema, unwrapped } = await argsToJsonSchema([v.string(), v.number()]) |
16 | | - expect(unwrapped).toBe(false) |
17 | | - expect(schema).toMatchObject({ |
18 | | - type: 'object', |
19 | | - required: ['arg0', 'arg1'], |
20 | | - additionalProperties: false, |
21 | | - }) |
22 | | - const props = (schema as any).properties |
23 | | - // valibot vendor → precise conversion via @standard-community/standard-json. |
24 | | - expect(props.arg0).toMatchObject({ type: 'string' }) |
25 | | - expect(props.arg1).toMatchObject({ type: 'number' }) |
| 30 | + it('uses the schema\'s own Standard JSON Schema converter when present', () => { |
| 31 | + const { schema } = argsToJsonSchema([withJsonSchema({ type: 'string' })]) |
| 32 | + expect((schema as any).properties.arg0).toEqual({ type: 'string' }) |
26 | 33 | }) |
27 | 34 |
|
28 | | - it('falls back to a permissive object for vendors without a converter', async () => { |
29 | | - const foreign = { |
30 | | - '~standard': { version: 1 as const, vendor: 'acme', validate: (value: unknown) => ({ value }) }, |
31 | | - } |
32 | | - const { schema } = await argsToJsonSchema([foreign]) |
| 35 | + it('falls back to a permissive object for validators without a native converter (valibot)', () => { |
| 36 | + const { schema } = argsToJsonSchema([v.string(), v.number()]) |
33 | 37 | expect((schema as any).properties.arg0).toEqual(PERMISSIVE) |
| 38 | + expect((schema as any).properties.arg1).toEqual(PERMISSIVE) |
| 39 | + expect(schema).toMatchObject({ type: 'object', required: ['arg0', 'arg1'], additionalProperties: false }) |
34 | 40 | }) |
35 | 41 | }) |
36 | 42 |
|
37 | 43 | describe('returnToJsonSchema', () => { |
38 | | - it('returns undefined when no schema is provided', async () => { |
39 | | - expect(await returnToJsonSchema(undefined)).toBeUndefined() |
| 44 | + it('returns undefined when no schema is provided', () => { |
| 45 | + expect(returnToJsonSchema(undefined)).toBeUndefined() |
| 46 | + }) |
| 47 | + |
| 48 | + it('uses the native converter when present', () => { |
| 49 | + expect(returnToJsonSchema(withJsonSchema({ type: 'object', properties: { ok: { type: 'boolean' } } }))) |
| 50 | + .toEqual({ type: 'object', properties: { ok: { type: 'boolean' } } }) |
40 | 51 | }) |
41 | 52 |
|
42 | | - it('converts a declared return schema precisely for known vendors', async () => { |
43 | | - const schema = await returnToJsonSchema(v.object({ ok: v.boolean() })) |
44 | | - expect((schema as any).type).toBe('object') |
45 | | - expect((schema as any).properties.ok).toMatchObject({ type: 'boolean' }) |
| 53 | + it('falls back to permissive for validators without a native converter', () => { |
| 54 | + expect(returnToJsonSchema(v.object({ ok: v.boolean() }))).toEqual(PERMISSIVE) |
46 | 55 | }) |
47 | 56 | }) |
0 commit comments