diff --git a/oxide-openapi-gen-ts/package-lock.json b/oxide-openapi-gen-ts/package-lock.json index d429131..35de523 100644 --- a/oxide-openapi-gen-ts/package-lock.json +++ b/oxide-openapi-gen-ts/package-lock.json @@ -1,12 +1,12 @@ { "name": "@oxide/openapi-gen-ts", - "version": "0.8.1", + "version": "0.9.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@oxide/openapi-gen-ts", - "version": "0.8.1", + "version": "0.9.0", "license": "MPL-2.0", "dependencies": { "minimist": "^1.2.8", diff --git a/oxide-openapi-gen-ts/package.json b/oxide-openapi-gen-ts/package.json index 1bbde6f..15455a4 100644 --- a/oxide-openapi-gen-ts/package.json +++ b/oxide-openapi-gen-ts/package.json @@ -1,6 +1,6 @@ { "name": "@oxide/openapi-gen-ts", - "version": "0.8.1", + "version": "0.9.0", "description": "OpenAPI client generator used to generate Oxide TypeScript SDK", "keywords": [ "oxide", diff --git a/oxide-openapi-gen-ts/src/client/msw-handlers.ts b/oxide-openapi-gen-ts/src/client/msw-handlers.ts index cab01a7..ed4f44f 100644 --- a/oxide-openapi-gen-ts/src/client/msw-handlers.ts +++ b/oxide-openapi-gen-ts/src/client/msw-handlers.ts @@ -33,7 +33,7 @@ export function generateMSWHandlers(spec: OpenAPIV3.Document, destDir: string) { type PathParams, } from "msw"; import type { SnakeCasedPropertiesDeep as Snakify, Promisable } from "type-fest"; - import { type ZodSchema } from "zod"; + import { type ZodType } from "zod/v4"; import type * as Api from "./Api"; import { snakeify } from "./util"; import * as schema from "./validate"; @@ -105,7 +105,7 @@ export function generateMSWHandlers(spec: OpenAPIV3.Document, destDir: string) { w("}"); w(` - function validateParams(schema: S, req: Request, pathParams: PathParams) { + function validateParams(schema: S, req: Request, pathParams: PathParams) { const rawParams = new URLSearchParams(new URL(req.url).search) const params: [string, unknown][] = [] @@ -131,7 +131,9 @@ export function generateMSWHandlers(spec: OpenAPIV3.Document, destDir: string) { return { paramsErr: json({ error_code, message }, { status }) } } - const handler = (handler: MSWHandlers[keyof MSWHandlers], paramSchema: ZodSchema | null, bodySchema: ZodSchema | null) => + const handler = (handler: MSWHandlers[keyof MSWHandlers], + // eslint-disable-next-line @typescript-eslint/no-explicit-any + paramSchema: ZodType | null, bodySchema: ZodType | null) => async ({ request: req, params: pathParams, diff --git a/oxide-openapi-gen-ts/src/client/zodValidators.ts b/oxide-openapi-gen-ts/src/client/zodValidators.ts index 7bb7cac..4a6a589 100644 --- a/oxide-openapi-gen-ts/src/client/zodValidators.ts +++ b/oxide-openapi-gen-ts/src/client/zodValidators.ts @@ -29,7 +29,7 @@ export function generateZodValidators( w(`/* eslint-disable */ - import { z, ZodType } from 'zod'; + import { z, ZodType } from 'zod/v4'; import { processResponseBody, uniqueItems } from './util'; /** diff --git a/oxide-openapi-gen-ts/src/schema/zod.ts b/oxide-openapi-gen-ts/src/schema/zod.ts index 56092ba..30fb04f 100644 --- a/oxide-openapi-gen-ts/src/schema/zod.ts +++ b/oxide-openapi-gen-ts/src/schema/zod.ts @@ -38,33 +38,33 @@ export const schemaToZod = makeSchemaGenerator({ }, string(schema, { w0 }) { - w0(`z.string()`); - - if ("default" in schema) { - w0(`.default(${JSON.stringify(schema.default)})`); - } + // Handle special formats that become standalone in Zod v4 if (schema.format === "uuid") { - w0(".uuid()"); - } - - if (schema.format === "ip") { - w0(".ip()"); + w0("z.uuid()"); + } else if (schema.format === "ip") { + // Generic IP becomes IPv4 for backward compatibility + w0("z.ipv4()"); } else if (schema.format === "ipv4") { - w0(".ip({ version: 'v4' })"); + w0("z.ipv4()"); } else if (schema.format === "ipv6") { - w0(".ip({ version: 'v6' })"); - } + w0("z.ipv6()"); + } else { + // Regular string handling + w0(`z.string()`); - if ("minLength" in schema) { - w0(`.min(${schema.minLength})`); - } - if ("maxLength" in schema) { - w0(`.max(${schema.maxLength})`); - } - if ("pattern" in schema) { - w0(`.regex(${new RegExp(schema.pattern!).toString()})`); + if ("minLength" in schema) { + w0(`.min(${schema.minLength})`); + } + if ("maxLength" in schema) { + w0(`.max(${schema.maxLength})`); + } + if ("pattern" in schema) { + w0(`.regex(${new RegExp(schema.pattern!).toString()})`); + } } + if (schema.nullable) w0(".nullable()"); + if ("default" in schema) w0(`.default(${JSON.stringify(schema.default)})`); }, date(schema, { w0 }) { @@ -98,7 +98,7 @@ export const schemaToZod = makeSchemaGenerator({ const { w0, w } = io; // record type, which only tells us the type of the values if (!schema.properties || Object.keys(schema.properties).length === 0) { - w0("z.record(z.string().min(1),"); + w0("z.record(z.string(),"); if (typeof schema.additionalProperties === "object") { schemaToZod(schema.additionalProperties, io); } else { @@ -179,14 +179,12 @@ export const schemaToZod = makeSchemaGenerator({ w("])"); } - if ("default" in schema) { - w0(`.default(${JSON.stringify(schema.default)})`); - } - if (schema.nullable) io.w0(".nullable()"); + if (schema.nullable) w0(".nullable()"); + if ("default" in schema) w0(`.default(${JSON.stringify(schema.default)})`); }, empty({ w0 }) { - w0("z.record(z.unknown())"); + w0("z.record(z.string(), z.unknown())"); }, default(schema) {