Apollo314 / openapi-to-zod

MIT License
3 stars 2 forks source link

Incorrect order for nullable/default #5

Closed robogeek closed 9 months ago

robogeek commented 9 months ago

If an object schema has a field with default: null and nullable: true, the Zod schema is generated incorrectly. The .nullable() appears after .default(null), and .default(null) appears twice.

With this schema:


components:
  schemas:
      hasDefaultNull:
        type: object
        properties:
          defaultNull:
            type: string
            format: date-time
            nullable: true
            default: null
      notNullable:
        type: object
        properties:
          defaultNull:
            type: string
            format: date-time
            # nullable: true
            default: null

Running the command:

$ npx openapi-to-zod -i ./nullable.yml -o zod -x ts

Generates these Zod schemas.

$ cat zod/zod-hasDefaultNull.ts 
import { z } from "zod";

export default z.object({
  defaultNull: z.string().datetime().default(null).nullable().default(null),
});

$ cat zod/zod-notNullable.ts 
import { z } from "zod";

export default z.object({ defaultNull: z.string().datetime().default(null) });

For the first .default(null), with tsconfig.json containing "strict": true, an error is thrown by the compiler saying the following:

No overload matches this call.
  Overload 1 of 2, '(def: string): ZodDefault<ZodString>', gave the following error.
    Argument of type 'null' is not assignable to parameter of type 'string'.
  Overload 2 of 2, '(def: () => string): ZodDefault<ZodString>', gave the following error.
    Argument of type 'null' is not assignable to parameter of type '() => string'.ts(2769)

But, moving the .nullable() before .default(null) no such error is thrown. THEORY, having .nullable first puts the Zod code into a state where .default() takes either null | string rather than just string.

The other issue is that .default(null) appears twice in the generated code. This does not happen if nullable does not appear in the schema.

robogeek commented 9 months ago

The upstream package says it has been fixed. Does this package need to update its dependencies?

robogeek commented 9 months ago

The package has this dependency:

    "json-schema-to-zod": "^1.1.1",

The upstream package is at 2.0.13

Apollo314 commented 9 months ago

updated it . I hope it resolves your problem.

robogeek commented 9 months ago

Well, I updated to 0.0.6 and now get the following error. I see at the referenced line there is require('./parser/parser') but there is no such file inside dist.

> npx openapi-to-zod -x ts -i ${npm_package_config_openadryaml} -o ${npm_package_config_zodoutput}

node:internal/modules/cjs/loader:1147
  throw err;
  ^

Error: Cannot find module './parser/parser'
Require stack:
- /home/david/Projects/openadr/openadr-3-ts-types/builder/node_modules/openapi-to-zod/dist/index.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1144:15)
    at Module._load (node:internal/modules/cjs/loader:985:27)
    at Module.require (node:internal/modules/cjs/loader:1235:19)
    at require (node:internal/modules/helpers:176:18)
    at Object.<anonymous> (/home/david/Projects/openadr/openadr-3-ts-types/builder/node_modules/openapi-to-zod/dist/index.js:39:18)
    at Module._compile (node:internal/modules/cjs/loader:1376:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
    at Module.load (node:internal/modules/cjs/loader:1207:32)
    at Module._load (node:internal/modules/cjs/loader:1023:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/home/david/Projects/openadr/openadr-3-ts-types/builder/node_modules/openapi-to-zod/dist/index.js'
  ]
}

Node.js v20.10.0
Apollo314 commented 9 months ago

odd. for some reason npm decided to ignore subdirectories in dist folder when package.json was like this:

https://github.com/Apollo314/openapi-to-zod/blob/51e6b49308555eb9ce6e37997fd62cc6a70125aa/package.json#L10

I changed it to 'dist' without the glob pattern and it now includes them.

edit: seems to be an npm bug

https://github.com/npm/cli/issues/7081

robogeek commented 9 months ago

Thank you for the quick response. That has the program running correctly. But, there's a new problem:

$ cat zod/zod-dateTime.ts 
z.string().datetime().describe("datetime in ISO 8601 format")

That is - the schema is not exported from the module.

A minor nitpick is there is no final newline at the end of the file.

Apollo314 commented 9 months ago

lol. sorry I'm a little sleepy right now. it's midnight here.

robogeek commented 9 months ago

I see you updated to 0.0.9

This update is working correctly.

Thank you.