orval icon indicating copy to clipboard operation
orval copied to clipboard

Orval generates some enums that are used before they are declared

Open markosandalj opened this issue 1 year ago • 18 comments

What are the steps to reproduce this issue?

  1. Open codesandbox link here: https://codesandbox.io/p/devbox/slgr4l
  2. run pnpm run orval in terminal or start development from terminal GUI in

I already run that command so you can also look at the generated TS file. I added both "stripped" version of schema yaml and full one. Currently stripped one is used for generation and should be enough but if needed orval.config can be switched to use full version.

Here is a google drive link for schema files: https://drive.google.com/drive/folders/1CtwFX2peUVhFRpPqgDjZMqNY-5FS30b2?usp=sharing

What happens?

Backend is written in Django and Django rest framework so we use drf spectacular for generating open api schema. What happens is, Orval correctly generates all the types but for some reason few enums are used before they are generated. For example on line 1540: export const SubjectRequestIcon = { ...SubjectIconEnum, ...BlankEnum, ...NullEnum } as const; , both BlankEnum and NullEnum are used but they are declared much further in the file (line ~8449 and ~5053). These two are most prevalent since they are used on every model that uses Django's choice filed and can be null in database. There are two more enums that are used before they are declared if it helps: ProductIconEnum and LevelEnum.

What were you expecting to happen?

That enumas that are used to construct other enums are generated before them so we don't get TS errors.

Any logs, error output, etc?

There is no logs, errors or anything in CLI - everything runs fine but the generated file has typescript errors:

  • Block-scoped variable 'BlankEnum' used before its declaration.ts(2448)
  • Variable 'BlankEnum' is used before being assigned.ts(2454)

Any other comments?

I attached schema.yaml if it helps and here is orval output config:

output: {
    target: './src/features/api/orval/',
    indexFiles: true,
    client: 'fetch',
    mode: 'tags-split',
    clean: true,
    prettier: true,
    baseUrl: 'http://0.0.0.0:8081',
    urlEncodeParameters: true,
    headers: true,
    override: {
        useNamedParameters: true,
        suppressReadonlyModifier: true,
        useTypeOverInterfaces: true,
        contentType: {
            include: [
                'application/json',
                'text/plain',
                'application/x-www-form-urlencoded',
                'multipart/form-data',
            ],
        },
    },
},

What versions are you using?

Operating System: MacOS Package Version: 6.31.0 Browser Version: Newest Chrome

markosandalj avatar Jul 09 '24 15:07 markosandalj

Do you have an OpenAPI JSON file to go with it?

melloware avatar Jul 09 '24 15:07 melloware

Here is a link to google drive since Github doesn't allow uploading .yaml files https://drive.google.com/drive/folders/1CtwFX2peUVhFRpPqgDjZMqNY-5FS30b2?usp=sharing

I added it to description aswell.

markosandalj avatar Jul 09 '24 15:07 markosandalj

This looks fetch client related right?

melloware avatar Aug 23 '24 12:08 melloware

I don't think so, since creating a schemas containing an enum is a different process than creating a client

soartec-lab avatar Sep 01 '24 08:09 soartec-lab

I don't have time to deal with this issue yet, so I'll remove the assignment to me.

soartec-lab avatar Sep 01 '24 08:09 soartec-lab

Also seeing a few of these typescript errors in my generated schema. Any suggested ways to workaround it?

Update: I am working around it by re-ordering my Open API 3.0 schemas in the json

rob-long avatar Sep 07 '24 22:09 rob-long

Another thought was use "mode: split" which puts all models in another file?

melloware avatar Sep 07 '24 23:09 melloware

Having the issue, mode: 'split' does not help, the issue remain on the schemas.ts file. My workaround is to add // @ts-nocheck to the schema file when using split mode.

alex3165 avatar Sep 13 '24 07:09 alex3165

I have the same issue and the workaroung // @ts-nocheck from @alex3165 helped for now, but annoying to do it every time I generate the files, but still better than writing your own services :P

oesah avatar Oct 02 '24 13:10 oesah

you can add it so it gets generated with your code.

petstore: {
    output: {
      override: {
        header: (info: InfoObject): String[] => { return "// @ts-nocheck\r\n" },
      },
    },

melloware avatar Oct 02 '24 14:10 melloware

@melloware your changes produce the following, which still does not work :(

/**
 * // @ts-nocheck
 * Generated by orval 🍺
 * Do not edit manually.
 * Lancer Express API
 * API Docs
 * OpenAPI spec version: 1.0.0
 */

The @ts-nocheck is added to the docs, not to the file head.

oesah avatar Dec 14 '24 14:12 oesah

My apologies it has to be a function like this...

header: (info: InfoObject): String[] => { return "// @ts-nocheck\r\n" },

now for me this generates...

// @ts-nocheck
import { useMutation, useQuery } from '@tanstack/react-query';
import type {
	DataTag,
	DefinedInitialDataOptions,
	DefinedUseQueryResult,
	MutationFunction,
	QueryFunction,
	QueryKey,
	UndefinedInitialDataOptions,
	UseMutationOptions,
	UseMutationResult,
	UseQueryOptions,
	UseQueryResult
} from '@tanstack/react-query';

melloware avatar Dec 14 '24 15:12 melloware

@melloware that works fine to suppress the Typescript errors when generating the API schema.

The issue is that if you want to use an enum type somewhere in your code, React will try to import it and that error will pop up again.

Wondering if it would be possible to tell Orval to put the enum types at the top of the schema file and also declare the const before the type, just like this:

// This is the top of the api.schemas.ts file

// eslint-disable-next-line @typescript-eslint/no-redeclare
export const BlankEnum = {
  "": ""
} as const;

export type BlankEnum = (typeof BlankEnum)[keyof typeof BlankEnum];

// eslint-disable-next-line @typescript-eslint/no-redeclare
export const NullEnum = {} as const;

export type NullEnum = (typeof NullEnum)[keyof typeof NullEnum];

// eslint-disable-next-line @typescript-eslint/no-redeclare
export const ContractTypeEnum = {
  indefinite: "indefinite",
  temporary: "temporary",
  self_employed: "self_employed",
  student: "student",
  other: "other"
} as const;

/**
 * * `indefinite` - Indefinite
 * `temporary` - Temporary
 * `self_employed` - Self-employed
 * `student` - Student
 * `other` - Other
 */
export type ContractTypeEnum =
  (typeof ContractTypeEnum)[keyof typeof ContractTypeEnum];

This will get rid of the errors and the typescript suppression won't be necessary.

dontic avatar Jan 08 '25 12:01 dontic

That is not a bad idea! Not sure how possible that is but PR is welcome!

melloware avatar Jan 08 '25 12:01 melloware

That is not a bad idea! Not sure how possible that is but PR is welcome!

Currently limited on time and not familiar with the code, but I will definitely give it a go when I get a bit more spare time.

dontic avatar Jan 08 '25 12:01 dontic

This error start showing up with 7.5.0 with a OpenAPI JSON which is working fine with 7.4.1

jc-louis avatar Feb 26 '25 13:02 jc-louis

While the trick with header: shuts up tsc compiler, next.js compiler seems to not care about it and still fails...

vsviridov avatar Feb 27 '25 00:02 vsviridov

Yep it needs to be fixed for real. PR is welcome...

melloware avatar Feb 27 '25 01:02 melloware