Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid zod schema type casting #1561

Open
xdata-golubev opened this issue Feb 14, 2025 · 0 comments
Open

Invalid zod schema type casting #1561

xdata-golubev opened this issue Feb 14, 2025 · 0 comments
Labels
bug Something isn't working @kubb/plugin-zod

Comments

@xdata-golubev
Copy link

xdata-golubev commented Feb 14, 2025

What version of kubb is running?

3.5.11

What kind of platform do you use?

MacOS

How does your kubb.config.ts config look like

import { defineConfig } from "@kubb/core";
import { pluginClient } from "@kubb/plugin-client";
import { Include, pluginOas } from "@kubb/plugin-oas";
import { pluginTs } from "@kubb/plugin-ts";
import { pluginZod } from "@kubb/plugin-zod";
import ts from "typescript";
import pkg from "typescript";

export const getApiGeneratedDirectoryPath = (apiName: string) =>
  `./src/shared/api/clients/${apiName}/generated`;

const { factory } = pkg;

const apiName = "apiName";

const includeOperations: Include[] = [
  {
    type: "path",
    pattern: "...",
  },
  {
    type: "path",
    pattern: "...",
  },
  {
    type: "path",
    pattern: "...",
  },
];

export default defineConfig(() => {
  return {
    name: apiName,
    root: ".",
    input: {
      path: "https://myapi",
    },
    output: {
      path: getApiGeneratedDirectoryPath(apiName),
      clean: true,
      barrelType: false,
      extension: { ".ts": "" },
    },
    hooks: {
      done: [
        `prettier --loglevel warn --write ${getApiGeneratedDirectoryPath(
          apiName
        )}`,
        `eslint --fix ${getApiGeneratedDirectoryPath(apiName)}`,
      ],
    },
    plugins: [
      pluginOas({
        generators: [],
        validate: true,
        serverIndex: 1,
      }),
      pluginTs({
        output: {
          path: "./models",
          barrelType: false,
        },
        group: {
          type: "tag",
          name: ({ group }) =>
            `${group
              .split(" ")
              .map(
                (part, index) =>
                  `${
                    index === 0
                      ? part.charAt(0).toLowerCase()
                      : part.charAt(0).toUpperCase()
                  }${part.slice(1)}`
              )
              .join("")}Controller`,
        },
        unknownType: "unknown",
        enumType: "literal",
        enumSuffix: "",
        include: includeOperations,
        mapper: {
          customerId: factory.createPropertySignature(
            undefined,
            factory.createIdentifier("customerId"),
            undefined,
            factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)
          ),
        },
      }),
      pluginZod({
        output: {
          path: `./validationSchemas/`,
          barrelType: false,
        },
        group: {
          type: "tag",
          name: ({ group }) =>
            `${group
              .split(" ")
              .map(
                (part, index) =>
                  `${
                    index === 0
                      ? part.charAt(0).toLowerCase()
                      : part.charAt(0).toUpperCase()
                  }${part.slice(1)}`
              )
              .join("")}Controller`,
        },
        unknownType: "unknown",
        dateType: false,
        typed: true,
        coercion: true,
        include: includeOperations,
      }),
      pluginClient({
        output: {
          path: "controllers",
          barrelType: false,
        },
        group: {
          type: "tag",
          name: ({ group }) =>
            `${group
              .split(" ")
              .map(
                (part, index) =>
                  `${
                    index === 0
                      ? part.charAt(0).toLowerCase()
                      : part.charAt(0).toUpperCase()
                  }${part.slice(1)}`
              )
              .join("")}Controller`,
        },
        dataReturnType: "data",
        pathParamsType: "inline",
        operations: true,
        paramsCasing: "camelcase",

        importPath: `~shared/api/clients/${apiName}/${apiName}AxiosClient`,
        include: includeOperations,
      }),
    ],
  };
});

Swagger/OpenAPI file?

Can't provide the full file, but this is the relevant endpoint:

      "/api/v1/business/{customerId}/notifications":{
         "get":{
            "tags":[
               "Business"
            ],
            "summary":"Get notifications",
            "description":"Get notifications",
            "operationId":"getNotifications",
            "parameters":[
               {
                  "name":"X-Auth-CustomerId",
                  "in":"header",
                  "schema":{
                     "type":"string",
                     "format":"long"
                  },
                  "example":12345678
               },
               {
                  "name":"customerId",
                  "in":"path",
                  "required":true,
                  "schema":{
                     "type":"string",
                     "format":"long"
                  },
                  "example":12345678
               }
            ],
            "responses":{
               "200":{
                  "description":"OK",
                  "content":{
                     "application/json":{
                        "schema":{
                           "type":"array",
                           "items":{
                              "type":"string",
                              "enum":[
                                 "TYPE1",
                                 "TYPE2",
                                 "TYPE3"
                              ]
                           }
                        }
                     }
                  }
               }
            }
         },

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

"react": "18.3.1",
"zod": "3.23.4",
"@tanstack/react-query": "5.56.2",

What steps can reproduce the bug?

  1. Generate the api files
  2. Check validation schema and model

Result:

export type GetNotifications200 = "TYPE1" | "TYPE2" | "TYPE3";

export type GetNotificationsQueryResponse = GetNotifications200;

export const getNotifications200Schema = z.array(
  z.enum(["TYPE1", "TYPE2", "TYPE3"])
) as unknown as ToZod<GetNotifications200>;

export const getNotificationsQueryResponseSchema = z.lazy(
  () => getNotifications200Schema
) as unknown as ToZod<GetNotificationsQueryResponse>;

The schemas are generated correctly, but then cast into a single element instead of an array

How often does this bug happen?

Every time

What is the expected behavior?

Schemas cast correctly to an array of GetNotifications200/GetNotificationsQueryResponse

Additional information

No response

@xdata-golubev xdata-golubev added the bug Something isn't working label Feb 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working @kubb/plugin-zod
Projects
None yet
Development

No branches or pull requests

2 participants