DEV Community

Max Bantsevich
Max Bantsevich

Posted on • Originally published at dev.family

πŸš€ Autogeneration of data fetching functions and typing with Orval

The need for fast, high quality interface creation is increasing every day. As a result, developers are moving away from manually writing code that can be generated automatically. We have moved towards automation with a tool like Orval. We'll tell you how we did it, and share sample code and libraries (follow the links in the text).

Why we have abandoned manual data fetching

Our team philosophy is that if routine processes can be successfully automated, we will do it. And we will spend our free time on much higher priority things than writing repetitive code from project to project. For example, additional application optimisation.

Most of our projects consist of multiple CRUDs, and the number of queries can exceed a hundred. In the past, we used to manually describe data fetching queries and all the typing involved. It could look like this:



const getVacanciesData = async ({
 locale,
}: ServiceDefaultParams): Promise> => {
 try {
   const response: JsonResponse = await get({
     url: VACANCIES_ENDPOINT,
     headers: { ...getXLangHeader(locale) },
   });
   return { ok: true, data: response?.data || [] };
 } catch (e) {
   handleError(e);
   return { ok: false, data: undefined };
 }
};


export default getVacanciesData;


Enter fullscreen mode Exit fullscreen mode

Earlier we wrote an optimized API for sending requests to axios-based servers. You can find all the code with examples of services based on this API in our other article. By the way, the get method used in the screenshot above is part of this API.

The main disadvantage, apart from wasting time, is the high probability of making mistakes when creating such queries. For example, when setting optionality within types, or incorrectly passing the request body. And in the case of autogeneration, the error can ONLY be on the server side – the code relies on the yaml file created by the backend developer, so the responsibility is on one side.

Creating trivial queries on the front-end takes literally 0 seconds. And the only nuance we encountered during the whole time we were using autogeneration was the modification of existing queries. Namely, the creation of a layer in the form of an adapter. But this is not always necessary.

Using Orval for service generation therefore helps to save time and eliminate the possibility of errors on the front end.

Why is Orval

Next, let's look at the most important Orval settings and learn how to integrate autogeneration into our application.

Orval is a tool for generating client code for RESTful APIs based on OpenAPI specifications. Its official documentation can be found here.

For the basic configuration of Orval's behavior, it is enough to create a configuration file in the root of the project. It looks like this – orval.config.js

One of the most important configuration parameters is input. In orval.config.js it points to the source of the OpenAPI specification and contains various configuration options.

Let's have a look at it.

Input
This part of the configuration is responsible for importing and converting the OpenAPI file used.

target - required parameter that specifies the path to the OpenAPI file from which services are generated;
validation - parameter responsible for using the openapi-validator lint developed by IBM for OpenAPI. The default value is false. Includes a default set of rules which can be optionally extended in the .validaterc file;
override.transformer - OpenAPIObject as its first parameter and must return an object with the same structure;
filters - accepts an object with the tags key, to which an array of strings or a regular expression should be passed. If there are tags in the OpenAPI schema, it will filter by tags. If no tags are found, generation will return an empty file with title and version.

Output
This part of the configuration is responsible for setting up the generated code.

workspace - common path that will be used in subsequent specified paths within the output;
target - path to file containing the generated code;
client - the name of the data fetch client, or your own function with implementation (angular, axios, axios-functions, react-query, svelte-query, vue-query, swr, zod, fetch.);
schemas - path where TS types are generated (by default, types are generated in the file specified in target);
mode - a method of generating final files that includes the

  • single - a common file containing all generated code;
  • split -different files for querying and typing;
  • tags - the generation of a separate file for each tag from the OpenAPI;
  • tags-split - the generation of a directory for each tag in the destination folder and splitting of it into several files.

We have a look at the whole integration path and an example of the generated code here.

Why do you need autogeneration

Once you have adapted Orval to the realities of your project, you will save a lot of time that could be better spent on optimisation or refactoring.

It's necessary for use in:

  • Large projects with lots of endpoints – your front-end users will no longer have to manually write repetitive code, leaving them not only freer to work on higher priority tasks, but also happier;
  • Multi-developer teams – Orval generates standardized code, which helps maintain consistency and makes it easier to work with the code base;
  • Customisation for other projects – the tool can be customized to meet specific project requirements, including data transformation, endpoint filtering and other customisations.

Updating the API is also easier and faster: when the specification changes, Orval allows you to quickly generate updated functions and types, reducing the risk of outdated or incorrect code in your project.

Top comments (0)