orval-labs / orval

orval is able to generate client with appropriate type-signatures (TypeScript) from any valid OpenAPI v3 or Swagger v2 specification, either in yaml or json formats. 🍺
https://orval.dev
MIT License
3.03k stars 333 forks source link

v8 ideas 💡 #434

Open anymaniax opened 2 years ago

anymaniax commented 2 years ago

I am already thinking about version 7 for a moment and wanted a place to talk about it.

  1. Split the lib into multiple packages to have a core and a package by template/client. Like that we can have multiple advantages. Versioning for the template and be able to use an older version of a template if your project is on an older version of react-query for example. Also having a core will help people that want to create their own template and then use it with other features of orval.

  2. Rethink the config file since I started this lib a lot of stuff has been added and I think we can improve some points. For example, the generation could be more custom. I think for example that having a mix of this and some of Orval features could be great

  3. move to esm?

if you have any other ideas throw them here so that we can discuss it

melloware commented 2 years ago

I definitely like the idea of breaking the lib up so its easier to find and make changes to the different libs. Changing the config file though might be a big and painful change. However it may be worth it but I am not sure.

anymaniax commented 2 years ago

I was also thinking about having a migrate command to do it easily for users

paolotiu commented 2 years ago

Another feature that would be handy is to add a zod schema generator

stijnvanhulle commented 2 years ago

https://github.com/anymaniax/orval/issues/347(export MSW controllers to a separate index file) This one should be great to have :)

anymaniax commented 2 years ago

What do you think of this for query keys

melloware commented 2 years ago

What do you think of this for query keys

I LOVE this idea. I find myself doing this a lot in my code...

const QUERY_LIST = "list-cars";
 const queryList = useGetEntityCars(
        { request: JSON.stringify(lazyParams) },
        {
            query: {
                queryKey: [QUERY_LIST, lazyParams],
                refetchOnWindowFocus: false,
                retry: false,
                cacheTime: 0
            }
        }
    );

So then later I can do this... queryClient.invalidateQueries([QUERY_LIST]);

So that library looks like what I wanted to do all along!

melloware commented 2 years ago

Although I do hate tying myself to another runtime library written by just one guy. it would be cool if you could just copy his code and include it in the generated code?

DominicBach commented 2 years ago

I've been playing with the codebase for a bit and have been experimenting with using the Typescript AST factory to generate code as opposed to plain string manipulation. I've used it to encapsulate mock generation logic into separate type classes, which I could then compose together to build more complex representations.

It could also solve your idea for additional customization by allowing users to hook into the AST generation process to change the code at generation time.

I've committed the code to my fork if it's something that might interest you, I'd be happy to put more work into this.

la55u commented 2 years ago

have been experimenting with using the Typescript AST factory to generate code

I also think that this is the way going forward as the string manipulation approach is quite unmaintainable. A cleaner approach can be seen for example here however it's quite opinionated and orval has much more configuratoin options. I think orval could attract a lot more contributors in the long run if it were rewritten with TS generators.

Edit: Can you pin this issue?

maapteh commented 1 year ago

Now with react-query v5 and breaking contracts it would be very handy to choose which major your client is using. Maybe support up to 1 major back?

Will-Mann-16 commented 12 months ago

Maybe have zod be an includable separate layer (i.e. request/response validation on top of axios on top of react-query). Or just splitting things into layers, like having the request engine layer be between axios or native fetch, then an optional validation layer with zod, then the caching control/hooks/query library layer for tanstack query or swr.

bojanbass commented 12 months ago

@Will-Mann-16 yes, this would be perfect, I'm searching for this solution.

arthurfiorette commented 11 months ago

I've done extensive work with code generation, specially in typescript, I'll write here some of my opinions and I'd love (as directly spoken with @anymaniax before) to help with v7 development.

Split the lib into multiple packages to have a core and a package by template/client.

Awesome idea, 100% agree with you. Initial work may be a little bit harder, here are some tips:

Architectures like Swagger JSON -> [swagger parsers] -> Orval AST -> [AST formatters] -> Generated code should work.

Think for example that having a mix of this and some of Orval features could be great.

