diff --git a/.changeset/fix-bigint-json-schema.md b/.changeset/fix-bigint-json-schema.md new file mode 100644 index 0000000..aa5cde8 --- /dev/null +++ b/.changeset/fix-bigint-json-schema.md @@ -0,0 +1,5 @@ +--- +"incur": patch +--- + +Fixed `z.bigint()`, `z.coerce.bigint()`, `z.date()`, and `z.coerce.date()` schemas failing during skill sync by representing them as `{ type: "string" }` in JSON Schema output. diff --git a/src/Schema.test.ts b/src/Schema.test.ts index 09d8afc..593a147 100644 --- a/src/Schema.test.ts +++ b/src/Schema.test.ts @@ -97,6 +97,35 @@ describe('toJsonSchema', () => { }) }) + test('converts z.bigint() as string', () => { + expect(Schema.toJsonSchema(z.bigint())).toEqual({ type: 'string' }) + }) + + test('converts z.coerce.bigint() as string', () => { + expect(Schema.toJsonSchema(z.coerce.bigint())).toEqual({ type: 'string' }) + }) + + test('converts z.object() with bigint field', () => { + expect( + Schema.toJsonSchema(z.object({ amount: z.coerce.bigint().describe('Token amount') })), + ).toEqual({ + type: 'object', + properties: { + amount: { type: 'string', description: 'Token amount' }, + }, + required: ['amount'], + additionalProperties: false, + }) + }) + + test('converts z.date() as string', () => { + expect(Schema.toJsonSchema(z.date())).toEqual({ type: 'string' }) + }) + + test('converts z.coerce.date() as string', () => { + expect(Schema.toJsonSchema(z.coerce.date())).toEqual({ type: 'string' }) + }) + test('full object with optional, default, and describe', () => { const result = Schema.toJsonSchema( z.object({ diff --git a/src/Schema.ts b/src/Schema.ts index 85704c4..e0dd404 100644 --- a/src/Schema.ts +++ b/src/Schema.ts @@ -1,8 +1,18 @@ import { z } from 'zod' -/** Converts a Zod schema to a JSON Schema object. Strips the `$schema` meta-property. */ +/** + * Converts a Zod schema to a JSON Schema object. Strips the `$schema` + * meta-property. Represents bigints and dates as `{ type: "string" }` + * since JSON lacks native types for them. + */ export function toJsonSchema(schema: z.ZodType): Record { - const result = z.toJSONSchema(schema) as Record + const result = z.toJSONSchema(schema, { + unrepresentable: 'any', + override: (ctx) => { + const type = ctx.zodSchema._zod?.def?.type + if (type === 'bigint' || type === 'date') ctx.jsonSchema.type = 'string' + }, + }) as Record delete result.$schema return result }