derived
A Gleam library for parsing and generating code from Gleam custom types marked
with special !derived()
directives in their docstrings. Use it to build code
generators for serialization, validation, documentation, and more.
Features
- Docstrings: Parses documentation as part of the AST
- Parse Gleam types: Extract detailed type information from source code
- Code generation: Insert generated code back into source with proper markers
- Rich type support: Handles variants, fields, generics, attributes, and more
- Marker replacement: Automatically replaces existing generated code on re-runs
- Multiple derivations: Support multiple
!derived()
directives per type
Quick Start
gleam add derived@1
Basic Parsing
import derived
pub fn main() -> Nil {
let gleam_source = "
/// A custom type for demonstration
/// !derived(json)
pub type Person {
Person(name: String, age: Int)
}
"
let derived_types = derived.parse(gleam_source)
// Returns a list of DerivedType records containing parsed type information
}
Code Generation
import derived
import derived/ast
import gleam/list
import gleam/string
pub fn main() -> Nil {
let source = "
/// User type
/// !derived(json_schema)
pub type User {
/// A regular user account
User(name: String, age: Int)
/// An admin user account
Admin(name: String, permissions: List(String))
}
"
let result = derived.generate(source, generate_json_schema)
// Returns source with generated JSON schema inserted
}
fn generate_json_schema(derived_type: ast.DerivedType) -> Result(String, Nil) {
case list.contains(derived_type.derived_names, "json_schema") {
True -> {
let schema = build_json_schema(derived_type.parsed_type)
Ok(
"const "
<> string.lowercase(derived_type.parsed_type.name)
<> "_schema = "
<> schema
<> ";",
)
}
False -> Error(Nil)
}
}
How it works
- Mark types: Add
!derived(generator_name)
to type docstrings - Parse or generate: Use
derived.parse()
for inspection orderived.generate()
for code generation - Process results: Work with parsed type information or insert generated code
Examples
I had claude throw together a quick JSON Schema Generator
Documentation
API documentation can be found at https://hexdocs.pm/derived.
Development
gleam run # Run the project
gleam test # Run the tests
FAQ
- Why not use glance?
I wrote this because glance doesn’t currently support docstrings in types. Issue here When that issue is closed, I’ll switch this project to use Glance and remove the AST module.
- Why not use deriv?
You should!
For one thing, it’s two fewer characters to type! Think of the LLM tokens you’ll save!
To be honest, I didn’t know deriv
existed when I started this. I think this
package handles documentation strings better than deriv
(because it doesn’t
depend on glance), but it probably has some AST parsing bugs (also because it
doesn’t depend on glance).
This package also supports comment markers in code so you can regenerate output when you change the type.
- Shouldn’t this be in the gleam compiler?
Maybe? In gleam, derive
is a reserved keyword so the dev team is obviously
thinking about it. This project is a chance to explore ho that might might look
and what use cases it can solve.
-
What should I use this for?
-
Generating serializers and deserializers to various formats.
-
Generating a glint CLI parser based solely on an input type.
-
Generating schemas for various protocols.
-
Generating stubs for wisp handlers or lustre clients