swagger-gen-js is a code generation tool. It takes as input a swagger specification for an API and produces redux reducers, redux actions, redux sagas, selectors, api middleware, and/or flow types suitable for use in a React/Redux based web application.
The goal of
swagger-gen-js is to remove as much as possible of the boilerplate normally required to write a full-featured
redux-saga-based webapp. A moderately complicated project using
redux-saga to handle making API calls as side effects to
redux actions can easily require thousands of lines of boilerplate redux actions, reducers, and sagas just to do repetitive tasks. This leaves the project open to subtle inconsistencies and bugs in API interaction logic, vastly more code to maintain, and wasted devloper effort on otherwise simple tasks.
How to Use
The command line options are:
--debug: If set, builds produce logging output in
./log. Default: false. Debug may also be set in the config file as described below.
--options: String path to the config file. Default:
--verbose: If set, build progress is reported via
console.info(). Default: false
swagger-gen-js configuration is done with a configuration file. For details, see Configuration.
There is little point to using
swagger-gen-js without generating (at least) reducers, sagas, selectors, action creators, and flow types. These guidelines assume these are all available.
swagger-gen-js output should not share directories with handwritten code. A simple way to achieve this is to give all the directory paths a suffix like
_gen. This also makes it easier to clean all generated code before builds. The generated output directories should be relatively close together in the directory tree. This will make it easier to trace the relationships between the generated files and make their output more readable.
operationId translations for the endpoints you plan to use. This allows you to make the output more readable. In cases where
operationIds in specifications change while the endpoints stay the same (such as when upgrading to a new spec version) having such translations will you to change the target
operationId without needing to update imports everywhere the generated output is consumed. Do not use
operationId translations for endpoints you are not using, as it will make the configuration file unncessarily long and obscure what you actually care about using in your app.
output.include config option to whitelist the tags to generate. This makes it easier to see which modules you're actually using. It also means the generated reducer won't fill your store with unused state.
Take advantage of the generated flow types when preparing actions to trigger API requests. Each api module exports flow types for the request body and params it expects. You can use these in your handwritten sagas to detect malformed data before making the request at all.
The generated reducers directory includes an
index.js which exports a reducer combining all the generated reducers and an accompanying flow type. Composing the generated reducer into your store reduces the boilerplate involved in consuming all the generated reducers individually. If you do this, remember to put the reducer in the same place in the store as was configured in the
api_reducer_location config option.
swagger-gen-js uses a recent version of
redux-actions. As a result, the generated action creators do not require separately defined action constants. When listening for a generated action type, use the
toString() method of the action creator. This makes it easier to search for where a given action is being used, and saves the boilerplate of separately defining and exporting string constants. Similarly, reducers created with
handleActions() can be created using a
Map keyed by the action creators directly instead of an object which must be keyed by a string.
What not to use
Avoid using the
output.spec_overrides config option in the long term. It is intended for cases where a specification does not match the actual behavior of the API it documents. In cases like those, you should do your best to have a fix implemented upstream. The spec override will allow you to continue work while the issue is resolved. Overrides should be removed as soon as they cease to be relevant.
Avoid storing data returned from an api call in handwritten reducers unless there is a specific need. Doing so runs the risk of contradictions between local and server-side versions of data or of subtle errors in the locally stored data. The generated reducer handles storing the most recent successes and failures. Good reasons to store data in handwritten reducers are for extra caching (eg. storing multiple preceding exceptions) and for keeping a subset of a response for persistence (eg. storing only a part of a customer profile in a cookie).
Do not access the generated state directly - instead, use the generated selectors. This will provide you with stronger type checking and allow you to benefit from memoization.
Do not use the generated action creators for ANYTHING except triggering and handling api interaction. This means that usually the only generated actions you should dispatch should be the
REQUEST actions, and only for the sole purpose of commencing API activity. The response actions are useful for eg. dispatching an analytics event in the event of a server exception, but should not be used manually for such purposes. Doing so will overwrite the data stored in the generated reducers.
Avoid using the api modules directly. They are available in case you need to use them in some way outside the assumptions made by
swagger-gen-js, but by using them directly you lose all the redux-related benefits of
swagger-gen-js and must handle input validation and responses entirely on your own.
What to commit
There are a few ways to use
The first way to use it is as a build-time tool to generate code used at runtime. In this case, the json input files should be committed to the repo. The upside to this approach is that there is only one source of truth as to what is actually produced. The downside is that a substantial portion of the actual content of a build is only known for sure at build time. In this case, the output target directories should be added to
.gitignore. Most projects currently using
swagger-gen-js follow this pattern, and it is the one we recommend in general.
swagger-gen-js provides a utility to download a swagger spec at build time based on the
specs setting in the config file. You can use that at build time to select a spec to use instead of committing the spec file. In this case you have the advantage of always using the latest spec, but you will no longer have reproducible builds.
swagger-gen-js also works as dev-time tool to generate code which is then committed to the repo directly. In this case, the generated files are committed. It is often helpful in this case to commit the source specs as well, but that runs the risk of the two getting out of sync. The upside to this approach is that it's very clear what actual code has changed when updating to new spec versions or changing settings. The downside is that the potentially large number of lines changed in response to configuration changes or minor spec revisions can make the diffs less useful.
swagger-gen-js exposes some internal utilities for use alongside
swagger-gen-js-generated code, or even alone.
For documentation on the available utilities, see Utilities.
For documentation on the inner workings of
swagger-gen-js, refer to Generators.