diff --git a/packages/docs/loaders/get-llm-text.ts b/packages/docs/loaders/get-llm-text.ts index 2b44bbc6b2..27d7ff30e9 100644 --- a/packages/docs/loaders/get-llm-text.ts +++ b/packages/docs/loaders/get-llm-text.ts @@ -13,7 +13,7 @@ const processor = remark().use(remarkMdx).use(remarkInclude).use(remarkGfm).use( export async function getLLMText(page: InferPageType): Promise { const filePath = page.data._file.absolutePath; const fileContent = await fs.readFile(filePath); - const { content, data } = matter(fileContent.toString()); + const { content } = matter(fileContent.toString()); const processed = await processor.process({ path: filePath, diff --git a/packages/zod/src/v4/classic/tests/to-json-schema.test.ts b/packages/zod/src/v4/classic/tests/to-json-schema.test.ts index 1e242235b1..c0a206b2f1 100644 --- a/packages/zod/src/v4/classic/tests/to-json-schema.test.ts +++ b/packages/zod/src/v4/classic/tests/to-json-schema.test.ts @@ -653,6 +653,24 @@ describe("toJSONSchema", () => { }); test("tuple", () => { + const schema = z.tuple([z.string(), z.number()]); + expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(` + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "prefixItems": [ + { + "type": "string", + }, + { + "type": "number", + }, + ], + "type": "array", + } + `); + }); + + test("tuple with rest", () => { const schema = z.tuple([z.string(), z.number()]).rest(z.boolean()); expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(` { @@ -673,6 +691,46 @@ describe("toJSONSchema", () => { `); }); + test("tuple openapi", () => { + const schema = z.tuple([z.string(), z.number()]); + expect(z.toJSONSchema(schema, { target: "openapi-3.0" })).toMatchInlineSnapshot(` + { + "items": [ + { + "type": "string", + }, + { + "type": "number", + }, + ], + "maxItems": 2, + "minItems": 2, + "type": "array", + } + `); + }); + + test("tuple with rest openapi", () => { + const schema = z.tuple([z.string(), z.number()]).rest(z.boolean()); + expect(z.toJSONSchema(schema, { target: "openapi-3.0" })).toMatchInlineSnapshot(` + { + "items": [ + { + "type": "string", + }, + { + "type": "number", + }, + { + "type": "boolean", + }, + ], + "minItems": 2, + "type": "array", + } + `); + }); + test("promise", () => { const schema = z.promise(z.string()); expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(` diff --git a/packages/zod/src/v4/core/to-json-schema.ts b/packages/zod/src/v4/core/to-json-schema.ts index 315e15faf6..a18b2fcdc6 100644 --- a/packages/zod/src/v4/core/to-json-schema.ts +++ b/packages/zod/src/v4/core/to-json-schema.ts @@ -371,32 +371,34 @@ export class JSONSchemaGenerator { const prefixItems = def.items.map((x, i) => this.process(x, { ...params, path: [...params.path, "prefixItems", i] }) ); + const rest = def.rest + ? this.process(def.rest, { + ...params, + path: [...params.path, "items"], + }) + : null; + if (this.target === "draft-2020-12") { json.prefixItems = prefixItems; + if (rest) { + json.items = rest; + } + } else if (this.target === "openapi-3.0") { + json.items = [...prefixItems]; + if (rest) { + json.items.push(rest); + } + json.minItems = prefixItems.length; + if (!rest) { + json.maxItems = prefixItems.length; + } } else { json.items = prefixItems; - } - - if (def.rest) { - const rest = this.process(def.rest, { - ...params, - path: [...params.path, "items"], - }); - if (this.target === "draft-2020-12") { - json.items = rest; - } else { + if (rest) { json.additionalItems = rest; } } - // additionalItems - if (def.rest) { - json.items = this.process(def.rest, { - ...params, - path: [...params.path, "items"], - }); - } - // length const { minimum, maximum } = schema._zod.bag as { minimum?: number;