Skip to content
On this page

Code generation with OpenAPI

DANGER

Many users of Farfetched have reported that the organization https://github.com/openapi/ is basically abandoned by its maintainers, it does not work in various cases (example #1, example #2, example #3).

We are currently looking for a better alternative. If you have any suggestions, please let us know in issues.

Farfetched itself does not have any code generation capabilities. However, it is possible to use the OpenAPI specification (and its implementation Swagger) to generate code for the client with external open-source tools.

In this recipe, we will use the OpenAPI Generator with a special preset for Effector.

Preparations

  1. Install the OpenAPI Generator and the Effector preset:
sh
pnpm add --save-dev openapi@^1.0.0 openapi-preset-effector typed-contracts
sh
yarn add --dev openapi@^1.0.0 openapi-preset-effector typed-contracts
sh
npm install --dev openapi@^1.0.0 openapi-preset-effector typed-contracts

WARNING

openapi-preset-effector supports only typed-contracts for now, but integrations for runtypes, io-ts and superstruct on their ways.

To prevent using many contract systems in your project, we recommend using typed-contracts across the whole project. Farfetched supports it out of the box, read more the API reference for @farfetched/typed-contracts.

  1. Create base Effect that will be used in the generated code, put it in the ./src/api/shared/request.ts file. In general, it has to be any Effect with the following signature:
ts
export interface Request {
  path: string;
  method: string;
  body?: object | null | void;
  query?: Record<string, string>;
  headers?: Record<string, string>;
  cookies?: string;
}

export interface Answer {
  ok: boolean;
  body: unknown;
  status: number;
  headers: Record<string, string>;
}

export const requestFx = createEffect<Request, Answer, Answer>({
  handler: async (request) => {
    // ...
  },
});

TIP

The full code of the file is out of scope of this recipe, but you can find it in the example repository.

  1. Create a configuration file openapi.config.js in the root of your project with the following contents:
js
module.exports = {
  file: 'https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v2.0/json/petstore-minimal.json',
  outputDir: './src/api/shared',
  presets: [
    [
      'openapi-preset-effector',
      {
        effectorImport: 'effector',
        requestName: 'fetchFx',
        requestPath: './request',
      },
    ],
  ],
};

TIP

This recipe is based on the official example from the OpenAPI specification repository — perstore-minimal.json.

Generation

You are ready to generate the code. Run the following command:

sh
pnpm openapi
sh
yarn openapi
sh
npm openapi

The generated code will be placed in the ./src/api/shared directory. You must not touch it, because it will be overwritten on the next generation.

Make it farfetched

Generated code contains Effects, but Farfetched's APIs work only with Query or Mutation. So, we need to wrap the generated code with Farfetched's APIs. Let's create a file ./src/api/shared/index.ts with the following contents:

ts
import { createQuery } from '@farfetched/core';

import { petsGet } from './swagger-petstore';

export const petsQuery = createQuery({ effect: petsGet });

Now, you can use petsQuery in your code as simple as any other Query, for example:

ts
import { retry } from '@farfetched/core';

import { petsQuery } from './api/shared';

retry(petsQuery, {
  times: 3,
  delay: 1000,
});

Released under the MIT License.