# OpenAI Client

Autogenerated client for OpenAI using the OpenAPI specification and [OpenAPI Generator](https://openapi-generator.tech/)

## Download API Specification

Requirements:
* File `openai-client/generator/config/openai-api-commit` with the desired commit of the OpenAI API

Running the task `downloadOpenAIAPI` will read that commit and download the specification into `openai-client/generator/config/openai-api.yaml`

```shell
./gradlew downloadOpenAIAPI
```

## Generate code

Requirements:
* File `openai-client/generator/config/openai-api.yaml` with the API specification

Running the task `openaiClientGenerate` will:
* Generate the code with OpenAI Generator using the configuration
* Run the task `spotlessApply`

```shell
./gradlew openaiClientGenerate
```

## Further Customization

We choose for a semi-manual approach to generate the code.
With a preference for a more controlled way of generating the code, so prefer custom template over workarounds.
This generator add support for `oneOf`, and potentially more in the future.

Since we focus on KMP, we use KotlinX Serialization and Ktor.
So by being opinionated, we can heavily simply the templates. Which is great for maintainability.

- [KMMGenerator](src/main/kotlin/com/openai/generator/KMMGenerator.kt) that generates the code.
- config/*.mustache files with the templates for the code generation.
  - api.mustache: invoked for each API endpoint. Generates interface, and smart-constructor.
  - openai.mustache: the OpenAI interface that exposes all the API endpoints, with fluent syntax.
  - model.mustache: invoked for each model. Delegate to the model templates (data, enum, oneOf). 
    - data.mustache: generates the data class for the model (including nested models).
    - enum.mustache: generates the enum class for the model (including nested models).
    - oneOf.mustache: generates the sealed class for the model (including nested models).

### Debugging

```
./gradlew openaiClientGenerate -PdebugModels=true > model.log
```
```
./gradlew openaiClientGenerate -PdebugOperations=true > operations.log
```

You can only debug one of the two properties at a time. _operations_ are used to debug the API endpoints, _models_ are used to debug the models.
It's best to dump the output in a file, such that you can inspect them in a more controlled way,
but they should be included in git!

### Mustache

[Mustache(5)](https://mustache.github.io) is being used as template engine,
with [Mustache Java](https://github.com/spullara/mustache.java).

Quick reference:
  - triple `{`: {{{var_name}}} is (HTML escaped)
  - double `{{`: {{var_name}} is plain value
  - {{#var_name}} ... {{/var_name}} is a section, drill down into model, for each, value present, etc.
  - {{^var_name}} ... {{/var_name}} is a negative section, if var_name is empty, or false, etc.
  - {{! comment }} is a comment
  - {{> partial }} is a partial, include another template
  - {{& var_name }} is a triple mustache without escaping
  - {{#-first}} ... {{/-first}} only execute for first/last element in an array
  - {{^-last}} ... {{/-last}} only execute for first/last element in an array
  - {{#lambda.name}} ... {{/lambda.name}} is a lambda, a function that can be called with a parameter
    - Following are available: (uppercase, snakecase, titlecase, kebabcase, camelcase, pascalcase, forwardslash, backslash, doublequote, indented, indented_8, indented_12, indented_16, escapeDollar)
    - And our custom ones: (oneOfName, capitalised, unquote, jsname)
