Generating JavaScript API Clients from Open API specifications.

Grayscale Photo of Computer Laptop Near White Notebook and Ceramic Mug on Table

One of the issues I encounter when building client/server applications is that model classes are often duplicated on both sides. In the past I have used feathers.js which solved this problem by providing feathers-client, a client-side counterpart to the server implementation. More recently I am looking into IBM’s Loopback framework which has built-in support for auto-generated OpenAPI specifications available on the /openapi.json endpoint. More on this later.

For the client, I started off with a create-react-app template and added the Ant.Design UI framework on top. I originally wanted to use fetch to handle all API related communication but quickly realised the amount of boilerplate I would have to write out by hand. (basically writing out an API client library by hand).

Introducing openapi-client-axios, a Javascript client generator that will take care of all that for you. All I had to do was overwrite the operationId in the Loopback server code. This is because the framework generates Ids that are not valid method names (they contain a space). This is a bit of an oversight in their implementation, but fixing it is not a big deal.

I simply added “operationId” below the responses object in each controller action and the generated openapi.json was updated accordingly.+

@get('/accounts', {
    "operationId" : "getAccounts",
    responses: {
      '200': {
        description: 'Array of Account model instances',
        content: {
          'application/json': {
            schema: {
              type: 'array',
              items: getModelSchemaRef(Account, {includeRelations: true}),
            },
          },
        },
      },
    }
  })
  async find(
    @param.query.object('filter', getFilterSchemaFor(Account)) filter?: Filter,
  ): Promise {
    return this.accountRepository.find(filter);
  }

To set up OpenAPIClientAxios in my react project, I created a new file api.js with the following content:

const api = new OpenAPIClientAxios({ definition: 'http://localhost:3000/openapi.json' });
api.init();

async function getAccounts() {
  const client = await api.getClient();
  console.log(client)
  const res = await client.getAccounts();
  console.log('Accounts queried: ', res.data);
}

 createTodo().then(r => console.log(r))

This initialises the Client and retrieves all accounts before printing them to the console.

I am really happy with this setup because it allows me to consume the API without writing boilerplate code.

Related posts

Fixing Parse Server Request Entity Too Large Error with Node.js and JavaScript: Troubleshooting Permission Errors

Taking playlist randomisation into my own hands – using Javascript to improve Spotify’s Broken Shuffle

PouchDB TypeError: Cannot set property ‘_rev’ of undefined

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Read More