Skip to content
/ oag Public

Idiomatic Go (Golang) client package generation from OpenAPI documents

License

Notifications You must be signed in to change notification settings

jbowes/oag

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

67 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

oag

Idiomatic Go client package generation from OpenAPI documents

Alpha Quality Build Status GitHub release MIT license codecov Go Report Card


Introduction

Introduction | Examples | Usage | Configuration | Contributing | License

🚧 Disclaimer: oag is alpha quality software. The API of generated code and configuration file format may change without warning between revisions. Please check your generated code before use! 🚧

oag generates idiomatic Go client packages from OpenAPI documents. OpenAPI 2.0 (née Swagger 2.0) is supported, with support for OpenAPI 3.0.0 coming soon.

Features

  • Idiomatic Concise Code: oag generates code modeled after some of Go's best REST API clients, like GitHub and Stripe.
  • Extensible: Generated code is written to a single file. You are free to add your own files to the package, adding behaviour to the generated types.
  • Fast: Code is generated in milliseconds.
  • Commit Friendly: Generated code is deterministic and stable. Multiple runs produce the same output. Document additions and removals create clean diffs.
  • Build Tool Friendly: If the generated code has not changed, nothing is written, and timestamps stay the same. A run of oag won't needlessly trigger other targets in make.
  • Single File Output: All generated code is written to a single file. Removals from an OpenAPI document won't result in orphaned generated files.

Examples

Introduction | Examples | Usage | Configuration | Contributing | License

The minimal petstore OpenAPI 2.0 example (edited for brevity):

// Client is an API client for all endpoints.
type Client struct {
    Pets *PetsClient
    // contains filtered or unexported fields
}

// New returns a new Client with the default configuration.
func New() *Client {}

// Pet is a data type for API communication.
type Pet struct {
    ID   int     `json:"id"`
    Name string  `json:"name"`
    Tag  *string `json:"tag"` // Optional
}

// PetIter Iterates over a result set of Pets.
type PetIter struct {
    // contains filtered or unexported fields
}

// Close closes the PetIter and releases any associated resources. After
// Close, any calls to Current will return an error.
func (i *PetIter) Close() {}

// Current returns the current Pet, and an optional error. Once an error
// has been returned, the PetIter is closed, or the end of iteration is
// reached, subsequent calls to Current will return an error.
func (i *PetIter) Current() (*Pet, error) {}

// Next advances the PetIter and returns a boolean indicating if the end
// has been reached. Next must be called before the first call to Current.
// Calls to Current after Next returns false will return an error.
func (i *PetIter) Next() bool {}

// PetsClient provides access to the /pets APIs
type PetsClient endpoint

// List corresponds to the GET /pets endpoint. Returns all pets from the
// system that the user has access to
func (c *PetsClient) List(ctx context.Context) *PetIter {}

View the complete generated client code

Usage

Introduction | Examples | Usage | Configuration | Contributing | License

Install oag

go get -u github.com/jbowes/oag

Initialize and edit your configuration file

# In the directory under your $GOPATH where your package will live
oag init
# Edit the created .oag.yaml file, following the comments

Generate and commit your code

oag
git add zz_oag_generated.go
git commit -m "Add autogenerated API client"

Implement the error interface for your error types

oag can determine which types are used as errors, but it does not know how you wish to present them.

Create a new file in the same package that implements error for your type. For example, if zz_oag_generated.go contained:

type APIError struct {
	ID	string `json:"id"`
	Message string `json:"message"`
	Class	string `json:"class"`
}

Where ID is some unique value generated per error, and Class is a group of error types, you could put the following in an error.go file:

// Error returns a string representation of this error
func (a *APIError) Error() string {
	return fmt.Sprintf("%s: %s (%s)", a.ID, a.Message, a.Class)
}

Configuration

Introduction | Examples | Usage | Configuration | Contributing | License

oag keeps its configuration in a separate file rather than relying on OpenAPI vendor extensions. If you are not the original author of the OpenAPI document, you don't need to carry patches to it to use oag.

By default, the file .oag.yaml is used for configuration. You may override this with the -c flag.

Configuration Directives

document

Required OpenAPI document to generate a client for.

Example:

document: ./openapi.yaml

package

The package path and optional name to use in the generated code.

Example:

package:
  path: github.com/jbowes/go-sample
  name: sample

types

Optional mapping of definitions to types.

Example:

types:
  SomeDefinedType: github.com/org/package.TypeName

string_formats

An optional map of OpenAPI format values to Go types. Schema fields, array items, and parameters that have these formats will be represented in the generated code with the provided type.

Any types used here must implement the TextMarshaler interface.

Example:

string_formats:
  telephone: github.com/org/package.TelephoneNumber

output

An optional override for the default output file.

Example:

output: zz_oag_generated_client_file.go

boilerplate

A niche configuration directive, allowing you to disable parts of oag's code generation, particularly for shipping generated code for multiple OpenAPI documents in the same package.

Example:

boilerplate:
  base_url: disabled
  backend: disabled
  endpoint: disabled
  client_prefix: PutThisBeforeTypeNames

Contributing

Introduction | Examples | Usage | Configuration | Contributing | License

I would love your help!

oag is still a work in progress. You can help by:

  • Trying oag against different OpenAPI documents, and reporting bugs when the generated code is broken, or suggesting improvements to the generated code.
  • Opening a pull request to resolve an open issue.
  • Adding a feature or enhancement of your own! If it might be big, please open an issue first so we can discuss it.
  • Improving this README or adding other documentation to oag.
  • Letting me know if you're using oag.

License

Introduction | Examples | Usage | Configuration | Contributing | License

MIT

MIT License

Copyright (c) 2017 James Bowes

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.