kubb-labs / kubb

The ultimate toolkit for working with APIs.
https://kubb.dev
MIT License
744 stars 67 forks source link

Integer validation schema not generated properly #1159

Closed assassinoNz closed 2 months ago

assassinoNz commented 3 months ago

What version of kubb is running?

2.25.3

What platform is your computer?

Linux

What version of external packages are you using(@tanstack-query, MSW, React, Vue, ...)

"devDependencies": { "@faker-js/faker": "^8.4.1", "@kubb/cli": "^2.25.3", "@kubb/core": "^2.25.3", "@kubb/swagger": "^2.25.3", "@kubb/swagger-zod": "^2.25.3", "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "^11.1.6", "@types/cors": "^2.8.16", "@types/express": "^4.17.21", "@types/jsonwebtoken": "^9.0.6", "@types/multer": "^1.4.12", "@types/node": "^22.0.2", "@typespec/compiler": "^0.59.0", "@typespec/http": "^0.59.0", "@typespec/openapi3": "^0.59.0", "@typespec/rest": "^0.59.0", "axios": "^1.7.3", "prisma": "^5.19.0", "prisma-erd-generator": "^1.11.2", "prisma-json-types-generator": "^3.0.4", "rollup": "^4.20.0", "typescript": "^5.5.4" }, "dependencies": { "@prisma/client": "^5.19.0", "cors": "^2.8.5", "dotenv": "^16.3.1", "electron": "^32.0.1", "express": "^4.19.2", "jsonwebtoken": "^9.0.2", "multer": "^1.4.5-lts.1", "tsx": "^4.15.7", "winston": "^3.11.0", "winston-daily-rotate-file": "^4.7.1", "zod": "^3.23.8" },

What steps can reproduce the bug?

1.Just run Kubb on any openapi.json/openapi.yaml file. I'm using the following kubb.config.ts

import { defineConfig } from "@kubb/core";
import { pluginOas } from "@kubb/plugin-oas";
import { pluginZod } from "@kubb/swagger-zod";

export default defineConfig({
    input: {
        path: "./typespec/tsp-output/@typespec/openapi3/openapi.json",
    },
    output: {
        path: "./gen",
    },
    plugins: [
        pluginOas(),
        pluginZod({
            output: {
                path: "./zod",
                exportType: false,
            },
            group: {
                type: "tag",
                output: "./zod/{{tag}}"
            },
            coercion: true
        })
    ],
})

How often does this bug happen?

Every time

What is the expected behavior?

Considered sections in the attached openapi.json

"parameters": [
  {
    "name": "page",
    "in": "query",
    "required": false,
    "schema": {
      "type": "integer",
      "minimum": 0
    }
  },
  {
    "name": "pageSize",
    "in": "query",
    "required": false,
    "schema": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "default": 10
    }
  }
],

Kubb Generated output

export const listModulesQueryParamsSchema = z.object({ "page": z.coerce.number().min(0).optional(), "pageSize": z.coerce.number().min(1).max(100).optional() }).optional();

Expected output

Swagger/OpenAPI file?

openapi.json

Additional information

  1. The .int() validation could be added successfully by modifying just within packages/plugin-zod/src/parser/index.ts.
    • Fixed zodKeywordMapper.integer() method as follows.
      integer: (coercion?: boolean, min?: number, max?: number) => {
      return [coercion ? 'z.coerce.number().int()' : 'z.number().int()', min !== undefined ? `.min(${min})` : undefined, max !== undefined ? `.max(${max})` : undefined]
      .filter(Boolean)
      .join('')
      },
    • Made use of that method (currently unused) as follows.
      
      if (isKeyword(current, schemaKeywords.number) ) {
      return zodKeywordMapper.number(options.coercion)
      }

if (isKeyword(current, schemaKeywords.integer) ) { return zodKeywordMapper.integer(options.coercion) }



2. The above fix doesn't solve the  `.default()` validation problem.
stijnvanhulle commented 2 months ago

@assassinoNz Your change would indeed fix it but I noticed in SchemaGenerator that when a property has default set we only did a check on string(typeof string) and boolean(typeof boolean). All other formats(like in this case number) were ignored.

I opened a PR with your changes + some tests to validate the SchemaGenerator(this fed the Zod parser so we can map based on a keyword like 'integer', 'number', ...): https://github.com/kubb-labs/kubb/pull/1166.

assassinoNz commented 2 months ago

Can confirm this issue is now resolved with the following versions.

{
  "@kubb/cli": "^2.25.5",
  "@kubb/core": "^2.25.5",
  "@kubb/swagger": "^2.25.5",
  "@kubb/swagger-zod": "^2.25.5",
}