# atproto_openapi

> **Alpha, pre-release.** Not yet published to Hex. Output shape and CLI
> flags are subject to change; expect breaking changes between 0.x releases.

A one-way emitter turning a set of [atproto lexicons](https://atproto.com/specs/lexicon)
into an [OpenAPI 3.1.0](https://spec.openapis.org/oas/v3.1.0) document,
built directly on [`atproto_lexicon`](https://hex.pm/packages/atproto_lexicon)'s AST. Sibling of
[`atproto_sdl`](https://hex.pm/packages/atproto_sdl) and [`atproto_mlf`](https://hex.pm/packages/atproto_mlf); a pure
transform plus a thin CLI.

## Installation

```sh
gleam add atproto_openapi
```

## Usage

```gleam
import atproto_lexicon/decoding
import atproto_openapi

let assert Ok(doc) = decoding.decode_json(source)
let options = atproto_openapi.Options(title: "atproto", version: "0.0.0", servers: [])
let assert Ok(generated) = atproto_openapi.generate([doc], options)

generated.json                    // the OpenAPI document, as a JSON string
generated.operation_count         // GET/POST paths emitted
generated.schema_count            // components/schemas entries emitted
generated.subscriptions_skipped   // subscription NSIDs excluded from paths
```

CLI, walking a directory of lexicon JSON and writing one OpenAPI document:

```sh
gleam run -m atproto_openapi -- <lexicons-dir> <out-file> [--title T] [--version V] [--server URL]
```

A lexicon file that fails to decode is reported and skipped rather than
aborting the run; `--server` may be repeated. The CLI prints a summary
(operation/schema counts) and names every subscription NSID it excluded
from `paths`, so the WSS gap is visible at the call site.

## Modules

| Module                 | What it does                                                                                    |
| ---------------------- | ----------------------------------------------------------------------------------------------- |
| `atproto_openapi`      | Public API: `generate` turns lexicon docs into one OpenAPI 3.1.0 document; `main` runs the CLI. |
| `atproto_openapi/refs` | Lexicon ref -> `components/schemas` key resolution; its `RefError` rides in the public `Error`. |

`cli`, `emit`, `paths`, and `schema` are internal.

## What it does NOT do

- No `subscription` defs in `paths`: WSS event streams aren't representable
  as OpenAPI operations. They're listed under the `x-atproto-subscriptions`
  vendor extension instead.
- No "try it out" server execution, no YAML output (JSON only for v1).
- This is a one-way transform: OpenAPI is never read back into a
  `LexiconDoc`.
- Output is compact JSON, not pretty-printed: `gleam_json` only exposes
  `json.to_string`, no pretty printer. Pipe through your formatter of
  choice (e.g. `jq .`) if you want it human-readable.