Splitting the generation inside multiple files will only give headache and bump into all horribleness that happens within the JS bundling scenario currently, This will become a never ending source of bugs and features to be implemented. As long we emit TS code in ESM, tree shaking (currently supported by all major bundlers) will resolve all of our performance/frontend problems. Although it should provide a way to generate types separately (to gain speed benefits from the import type typescript's feature). There's no real benefit into supporting what we currently know as mode option. Also generated code shouldn't be edited/checked manually so readability does not applies here.

Move to esm?

ESM in general is still a great pain-in-the-ass for the current state of JS, if ESM is used inside a package users really need, they may consider changing their current build/bundle process, however, orval will mostly (if not always) be consumed as a CLI, which providing a ESM only bundle will broadly reduce user adoption. If a ESM bundle is REALLY needed, we could provide a non default esm version, like orval and orval-esm binaries.

Oclif is the go-to current standard to build a CLI, so if rewritten, I strongly recommend to use it here too, plugins like autocomplete and warn-if-update-available are awesome.

changing the config file.

JS in general is a bit too much unopinionated in my opinion, as long as we have a typesafe way to writing our configuration file, i'm happy with it. Not too permissive as https://github.com/cosmiconfig/cosmiconfig but nothing too strict as a json file, current orval.config.js is awesome but probably will have its current properties changed upon refactor in favor of v7. Custom config lookup/parsing/resolution usually takes a good portion of a CLI's runtime, so this should be taken care of.

Code->string generation tools.

I've tried a lot in the past, generating TS, generating dts+js, generating inside node_modules (like what prisma does), generating inside the user's src dir, using handlebars-like templates, using raw ` or using an ast builder like typescript compiler api.

Somehow I keep finding myself going back to writing raw template strings with some helpers, I'm experimenting ts-writer (usage example), pairing it with vscode-sql-tagged-template-literals gives a nice DX with instantaneous performance.

AST generators may be more type safe, but comes with a super slow performance compared to template literals and a worse DX, which WILL scare devs away from implementing custom generators (declarative > imperative). Handlebars could be an option, but I could not find a nice way to get typescript syntax highlighting to work. Simple top level functions used everywhere in combination with ts-writer is the best I could achieve until now, but would love new ideas.


Sorry if the above text has spelling mistakes, this is everything I could come up with at 1am.

melloware commented 11 months ago

@arthurfiorette would love any help. Your plan sounds very ambitious.

anymaniax commented 10 months ago

@arthurfiorette can you contact me on discord to discuss it?

olafur164 commented 9 months ago

@anymaniax Do you think it would be difficult to implement support for https://github.com/ngneat/query and then for the official package for Angular Query from TanStack once it is out of experimental stage? https://tanstack.com/query/v5/docs/angular/overview

luania commented 8 months ago

@arthurfiorette

Splitting the generation inside multiple files will only give headache and bump into all horribleness that happens within the JS bundling scenario currently, This will become a never ending source of bugs and features to be implemented. As long we emit TS code in ESM, tree shaking (currently supported by all major bundlers) will resolve all of our performance/frontend problems. Although it should provide a way to generate types separately (to gain speed benefits from the import type typescript's feature). There's no real benefit into supporting what we currently know as mode option. Also generated code shouldn't be edited/checked manually so readability does not applies here.

I would not trust any code generated by any code generator. Split mode allows us to easily manage the generated code with git, improve the review experience, and give us less conflicts

bottd commented 6 months ago

Future Orval idea: TypeSpec support? To be honest the worst part of using Orval is writing YAML. We can use TypeSpec with Orval today by compiling to OpenAPI then generating with Orval, but a YAML free workflow would be awesome. Given Microsoft support I think this standard will stay around, would be interesting to think about what features we could get by using TypeSpec as a generation source.

https://github.com/Microsoft/typespec https://typespec.io/x

weicong commented 2 months ago

I recommend referring to kubb

melloware commented 2 months ago

Kubb was just deprecated by its owner. You can read his reasons on his github page

EduardoAC commented 1 month ago

I appreciate the move towards ESM, but I have some reservations. In my experience, particularly with the projects I’ve been working on, supporting ESM correctly has been quite challenging. While I understand the push for outputting ESM, the "type": "module" setting has been a significant headache in several cases. There always seems to be something that doesn’t fully transform into ESM, leading to unexpected issues. A recent example of this is the vitest-chrome project, which illustrates some of the difficulties I've encountered.

On the positive side, I would love to see a better structure for the project that makes it easy to debug and test it effectively. I have spent some time researching how to add tests to validate certain functions or even try out the generator. I truly believe this project will benefit from a TDD approach to its development, and perhaps the architecture should be cleaned up.

Speaking from a naive perspective, please take it with a grain of salt. I propose rethinking what orval/core means; I feel the core should provide all the tools needed to generate the base configuration, including generation and evolution around additional features and have a good set of relevant tests. If it's hard to navigate, it's hard to contribute

beaussan commented 1 month ago

changing the config file.

JS in general is a bit too much unopinionated in my opinion, as long as we have a typesafe way to writing our configuration file, i'm happy with it. Not too permissive as cosmiconfig/cosmiconfig but nothing too strict as a json file, current orval.config.js is awesome but probably will have its current properties changed upon refactor in favor of v7. Custom config lookup/parsing/resolution usually takes a good portion of a CLI's runtime, so this should be taken care of.

One thing I wanted to mention, the current config file, being in JS, allows to have within a monorepo local codegen based on Orval, without the need to publish them on npm. It also allows to have presets within a monorepo to share configuration in a easier way. If the config is in yaml / json / whatnot, we may loose this kind of features and would need to happen on orval land instead of user land. This is a big part of why eslint moved back to js only (RFC from 2019 about it)