orval
orval copied to clipboard
Zod schemas generated with undefined min and max variables
What are the steps to reproduce this issue?
- I am using FastAPI (v. 0.111.0) to generate my OpenAPI Schema (v. 3.1.0).
- Then I am using Orval to generate my Zod schemas.
What happens?
When I give a field a min and max length together with optional and nullable, Orval sets the min and max to undefined variables.
What were you expecting to happen?
I would rather have these be the numbers themselves instead of variables, or defined variables :)
Minimal Reproducible Example:
Example yaml:
openapi: 3.1.0
info:
title: FastAPI
version: 0.1.0
paths:
/api/v1/users/:
post:
tags:
- users
summary: Create User
operationId: create_user
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UserCreate'
required: true
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/UserRead'
components:
schemas:
UserCreate:
properties:
first_name:
type: string
maxLength: 50
minLength: 1
title: First Name
last_name:
type: string
maxLength: 50
minLength: 1
title: Last Name
email:
anyOf:
- type: string
maxLength: 99
minLength: 5
format: email
- type: 'null'
title: Email
nullable: true
phone:
anyOf:
- type: string
maxLength: 15
minLength: 10
- type: 'null'
title: Phone
date_of_birth:
type: string
format: date
title: Date Of Birth
type: object
required:
- first_name
- last_name
- date_of_birth
title: UserCreate
description: User create schema
UserRead:
properties:
first_name:
type: string
maxLength: 50
minLength: 1
title: First Name
last_name:
type: string
maxLength: 50
minLength: 1
title: Last Name
email:
anyOf:
- type: string
maxLength: 99
minLength: 5
format: email
- type: 'null'
title: Email
nullable: true
phone:
anyOf:
- type: string
maxLength: 15
minLength: 10
- type: 'null'
title: Phone
date_of_birth:
type: string
format: date
title: Date Of Birth
user_id:
type: integer
title: User Id
type: object
required:
- first_name
- last_name
- date_of_birth
- user_id
title: UserRead
description: User read schema
Example config:
import { defineConfig } from "orval";
const target = 'test.yaml'
export default defineConfig({
Zod: {
input: {
target: target,
},
output: {
mode: "tags",
target: './src/gen/zod',
client: "zod",
},
}
});
Example Output:
/**
* Generated by orval v6.31.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
import {
z as zod
} from 'zod'
/**
* @summary Create User
*/
export const createUserBodyFirstNameMax = 50;
export const createUserBodyLastNameMax = 50;
export const createUserBody = zod.object({
"first_name": zod.string().min(1).max(createUserBodyFirstNameMax),
"last_name": zod.string().min(1).max(createUserBodyLastNameMax),
"email": zod.string().email().min(createUserBodyEmailMinOne).max(createUserBodyEmailMaxOne).or(zod.null()).nullish(),
"phone": zod.string().min(createUserBodyPhoneMinOne).max(createUserBodyPhoneMaxOne).or(zod.null()).optional(),
"date_of_birth": zod.string().date()
})
export const createUserResponseFirstNameMax = 50;
export const createUserResponseLastNameMax = 50;
export const createUserResponse = zod.object({
"first_name": zod.string().min(1).max(createUserResponseFirstNameMax),
"last_name": zod.string().min(1).max(createUserResponseLastNameMax),
"email": zod.string().email().min(createUserResponseEmailMinOne).max(createUserResponseEmailMaxOne).or(zod.null()).nullish(),
"phone": zod.string().min(createUserResponsePhoneMinOne).max(createUserResponsePhoneMaxOne).or(zod.null()).optional(),
"date_of_birth": zod.string().date(),
"user_id": zod.number()
})
- createUserBodyEmailMinOne and createUserResponseEmailMaxOne are not defined.
Any other comments?
Great library, thank you very much! Let me know how I can help out. And sorry if there is something small I am missing.
What versions are you using?
Operating System: MacOS (M1) Package Version: 6.31.0
PR is welcome if you want to look at the zod generating source.
Any ideas on where in the zod file to start?
Start here maybe: https://github.com/anymaniax/orval/blob/e038704a13176379086feb71212157f65ca35353/packages/zod/src/index.ts#L111-L112
I'm getting similar.
openapi version: "3.1.0"
openapi json:
"/entity": {
"get": {
"tags": [
"Entities"
],
"summary": "List Entities",
"description": "List entities with optional query parameter filters.",
"operationId": "list_entities_entity_get",
"parameters": [
...
{
"name": "page_size",
"in": "query",
"required": false,
"schema": {
"anyOf": [
{
"type": "integer",
"maximum": 100,
"minimum": 1
},
{
"type": "null"
}
],
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 10,
"title": "Page Size"
}
}
],
...
gives me: ** partial zod output**:
page_size: zod
.number()
.min(1)
.max(listEntitiesEntityGetQueryPageSizeMaxOne)
.or(zod.null())
.min(1)
.max(listEntitiesEntityGetQueryPageSizeMax)
.optional(),
});
I don't foresee myself having time to look into this soon, but if you find anything that may be helpful, let me know and I'll try to see.
I'm also having issues with regexes. The following happens occurs several times in the api and the result is the same for all of them:
openapi doc
"phone_number": {
"anyOf": [
{
"type": "string",
"pattern": "^(\\+?[1|0])?( )*([ \\[\\(])?\\d{3}([\\)\\]\\. \\-])?( )*\\d{3}([\\. \\-])?( )*\\d{4}$",
"examples": [
"+15555555555",
"(555)555-55555",
"555.555.5555",
"(555) 555-5555",
"15555555555",
"[555]555-5555"
]
},
{
"type": "null"
}
],
"title": "Phone Number"
}
Resulting zod:
phone_number: zod
.string()
.regex(getUserUserSubGetResponsePhoneNumberRegExpOne)
.or(zod.null())
.optional(),
Let me know if I should open a separate issue for this.
@stephan-noel probably best to open a separate issue
can someone re-test with 7.8.0 and let me know if this is still an issue?
Looks like it is working now, thank you very much!