# atproto_sdl
> **Alpha.** Grammar, CLI flags, and printed output are all subject to
> change. Not published; monorepo use only.
A Prisma/GraphQL-inspired schema language for
[atproto lexicons](https://atproto.com/specs/lexicon) ("Lexicon SDL"),
parsing to and printing from [`atproto_lexicon`](../atproto_lexicon)'s AST.
The printer is total: every AST construct has a spelling, so lexicon JSON
round-trips through SDL with zero exception files. Design authority:
[`docs/lexicon-sdl.md`](../docs/lexicon-sdl.md).
```
/// A forum-style shelf entry.
record shelfEntry @key(tid) {
title: String! @len(1, 200)
tags: [String @len(max: 64)] @max(10)
createdAt: Datetime!
}
query listReleases(q: String, limit: Int = 25 @range(1, 100)): releasePage
throws NotFound | Expired
```
## Installation
Monorepo path dependency:
```toml
[dependencies]
atproto_sdl = { path = "../atproto_sdl" }
```
## Usage
CLI, converting a tree of `.sdl`/`.json` files to the other format (NSID
derives from the file path; `--to json|sdl` restricts direction):
```sh
gleam run -m atproto_sdl -- <src-dir> <out-dir> [--to json|sdl]
```
Library:
```gleam
import atproto_sdl
import atproto_lexicon/encoding
let assert Ok(doc) = atproto_sdl.parse(source, "com.example.thing")
let sdl_text = atproto_sdl.print(doc)
let json_text = encoding.to_json_string(doc)
```
## Architecture
Text -> `lexer` -> `parser` (intermediate `tree`) -> `lower` -> `ast.LexiconDoc` -> `printer` -> text.
| Module | What it does |
| ----------------------- | ----------------------------------------------------------------------------------------------- |
| `token`, `lexer` | Token vocabulary; source -> spanned token stream |
| `tree` | Parser's intermediate tree |
| `parser` + `parser/*` | Tokens -> tree (`cursor`, `values`, `types` submodules) |
| `lower` + `lower/*` | Tree -> AST (`scope`, `attrs`, `fields`, `methods`) |
| `printer` + `printer/*` | AST -> SDL (`render`, `constraints`, `types`, `methods`); depends only on `atproto_lexicon/ast` |
| `pipeline`, `cli` | Lex+parse+lower entry points; tree converter |
| `error` | Spanned errors + `describe` |
Corpus status: 28/28 at-record lexicons and 25/25 vendored corpus files
round-trip decode -> print -> parse, print-idempotent (`gleam test`).