Open anymaniax opened 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.
I was also thinking about having a migrate command to do it easily for users
Another feature that would be handy is to add a zod schema generator
https://github.com/anymaniax/orval/issues/347(export MSW controllers to a separate index file) This one should be great to have :)
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!
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?
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.
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?
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?
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.
@Will-Mann-16 yes, this would be perfect, I'm searching for this solution.
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:
The bigger problem with splitting into multiple packages, is having to force the user to install them separately, if I understood right, it is supposed to be something like npm i -D @orval/core @orval/react-query
. Keeping these versions pined when releasing is the best we can do to avoid version mismatch, pnpm's workspace protocol helps a lot here. Here's how I did it with @kitajs/* repositories. Changesets is awesome too.
In code generation tools like this one, a good architecture is to provide an AST-like abstraction layer, firstly a package reads the swagger and convert it into orval AST/TypeNode with all needed information, then another package reads this proprietary AST and generates the code with it, ts-json-schema-generator
did it right, this allows someone to generate the orval's AST in their own way to be used with a imaginary @orval/react-query
, for example, or someone can use the AST generated by orval to write their own generator without having to hardcode orval and/or swagger related things. kitajs/parser also did something similar with its AST nodes.
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.
@arthurfiorette would love any help. Your plan sounds very ambitious.
@arthurfiorette can you contact me on discord to discuss it?
@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
@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
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.
Kubb was just deprecated by its owner. You can read his reasons on his github page
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
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)
I am already thinking about version 7 for a moment and wanted a place to talk about it.
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.
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
move to esm?
if you have any other ideas throw them here so that we can discuss it