README.md

# OpenAPI Generator for Elixir

[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md) 

_A highly-configurable code generator that combines ergonomics with maintainability._

---

[OpenAPI](https://swagger.io/specification/) is a standard way to describe REST APIs on the web.
Anyone can create an OpenAPI description document that includes the available endpoints, expected request data, and possible responses.
For example, [GitHub](https://github.com/github/rest-api-description) maintains a comprehensive OpenAPI description for their services.

Generating code from an OpenAPI description can be relatively easy — this project [certainly isn't the first](https://openapi-generator.tech/docs/generators/elixir) — but there's a catch: API descriptions often don't translate into ergonomic code.
Most users of an API client library don't want to think about the difference between a `NullableRepository` and `Repository`, as in the GitHub API description.
(They have the same fields, but one has `nullable: true`.)
Users just want to get back a `%Repository{}` or `nil`.

The goal of this library is to create **ergonomic** client libraries from OpenAPI descriptions.
At the same time, the changes made to the code are easily repeatable (fully automated) for the sake of maintainability.
Think: the friendliness of your favorite hand-crafted client library applied to the scale of large APIs.

For more on how this is accomplished, see **Configuration** below.


## Installation

OpenAPI Generator is not yet available on Hex.pm.
In the meantime, please install it directly from GitHub:

```elixir
def deps do
  [
    {:oapi_generator, github: "aj-foster/open-api-generator", branch: "main"}
  ]
end
```

Be aware that the `main` branch may occasionally include unstable updates.


## Configuration

The real power of this library is in the available configuration.
Although the options are conceptually simple, they add up to a better user experience.

This project uses configuration profiles to allow multiple configurations with the same package.
To get started, create a profile called `default` in your configuration:

```elixir
config :oapi_generator,
  default: [
    base_location: "lib/example",
    base_module: Example
  ]
```

This is the minimum viable configuration for the generator.
It will create modules namespaced with `Example.` and save files in `lib/example`.
For a full list of configuration options, see the documentation for `OpenAPI.Config`.

### Output Module Naming

When the generator encounters a schema in the OpenAPI description, it performs a number of steps to determine the final name (module and type) of the schema that will be output to a file:

1. Based on the schema's location in the document, a provisional name is assigned.
  For example, `#/components/schemas/full-repository` becomes `FullRepository.t()`.

2. Schemas are **merged** based on the `merge` configuration key.
  For example, you may choose to merge `FullRepository.t()` into the `Repository.t()` schema to create `Repository.full()`.
  If two merged schemas have identical fields, then they will get the same name.

3. Schemas can be **ignored** using the `ignore` configuration key.
  Ignored schemas will be typed as simple `map()` types elsewhere in the generated code.

4. Schemas can be **renamed** using the `rename` configuration key.
  For example, you may wish to add or remove a word, change plurality, etc.

5. Finally, schemas can be **grouped** using the `group` configuration key.
  For example, a group of `Repository` would change `RepositoryInvitation` to `Repository.Invitation`.

The final module and type will be consistent in the output schema files and other files that reference them.

The `config/config.exs` file for this repository contains an example configuration related to the GitHub API description.
It includes a large number of groups for easily readable module names, merges for repeated or highly related schemas, and some module renaming for ease-of-use.


## Usage

Once the library is installed and configured, use `mix api.gen` with the name of the configuration profile and the OpenAPI description file:

```shell
mix api.gen default ../rest-api-description/spec.yaml
```

## Further Reading

* [Code of Conduct](CODE_OF_CONDUCT.md)
* [Contribution Guidelines](CONTRIBUTING.md)
* [License](LICENSE)
* [OpenAPI Specification](https://swagger.io/specification/)


## Sponsorship

If you like this library or it makes you money, please consider [sponsoring](https://github.com/sponsors/aj-foster).