Skip to content

Commit c75bc88

Browse files
test(compat): move zod-compat tests to zodCompat.test.ts; tighten normalizeRawShapeSchema guard to require ~standard.jsonSchema
1 parent 7e80880 commit c75bc88

3 files changed

Lines changed: 45 additions & 38 deletions

File tree

packages/core/src/util/zodCompat.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import * as z from 'zod/v4';
88

99
import type { StandardSchemaV1, StandardSchemaWithJSON } from './standardSchema.js';
10-
import { isStandardSchema } from './standardSchema.js';
10+
import { isStandardSchema, isStandardSchemaWithJSON } from './standardSchema.js';
1111

1212
function isZodSchema(v: unknown): v is z.ZodType {
1313
if (typeof v !== 'object' || v === null) return false;
@@ -45,9 +45,9 @@ export function normalizeRawShapeSchema(
4545
if (isZodRawShape(schema)) {
4646
return z.object(schema) as StandardSchemaWithJSON;
4747
}
48-
if (!isStandardSchema(schema)) {
48+
if (!isStandardSchemaWithJSON(schema)) {
4949
throw new TypeError(
50-
'inputSchema/outputSchema/argsSchema must be a Standard Schema (e.g. z.object({...})) or a raw Zod shape ({ field: z.string() }).'
50+
'inputSchema/outputSchema/argsSchema must be a Standard Schema with JSON Schema export (`~standard.jsonSchema`, e.g. z.object({...}) from zod >=4.2.0) or a raw Zod shape ({ field: z.string() }).'
5151
);
5252
}
5353
return schema;

packages/core/test/util/standardSchema.test.ts

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,6 @@
11
import * as z from 'zod/v4';
22

33
import { standardSchemaToJsonSchema } from '../../src/util/standardSchema.js';
4-
import { isZodRawShape, normalizeRawShapeSchema } from '../../src/util/zodCompat.js';
5-
6-
describe('isZodRawShape', () => {
7-
test('treats empty object as a raw shape (matches v1)', () => {
8-
expect(isZodRawShape({})).toBe(true);
9-
});
10-
test('detects raw shape with zod fields', () => {
11-
expect(isZodRawShape({ a: z.string() })).toBe(true);
12-
});
13-
test('rejects a Standard Schema instance', () => {
14-
expect(isZodRawShape(z.object({ a: z.string() }))).toBe(false);
15-
});
16-
test('rejects a shape with non-Zod Standard Schema fields', () => {
17-
const nonZod = { '~standard': { version: 1, vendor: 'arktype', validate: () => ({ value: 'x' }) } };
18-
expect(isZodRawShape({ a: nonZod })).toBe(false);
19-
});
20-
});
21-
22-
describe('normalizeRawShapeSchema', () => {
23-
test('wraps empty raw shape into z.object({})', () => {
24-
const wrapped = normalizeRawShapeSchema({});
25-
expect(wrapped).toBeDefined();
26-
expect(standardSchemaToJsonSchema(wrapped!, 'input').type).toBe('object');
27-
});
28-
test('passes through an already-wrapped Standard Schema unchanged', () => {
29-
const schema = z.object({ a: z.string() });
30-
expect(normalizeRawShapeSchema(schema)).toBe(schema);
31-
});
32-
test('returns undefined for undefined input', () => {
33-
expect(normalizeRawShapeSchema(undefined)).toBeUndefined();
34-
});
35-
test('throws TypeError for an invalid object that is neither raw shape nor Standard Schema', () => {
36-
expect(() => normalizeRawShapeSchema({ a: 'not a zod schema' } as never)).toThrow(TypeError);
37-
});
38-
});
394

405
describe('standardSchemaToJsonSchema', () => {
416
test('emits type:object for plain z.object schemas', () => {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import * as z from 'zod/v4';
2+
3+
import { standardSchemaToJsonSchema } from '../../src/util/standardSchema.js';
4+
import { isZodRawShape, normalizeRawShapeSchema } from '../../src/util/zodCompat.js';
5+
6+
describe('isZodRawShape', () => {
7+
test('treats empty object as a raw shape (matches v1)', () => {
8+
expect(isZodRawShape({})).toBe(true);
9+
});
10+
test('detects raw shape with zod fields', () => {
11+
expect(isZodRawShape({ a: z.string() })).toBe(true);
12+
});
13+
test('rejects a Standard Schema instance', () => {
14+
expect(isZodRawShape(z.object({ a: z.string() }))).toBe(false);
15+
});
16+
test('rejects a shape with non-Zod Standard Schema fields', () => {
17+
const nonZod = { '~standard': { version: 1, vendor: 'arktype', validate: () => ({ value: 'x' }) } };
18+
expect(isZodRawShape({ a: nonZod })).toBe(false);
19+
});
20+
});
21+
22+
describe('normalizeRawShapeSchema', () => {
23+
test('wraps empty raw shape into z.object({})', () => {
24+
const wrapped = normalizeRawShapeSchema({});
25+
expect(wrapped).toBeDefined();
26+
expect(standardSchemaToJsonSchema(wrapped!, 'input').type).toBe('object');
27+
});
28+
test('passes through an already-wrapped Standard Schema unchanged', () => {
29+
const schema = z.object({ a: z.string() });
30+
expect(normalizeRawShapeSchema(schema)).toBe(schema);
31+
});
32+
test('returns undefined for undefined input', () => {
33+
expect(normalizeRawShapeSchema(undefined)).toBeUndefined();
34+
});
35+
test('throws TypeError for an invalid object that is neither raw shape nor Standard Schema', () => {
36+
expect(() => normalizeRawShapeSchema({ a: 'not a zod schema' } as never)).toThrow(TypeError);
37+
});
38+
test('throws TypeError for a Standard Schema without JSON Schema export', () => {
39+
const noJson = { '~standard': { version: 1, vendor: 'x', validate: () => ({ value: {} }) } };
40+
expect(() => normalizeRawShapeSchema(noJson as never)).toThrow(/~standard\.jsonSchema/);
41+
});
42+
});

0 commit comments

Comments
 (0)