From 0478ca97f8250a652eb0afac7cdb0f4356b21311 Mon Sep 17 00:00:00 2001 From: Hasegawa-Yukihiro Date: Sun, 21 Jul 2024 15:26:28 +0900 Subject: [PATCH 1/2] fix: use schema types for path params --- lib/src/getZodiosEndpointDefinitionList.ts | 37 +------ lib/src/openApiToZod.ts | 116 +++++++++++++-------- 2 files changed, 79 insertions(+), 74 deletions(-) diff --git a/lib/src/getZodiosEndpointDefinitionList.ts b/lib/src/getZodiosEndpointDefinitionList.ts index c572068..920924e 100644 --- a/lib/src/getZodiosEndpointDefinitionList.ts +++ b/lib/src/getZodiosEndpointDefinitionList.ts @@ -17,7 +17,7 @@ import type { CodeMeta, ConversionTypeContext } from "./CodeMeta"; import { getOpenApiDependencyGraph } from "./getOpenApiDependencyGraph"; import { isReferenceObject } from "./isReferenceObject"; import { makeSchemaResolver } from "./makeSchemaResolver"; -import { getZodChain, getZodSchema } from "./openApiToZod"; +import { getZodSchema } from "./openApiToZod"; import { getSchemaComplexity } from "./schema-complexity"; import type { TemplateContext } from "./template-context"; import { @@ -202,14 +202,7 @@ export const getZodiosEndpointDefinitionList = (doc: OpenAPIObject, options?: Te name: "body", type: "Body", description: requestBody.description!, - schema: - getZodVarName(bodyCode, operationName + "_Body") + - getZodChain({ - schema: isReferenceObject(bodySchema) - ? ctx.resolver.getSchemaByRef(bodySchema.$ref) - : bodySchema, - meta: bodyCode.meta, - }), + schema: getZodVarName(bodyCode, operationName + "_Body"), }); } } @@ -275,13 +268,7 @@ export const getZodiosEndpointDefinitionList = (doc: OpenAPIObject, options?: Te .with("query", () => "Query") .with("path", () => "Path") .run() as "Header" | "Query" | "Path", - schema: getZodVarName( - paramCode.assign( - paramCode.toString() + - getZodChain({ schema: paramSchema, meta: paramCode.meta, options }) - ), - paramItem.name - ), + schema: getZodVarName(paramCode.assign(paramCode.toString()), paramItem.name), }); } } @@ -307,14 +294,7 @@ export const getZodiosEndpointDefinitionList = (doc: OpenAPIObject, options?: Te if (maybeSchema) { schema = getZodSchema({ schema: maybeSchema, ctx, meta: { isRequired: true }, options }); - schemaString = - (schema.ref ? getZodVarName(schema) : schema.toString()) + - getZodChain({ - schema: isReferenceObject(maybeSchema) - ? ctx.resolver.getSchemaByRef(maybeSchema.$ref) - : maybeSchema, - meta: schema.meta, - }); + schemaString = schema.ref ? getZodVarName(schema) : schema.toString(); } if (endpointDefinition.responses !== undefined) { @@ -363,14 +343,7 @@ export const getZodiosEndpointDefinitionList = (doc: OpenAPIObject, options?: Te if (maybeSchema) { schema = getZodSchema({ schema: maybeSchema, ctx, meta: { isRequired: true }, options }); - schemaString = - (schema.ref ? getZodVarName(schema) : schema.toString()) + - getZodChain({ - schema: isReferenceObject(maybeSchema) - ? ctx.resolver.getSchemaByRef(maybeSchema.$ref) - : maybeSchema, - meta: schema.meta, - }); + schemaString = schema.ref ? getZodVarName(schema) : schema.toString(); } if (schemaString) { diff --git a/lib/src/openApiToZod.ts b/lib/src/openApiToZod.ts index 2bd35d2..1790519 100644 --- a/lib/src/openApiToZod.ts +++ b/lib/src/openApiToZod.ts @@ -99,9 +99,15 @@ export function getZodSchema({ schema: $schema, ctx, meta: inheritedMeta, option .join(", ")}]) `); } - + const chain = getZodChain({ + schema, + meta: { ...code.meta, isRequired: code.meta.isRequired ?? true }, + options, + }); return code.assign( - `z.union([${schema.oneOf.map((prop) => getZodSchema({ schema: prop, ctx, meta, options })).join(", ")}])` + `z.union([${schema.oneOf + .map((prop) => getZodSchema({ schema: prop, ctx, meta, options })) + .join(", ")}])${chain}` ); } @@ -129,8 +135,12 @@ export function getZodSchema({ schema: $schema, ctx, meta: inheritedMeta, option return type.toString(); }) .join(", "); - - return code.assign(`z.union([${types}])`); + const chain = getZodChain({ + schema, + meta: { ...code.meta, isRequired: code.meta.isRequired ?? true }, + options, + }); + return code.assign(`z.union([${types}])${chain}`); } if (schema.allOf) { @@ -167,17 +177,24 @@ export function getZodSchema({ schema: $schema, ctx, meta: inheritedMeta, option const schemaType = schema.type ? (schema.type.toLowerCase() as NonNullable) : undefined; if (schemaType && isPrimitiveType(schemaType)) { + const chain = getZodChain({ + schema, + meta: { ...code.meta, isRequired: code.meta.isRequired ?? true }, + options, + }); if (schema.enum) { if (schemaType === "string") { if (schema.enum.length === 1) { const value = schema.enum[0]; const valueString = value === null ? "null" : `"${value}"`; - return code.assign(`z.literal(${valueString})`); + return code.assign(`z.literal(${valueString})${chain}`); } // eslint-disable-next-line sonarjs/no-nested-template-literals return code.assign( - `z.enum([${schema.enum.map((value) => (value === null ? "null" : `"${value}"`)).join(", ")}])` + `z.enum([${schema.enum + .map((value) => (value === null ? "null" : `"${value}"`)) + .join(", ")}])${chain}` ); } @@ -187,37 +204,42 @@ export function getZodSchema({ schema: $schema, ctx, meta: inheritedMeta, option if (schema.enum.length === 1) { const value = schema.enum[0]; - return code.assign(`z.literal(${value === null ? "null" : value})`); + return code.assign(`z.literal(${value === null ? "null" : value})${chain}`); } - return code.assign( // eslint-disable-next-line sonarjs/no-nested-template-literals - `z.union([${schema.enum.map((value) => `z.literal(${value === null ? "null" : value})`).join(", ")}])` + `z.union([${schema.enum + .map((value) => `z.literal(${value === null ? "null" : value})`) + .join(", ")}])${chain}` ); } - return code.assign( - match(schemaType) - .with("integer", () => "z.number()") - .with("string", () => - match(schema.format) - .with("binary", () => "z.instanceof(File)") - .otherwise(() => "z.string()") - ) - .otherwise((type) => `z.${type}()`) - ); + const type = match(schemaType) + .with("integer", () => "z.number()") + .with("string", () => + match(schema.format) + .with("binary", () => "z.instanceof(File)") + .otherwise(() => "z.string()") + ) + .otherwise((type) => `z.${type}()`); + return code.assign(type + chain); } const readonly = options?.allReadonly ? ".readonly()" : ""; if (schemaType === "array") { + const chain = getZodChain({ + schema, + meta: { ...code.meta, isRequired: code.meta.isRequired ?? true }, + options, + }); if (schema.items) { return code.assign( - `z.array(${getZodSchema({ schema: schema.items, ctx, meta, options }).toString()})${readonly}` + `z.array(${getZodSchema({ schema: schema.items, ctx, meta, options }).toString()})${readonly}${chain}` ); } - return code.assign(`z.array(z.any())${readonly}`); + return code.assign(`z.array(z.any())${readonly}${chain}`); } if (schemaType === "object" || schema.properties || schema.additionalProperties) { @@ -231,15 +253,18 @@ export function getZodSchema({ schema: $schema, ctx, meta: inheritedMeta, option const additionalPropsSchema = additionalProps === false ? "" : ".passthrough()"; if (typeof schema.additionalProperties === "object" && Object.keys(schema.additionalProperties).length > 0) { + const chain = getZodChain({ + schema, + meta: { ...code.meta, isRequired: code.meta.isRequired ?? true }, + options, + }); return code.assign( - `z.record(${( - getZodSchema({ schema: schema.additionalProperties, ctx, meta, options }) + - getZodChain({ - schema: schema.additionalProperties as SchemaObject, - meta: { ...meta, isRequired: true }, - options, - }) - ).toString()})` + `z.record(${getZodSchema({ + schema: schema.additionalProperties, + ctx, + meta, + options, + }).toString()})${chain}` ); } @@ -259,20 +284,17 @@ export function getZodSchema({ schema: $schema, ctx, meta: inheritedMeta, option name: prop, } as CodeMetaData; - let propActualSchema = propSchema; - + const zodSchema = getZodSchema({ schema: propSchema, ctx, meta: propMetadata, options }); if (isReferenceObject(propSchema) && ctx?.resolver) { - propActualSchema = ctx.resolver.getSchemaByRef(propSchema.$ref); - if (!propActualSchema) { - throw new Error(`Schema ${propSchema.$ref} not found`); - } + const chain = getZodChain({ + schema, + meta: propMetadata, + options, + }); + return [prop, zodSchema + chain]; } - const propCode = - getZodSchema({ schema: propSchema, ctx, meta: propMetadata, options }) + - getZodChain({ schema: propActualSchema as SchemaObject, meta: propMetadata, options }); - - return [prop, propCode.toString()]; + return [prop, zodSchema.toString()]; }); properties = @@ -283,10 +305,20 @@ export function getZodSchema({ schema: $schema, ctx, meta: inheritedMeta, option const partial = isPartial ? ".partial()" : ""; const strict = options?.strictObjects ? ".strict()" : ""; - return code.assign(`z.object(${properties})${partial}${strict}${additionalPropsSchema}${readonly}`); + const chain = getZodChain({ + schema, + meta: { ...code.meta, isRequired: code.meta.isRequired ?? true }, + options, + }); + return code.assign(`z.object(${properties})${partial}${strict}${additionalPropsSchema}${readonly}${chain}`); } - if (!schemaType) return code.assign("z.unknown()"); + const chain = getZodChain({ + schema, + meta: { ...code.meta, isRequired: code.meta.isRequired ?? true }, + options, + }); + if (!schemaType) return code.assign(`z.unknown()${chain}`); // eslint-disable-next-line @typescript-eslint/restrict-template-expressions throw new Error(`Unsupported schema type: ${schemaType}`); From 6a6d956744aba62ed0224c9f960e7a4e9e3c0277 Mon Sep 17 00:00:00 2001 From: Hasegawa-Yukihiro Date: Sun, 21 Jul 2024 15:27:59 +0900 Subject: [PATCH 2/2] test: update test --- lib/src/openApiToZod.test.ts | 30 ++++---- .../allOf-oneOf-anyOf-single-ref.test.ts | 10 +-- ...ody-with-chains-tag-group-strategy.test.ts | 7 +- lib/tests/enum-null.test.ts | 76 ++++++++++--------- lib/tests/export-all-types.test.ts | 18 ++--- lib/tests/invalid-pattern-regex.test.ts | 15 +--- ...chains-on-z-object-with-refs-props.test.ts | 50 ++++-------- lib/tests/missing-zod-chains.test.ts | 8 +- 8 files changed, 95 insertions(+), 119 deletions(-) diff --git a/lib/src/openApiToZod.test.ts b/lib/src/openApiToZod.test.ts index a24b3ab..4e52f57 100644 --- a/lib/src/openApiToZod.test.ts +++ b/lib/src/openApiToZod.test.ts @@ -15,7 +15,7 @@ test("getSchemaAsZodString", () => { expect(getSchemaAsZodString({ type: "boolean" })).toMatchInlineSnapshot('"z.boolean()"'); expect(getSchemaAsZodString({ type: "string" })).toMatchInlineSnapshot('"z.string()"'); expect(getSchemaAsZodString({ type: "number" })).toMatchInlineSnapshot('"z.number()"'); - expect(getSchemaAsZodString({ type: "integer" })).toMatchInlineSnapshot('"z.number()"'); + expect(getSchemaAsZodString({ type: "integer" })).toMatchInlineSnapshot('"z.number().int()"'); // expect(getSchemaAsZodString({ type: "string", format: "date-time" })).toMatchInlineSnapshot('"z.string().datetime()"'); // expect(getSchemaAsZodString({ type: "number", nullable: true, minimum: 0 })).toMatchInlineSnapshot('"z.number().nullable().gte(0)"'); @@ -161,8 +161,8 @@ test("getSchemaAsZodString", () => { type: "string", }, }, - } - ] + }, + ], }, { type: "object", @@ -180,11 +180,10 @@ test("getSchemaAsZodString", () => { }, }, }, - ] - } + ], + }, ], discriminator: { propertyName: "type" }, - }) ).toMatchInlineSnapshot(` " @@ -226,7 +225,7 @@ test("getSchemaAsZodString", () => { }, }, }, - ] + ], }, { type: "object", @@ -257,13 +256,14 @@ test("getSchemaAsZodString", () => { }, }, }, - ] - } + ], + }, ], discriminator: { propertyName: "type" }, - }) - ).toMatchInlineSnapshot('"z.union([z.object({ type: z.literal("a"), a: z.string() }).passthrough().and(z.object({ type: z.literal("c"), c: z.string() }).passthrough()), z.object({ type: z.literal("b"), b: z.string() }).passthrough().and(z.object({ type: z.literal("d"), d: z.string() }).passthrough())])"'); + ).toMatchInlineSnapshot( + '"z.union([z.object({ type: z.literal("a"), a: z.string() }).passthrough().and(z.object({ type: z.literal("c"), c: z.string() }).passthrough()), z.object({ type: z.literal("b"), b: z.string() }).passthrough().and(z.object({ type: z.literal("d"), d: z.string() }).passthrough())])"' + ); expect( getSchemaAsZodString({ @@ -272,9 +272,7 @@ test("getSchemaAsZodString", () => { anyOfExample: { anyOf: [{ type: "string" }, { type: "number" }] }, }, }) - ).toMatchInlineSnapshot( - '"z.object({ anyOfExample: z.union([z.string(), z.number()]) }).partial().passthrough()"' - ); + ).toMatchInlineSnapshot('"z.object({ anyOfExample: z.union([z.string(), z.number()]) }).partial().passthrough()"'); expect( getSchemaAsZodString({ @@ -296,14 +294,14 @@ test("getSchemaAsZodString", () => { }); test("getSchemaWithChainableAsZodString", () => { - expect(getSchemaAsZodString({ type: "string", nullable: true })).toMatchInlineSnapshot('"z.string()"'); + expect(getSchemaAsZodString({ type: "string", nullable: true })).toMatchInlineSnapshot('"z.string().nullable()"'); expect(getSchemaAsZodString({ type: "string", nullable: false })).toMatchInlineSnapshot('"z.string()"'); expect(getSchemaAsZodString({ type: "string", nullable: false }, { isRequired: true })).toMatchInlineSnapshot( '"z.string()"' ); expect(getSchemaAsZodString({ type: "string", nullable: true }, { isRequired: true })).toMatchInlineSnapshot( - '"z.string()"' + '"z.string().nullable()"' ); }); diff --git a/lib/tests/allOf-oneOf-anyOf-single-ref.test.ts b/lib/tests/allOf-oneOf-anyOf-single-ref.test.ts index 7f6fc96..49ee27b 100644 --- a/lib/tests/allOf-oneOf-anyOf-single-ref.test.ts +++ b/lib/tests/allOf-oneOf-anyOf-single-ref.test.ts @@ -56,13 +56,13 @@ test("allOf-single-ref", async () => { import { z } from "zod"; const MyComponent = z.enum(["one", "two", "three"]); - const allOf_ref_param = MyComponent.optional(); - + const allOf_ref_param = MyComponent; + export const schemas = { MyComponent, allOf_ref_param, }; - + const endpoints = makeApi([ { method: "get", @@ -88,9 +88,9 @@ test("allOf-single-ref", async () => { response: z.void(), }, ]); - + export const api = new Zodios(endpoints); - + export function createApiClient(baseUrl: string, options?: ZodiosOptions) { return new Zodios(baseUrl, endpoints, options); } diff --git a/lib/tests/array-body-with-chains-tag-group-strategy.test.ts b/lib/tests/array-body-with-chains-tag-group-strategy.test.ts index aa0d367..11b56ca 100644 --- a/lib/tests/array-body-with-chains-tag-group-strategy.test.ts +++ b/lib/tests/array-body-with-chains-tag-group-strategy.test.ts @@ -56,7 +56,10 @@ test("array-body-with-chains-tag-group-strategy", async () => { "Test": "import { makeApi, Zodios, type ZodiosOptions } from "@zodios/core"; import { z } from "zod"; - const putTest_Body = z.array(z.object({ testItem: z.string() }).partial()); + const putTest_Body = z + .array(z.object({ testItem: z.string() }).partial()) + .min(1) + .max(10); export const schemas = { putTest_Body, @@ -72,7 +75,7 @@ test("array-body-with-chains-tag-group-strategy", async () => { { name: "body", type: "Body", - schema: putTest_Body.min(1).max(10), + schema: putTest_Body, }, ], response: z.void(), diff --git a/lib/tests/enum-null.test.ts b/lib/tests/enum-null.test.ts index ba37750..08caa55 100644 --- a/lib/tests/enum-null.test.ts +++ b/lib/tests/enum-null.test.ts @@ -12,39 +12,39 @@ test("enum-null", async () => { }, components: { schemas: { - "Null1": { + Null1: { type: "string", enum: [null], }, - "Null2": { + Null2: { type: "string", enum: ["a", null], }, - "Null3": { + Null3: { type: "string", enum: ["a", null], - nullable: true + nullable: true, }, - "Null4": { + Null4: { type: "string", enum: [null], - nullable: true + nullable: true, }, - "Compound": { + Compound: { type: "object", properties: { - "field": { + field: { oneOf: [ - { $ref: '#/components/schemas/Null1' }, - { $ref: '#/components/schemas/Null2' }, - { $ref: '#/components/schemas/Null3' }, - { $ref: '#/components/schemas/Null4' }, - { type: "string" } - ] - } - } - } - } + { $ref: "#/components/schemas/Null1" }, + { $ref: "#/components/schemas/Null2" }, + { $ref: "#/components/schemas/Null3" }, + { $ref: "#/components/schemas/Null4" }, + { type: "string" }, + ], + }, + }, + }, + }, }, paths: { "/sample": { @@ -56,9 +56,9 @@ test("enum-null", async () => { "application/json": { schema: { $ref: "#/components/schemas/Null1", - } - } - } + }, + }, + }, }, "400": { description: "null with a string", @@ -66,9 +66,9 @@ test("enum-null", async () => { "application/json": { schema: { $ref: "#/components/schemas/Null2", - } - } - } + }, + }, + }, }, "401": { description: "null with a string and nullable", @@ -76,9 +76,9 @@ test("enum-null", async () => { "application/json": { schema: { $ref: "#/components/schemas/Null3", - } - } - } + }, + }, + }, }, "402": { description: "null with nullable", @@ -86,9 +86,9 @@ test("enum-null", async () => { "application/json": { schema: { $ref: "#/components/schemas/Null4", - } - } - } + }, + }, + }, }, "403": { description: "object that references null", @@ -96,9 +96,9 @@ test("enum-null", async () => { "application/json": { schema: { $ref: "#/components/schemas/Compound", - } - } - } + }, + }, + }, }, }, }, @@ -106,7 +106,11 @@ test("enum-null", async () => { }, }; - const output = await generateZodClientFromOpenAPI({ disableWriteToFile: true, openApiDoc, options: { shouldExportAllTypes: true } }); + const output = await generateZodClientFromOpenAPI({ + disableWriteToFile: true, + openApiDoc, + options: { shouldExportAllTypes: true }, + }); expect(output).toMatchInlineSnapshot(` "import { makeApi, Zodios, type ZodiosOptions } from "@zodios/core"; import { z } from "zod"; @@ -121,8 +125,8 @@ test("enum-null", async () => { const Null1 = z.literal(null); const Null2 = z.enum(["a", null]); - const Null3 = z.enum(["a", null]); - const Null4 = z.literal(null); + const Null3 = z.enum(["a", null]).nullable(); + const Null4 = z.literal(null).nullable(); const Compound: z.ZodType = z .object({ field: z.union([Null1, Null2, Null3, Null4, z.string()]) }) .partial() diff --git a/lib/tests/export-all-types.test.ts b/lib/tests/export-all-types.test.ts index 6169d27..2a9858e 100644 --- a/lib/tests/export-all-types.test.ts +++ b/lib/tests/export-all-types.test.ts @@ -103,13 +103,13 @@ describe("export-all-types", () => { expect(data).toEqual({ schemas: { - Settings: "z.object({ theme_color: z.string(), features: Features.min(1) }).partial().passthrough()", - Author: "z.object({ name: z.union([z.string(), z.number()]).nullable(), title: Title.min(1).max(30), id: Id, mail: z.string(), settings: Settings }).partial().passthrough()", - Features: "z.array(z.string())", + Settings: "z.object({ theme_color: z.string(), features: Features }).partial().passthrough()", + Author: "z.object({ name: z.union([z.string().nullable(), z.number()]).nullable(), title: Title, id: Id, mail: z.string(), settings: Settings }).partial().passthrough()", + Features: "z.array(z.string()).min(1)", Song: "z.object({ name: z.string(), duration: z.number() }).partial().passthrough()", Playlist: "z.object({ name: z.string(), author: Author, songs: z.array(Song) }).partial().passthrough().and(Settings)", - Title: "z.string()", + Title: "z.string().min(1).max(30)", Id: "z.number()", }, endpoints: [ @@ -198,17 +198,17 @@ describe("export-all-types", () => { duration: number; }>; - const Title = z.string(); + const Title = z.string().min(1).max(30); const Id = z.number(); - const Features = z.array(z.string()); + const Features = z.array(z.string()).min(1); const Settings: z.ZodType = z - .object({ theme_color: z.string(), features: Features.min(1) }) + .object({ theme_color: z.string(), features: Features }) .partial() .passthrough(); const Author: z.ZodType = z .object({ - name: z.union([z.string(), z.number()]).nullable(), - title: Title.min(1).max(30), + name: z.union([z.string().nullable(), z.number()]).nullable(), + title: Title, id: Id, mail: z.string(), settings: Settings, diff --git a/lib/tests/invalid-pattern-regex.test.ts b/lib/tests/invalid-pattern-regex.test.ts index 06f3207..b8da2a1 100644 --- a/lib/tests/invalid-pattern-regex.test.ts +++ b/lib/tests/invalid-pattern-regex.test.ts @@ -1,6 +1,5 @@ import { getZodSchema } from "../src"; import { expect, test } from "vitest"; -import { getZodChain } from "../src/openApiToZod"; import { SchemaObject } from "openapi3-ts"; test("invalid-pattern-regex", () => { @@ -17,15 +16,9 @@ test("invalid-pattern-regex", () => { pattern: "/[\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\uFFFE\uFFFF]+/", }; - expect(getZodSchema({ schema: schema }) + getZodChain({ schema })).toMatchInlineSnapshot( - '"z.string().regex(/[0-9]+/).optional()"' - ); - expect(getZodSchema({ schema: invalidSchema }) + getZodChain({ schema: invalidSchema })).toMatchInlineSnapshot( - '"z.string().regex(/[0-9]+/).optional()"' - ); - expect( - getZodSchema({ schema: controlCharacters }) + getZodChain({ schema: controlCharacters }) - ).toMatchInlineSnapshot( - '"z.string().regex(/[\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\\x7f\\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87\\x88\\x89\\x8a\\x8b\\x8c\\x8d\\x8e\\x8f\\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97\\x98\\x99\\x9a\\x9b\\x9c\\x9d\\x9e\\x9f\\ufffe\\uffff]+/).optional()"' + expect(getZodSchema({ schema })).toMatchInlineSnapshot('"z.string().regex(/[0-9]+/)"'); + expect(getZodSchema({ schema: invalidSchema })).toMatchInlineSnapshot('"z.string().regex(/[0-9]+/)"'); + expect(getZodSchema({ schema: controlCharacters })).toMatchInlineSnapshot( + '"z.string().regex(/[\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\\x7f\\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87\\x88\\x89\\x8a\\x8b\\x8c\\x8d\\x8e\\x8f\\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97\\x98\\x99\\x9a\\x9b\\x9c\\x9d\\x9e\\x9f\\ufffe\\uffff]+/)"' ); }); diff --git a/lib/tests/missing-zod-chains-on-z-object-with-refs-props.test.ts b/lib/tests/missing-zod-chains-on-z-object-with-refs-props.test.ts index 6293e46..bf22118 100644 --- a/lib/tests/missing-zod-chains-on-z-object-with-refs-props.test.ts +++ b/lib/tests/missing-zod-chains-on-z-object-with-refs-props.test.ts @@ -51,25 +51,18 @@ test("missing-zod-chains-on-z-object-with-refs-props", async () => { "import { makeApi, Zodios, type ZodiosOptions } from "@zodios/core"; import { z } from "zod"; - const Email = z.string(); - const Password = z.string(); - const AddUser = z - .object({ - email: Email.min(6) - .max(255) - .regex(/(EmailRegex)/), - password: Password.min(16) - .max(255) - .regex(/(PasswordRegex)/), - }) - .passthrough(); - const PasswordReminder = z - .object({ - email: Email.min(6) - .max(255) - .regex(/(EmailRegex)/), - }) - .passthrough(); + const Email = z + .string() + .min(6) + .max(255) + .regex(/(EmailRegex)/); + const Password = z + .string() + .min(16) + .max(255) + .regex(/(PasswordRegex)/); + const AddUser = z.object({ email: Email, password: Password }).passthrough(); + const PasswordReminder = z.object({ email: Email }).passthrough(); export const schemas = { Email, @@ -87,16 +80,7 @@ test("missing-zod-chains-on-z-object-with-refs-props", async () => { { name: "body", type: "Body", - schema: z - .object({ - email: Email.min(6) - .max(255) - .regex(/(EmailRegex)/), - password: Password.min(16) - .max(255) - .regex(/(PasswordRegex)/), - }) - .passthrough(), + schema: z.object({ email: Email, password: Password }).passthrough(), }, ], response: z.void(), @@ -109,13 +93,7 @@ test("missing-zod-chains-on-z-object-with-refs-props", async () => { { name: "body", type: "Body", - schema: z - .object({ - email: Email.min(6) - .max(255) - .regex(/(EmailRegex)/), - }) - .passthrough(), + schema: z.object({ email: Email }).passthrough(), }, ], response: z.void(), diff --git a/lib/tests/missing-zod-chains.test.ts b/lib/tests/missing-zod-chains.test.ts index 69ece46..54d239a 100644 --- a/lib/tests/missing-zod-chains.test.ts +++ b/lib/tests/missing-zod-chains.test.ts @@ -59,14 +59,14 @@ test("missing-zod-chains", async () => { "import { makeApi, Zodios, type ZodiosOptions } from "@zodios/core"; import { z } from "zod"; - const test1 = z.string(); - const test2 = z.number(); + const test1 = z.string().min(5); + const test2 = z.number().int().gte(10); const test3 = z .object({ text: z.string().min(5), num: z.number().int().gte(10) }) .passthrough(); - const nulltype = z.object({}).partial().passthrough(); + const nulltype = z.object({}).partial().passthrough().nullable(); const anyOfType = z.union([ - z.object({}).partial().passthrough(), + z.object({}).partial().passthrough().nullable(), z.object({ foo: z.string() }).partial().passthrough(), ]);