-
Notifications
You must be signed in to change notification settings - Fork 16
OpenAPI spec based generation
This project demonstrates a pattern for automatic type and request generation of TypeScript types and API calls for the PetStore swagger spec. A few observations:
- The project automatically generates a package in
gen/api
, which is then imported into the main source code - The generated source creates async/await based functions that run a request with parameters and headers specified by the OpenAPI spec
- The generated source is then included as a module in the main react-redux-saga based application, which has access to strong types tied to API utility functions, but must still implement saga code by the old fashioned way
First glance takeaways:
- We could leverage this pattern (which uses
@openapitools/openapi-generator-cli
) to generate the base types and API calls for TAPIS and spin it off as a separate lower level repositorytapis-api
that can be consumed by any framework - The generated api calls could then be wrapped by
tapis-redux
middleware, replacing the generictapisFetch
utility function with calls to the external automatically generatedtapis-api
package - The generator, while useful for generating the types, does not automatically buy us well defined hooks and components. It simply resolves the type and API call generation on our behalf.
I made a working branch task/tui-19--openapi. This branch adds an npm command called "api". You can autogenerate from spec by doing the following:
- Make sure you have a Java runtime installed
- Install the openapi-generator-cli with
npm install -g @openapitools/openapi-generator-cli
(need to figure out how to properly configure this project for npx so that you don't have to install these commands to your global node_modules) - Run the api generator with
npm run api
This will autogenerate the Tenants API spec and place it in tapis-api. Here is what I found
- openapi-generator-cli, despite being a node package, requires a java virtual machine to be installed
- We may require a single OpenAPI spec for all the services, otherwise we will end up generating multiple API packages per individual service
- Upon trying to consume the TAPIS OpenAPI spec, it generates the many errors similar to this:
src/apis/index.ts:4:1 - error TS2308: Module './LdapsApi' has already exported a member named 'CreateLdapRequest'. Consider explicitly re-exporting to resolve the ambiguity.
4 export * from './TenantsApi';
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The generator cannot continue after this point. This may be caused by duplicate names. The LDAP specification contains CreateLdapRequest, and this is repeated in the Tenants specification.
Using this tool would either require manual curation of generated artifacts or changing the existing OpenAPI specs to resolve name conflicts. However, this is the official tool and is well supported with two years of development by 10 contributors.
Artifacts from this generator are available here.
This is a different tool available as an npm cli tool openapi-generator-plus
. This tool is plugin based and does not require Java. Documentation is sparse. This generator uses a different package generation strategy which avoids the naming export conflict. Additionally it generates types.
Artifacts from this generator are available here.
This tool works out of the box. This unofficial tool is a single developer project with a year of maturity. It could be dangerous to rely on this tool if it were to become unmaintained.
Both tools provide a way of specifying a "configuration" object that allows setting the base URL and any required auth headers.
It may be more feasible to spin off a separate tapis-typescript-api
project and publish it as an npm package that is consumed downstream by tapis-ui
, etc. This project could collate all of the various service specs and publish by version.
It appears that the OpenAPI spec for tenants often provides two slightly different types for POST objects. For example, Tenant
as a result and NewTenant
as a post body object. Both CLIs generated separate objects for each. If the OpenAPI spec is cleaned up to use inheritance, this may result in fewer automatically generated types and a better end user experience for the generated TypeScript types. A cursory glance at multiple TAPIS v3 services shows inconsistencies in naming between different services. For example, in the Tenants API objects schemas may be Tenant
and NewTenant
but in the Systems API it may be TSystem
and ReqCreateSystem
.
Before generating a public tool, it would be good to revise existing specifications for consistency as well as compatibility with the official openapi-generator-cli tool.