goagen, the goa Tool


Code Generation Tool

goagen is a tool that generates various artifacts from a goa design package.

Install it with:

go install github.com/goadesign/goa/goagen

Each type of artifact is associated with a goagen command that exposes it own set of flags. Internally these commands map to “generators” that contain the logic for generating the artifacts. It works something like this:

  1. goagen parses the command line to determine the type of output desired and invokes the appropriate generator.
  2. The generator writes the code of the tool that will produce the final output to a temporary directory.
  3. The tool composed of the design package and the tool code is compiled in the temporary directory.
  4. The tool is run, it traverses the design data structures to write the final output.

Each generator is exposed via a command of the goagen tool, goagen --help lists all the available commands. These are:

  • app: generates the service boilerplate code including controllers, contexts, media types and user types.
  • main: generates a skeleton file for each resource controller as well as a default main.
  • client: generates an API client Go package and tool.
  • js: generates a JavaScript API client.
  • swagger: generates the API Swagger specification.
  • schema: generates the API Hyper-schema JSON.
  • gen: invokes a third party generator.
  • bootstrap: invokes the app, main, client and swagger generators.

Common flags

The following flags apply to all the goagen commands:

  • --design|-d=DESIGN defines the Go package path to the service design package.
  • --out|-o=OUT specifies where to generate the files, defaults to the current directory.
  • --debug enables goagen debug. This causes goagen to print the content of the temporary files and to leave them around.
  • --help prints contextual help.

Contexts and Controllers: goagen app

The app command is arguably the most critical. It generates all the supporting code for the goa service. The command also generates a test sub-package that contain test helpers, one per controller action and view they return. These helpers make it easy to test the action implementations by invoking them with controlled values and validating the returned media types. This command supports a couple of additional flags:

  • --pkg=app specifies the name of the generated Go package, defaults to app. That’s also the name of the subdirectory that gets created to store the generated Go files.
  • --notest prevents the generation of the the test helpers.

This command always deletes and re-creates any pre-existing directory with the same name. The idea being that these files should never be edited.

Scaffolding: goagen main

The main command helps bootstrap a new goa service by generating a default main.go as well as a default (empty) implementation for each resource controller defined in the design package. By default this command only generates the files if they don’t exist in the output directory. This command accepts an additional flag:

  • --force causes the files to be generated even if files with the same name already exist.

Client Package and Tool: goagen client

The client command generates both an API client package and a CLI tool. The client package implements a Client object that exposes one method for each resource action. It also exposes methods to create the corresponding http request objects without sending them. The generated code of the CLI tool leverages the package to make the API requests to the service.

The Client object is configured to use request signers that get invoked prior to sending the request if security is enabled for the Action (that is if the action DSL makes use of the Security function). The signers modify the request to include auth headers for example. goa comes with signers that implement basic auth, JWT auth, API key and a subset of OAuth2.

JavaScript: goagen js

The js command generates a JavaScript API client suitable for both client-side and server-side applications. The generated code defines an anonymous AMD module and relies on the axios promise-based JavaScript library for making the actual HTTP requests.

The generated module wraps the axios client and adds API specific functions, for example:

// List all bottles in account optionally filtering by year
// path is the request path, the format is "/cellar/accounts/:accountID/bottles"
// years is used to build the request query string.
// config is an optional object to be merged into the config built by the function prior to making the request.
// The content of the config object is described here: https://github.com/mzabriskie/axios#request-api
// This function returns a promise which raises an error if the HTTP response is a 4xx or 5xx.
client.listBottle = function (path, years, config) {
        cfg = {
                timeout: timeout,
                url: urlPrefix + path,
                method: 'get',
                params: {
                        years: years
                },
                responseType: 'json'
        };
        if (config) {
                cfg = utils.merge(cfg, config);
        }
        return client(cfg);
}

The generated client module can be loaded using requirejs:

requirejs.config({
        paths: {
                axios: '/js/axios.min',
                client: '/js/client'
        }
});
requirejs(['client'], function (client) {
        client().listBottle ("/cellar/accounts/440/bottles", 317)
                .then(function (resp) {
                        // All good, use resp
                })
                .catch(function (resp) {
                        // Woops, request failed or returned 4xx or 5xx.
                });
});

The code above assumes that the generated files client.js and axios.min.js are both served from /js. The resp value returned to the promise is an object with the following fields:

{
        // `data` is the response that was provided by the server
        data: {},

        // `status` is the HTTP status code from the server response
        status: 200,

        // `statusText` is the HTTP status message from the server response
        statusText: 'OK',

        // `headers` is the headers that the server responded with
        headers: {},

        // `config` is the config that was provided to `axios` for the request
        config: {}
}

The generator also produces an example HTML and controller that can be mounted on a goa service to quickly test the JavaScript. Simply import the js Go package in your service main and mount the controller. The example HTML is served under /js so that loading this path in a browser will trigger the generated JavaScript.

Swagger: goagen swagger

The swagger command generates a Swagger specification of the API. The command does not accept additional flags. It generates both the Swagger JSON and YAML. The generated files can be served from the API itself using a file server defined in the design with Files

JSON Schema: goagen schema

The schema command generates a Heroku-like JSON hyper-schema representation of the API. It generates both the JSON as well as a controller that can be mounted on the goa service to serve it under /schema.json.

Plugins: goagen gen

The gen command makes it possible to invoke goagen plugins. This command accepts one flag:

  • --pkg-path=PKG-PATH specifies the Go package import path to the plugin package.

Refer to the Generator Plugins section for details on goa plugins.