Current section

Files

Jump to
oaspec src oaspec codegen ir.gleam
Raw

src/oaspec/codegen/ir.gleam

/// Gleam Code IR - intermediate representation for generated Gleam source files.
/// This separates schema semantics from text rendering, preventing the
/// duplication of logic across types/decoders/client generators.
import gleam/option.{type Option}
/// A complete generated Gleam source file.
///
/// Opaque: construct via `module/3`, read via `module_header/1`,
/// `module_imports/1`, and `module_declarations/1`. The internal shape
/// can then evolve (e.g. to track file-level doc comments) without
/// rippling into every renderer pass.
pub opaque type Module {
Module(
header: String,
imports: List(String),
declarations: List(Declaration),
header_records: List(ResponseHeaderRecord),
)
}
/// Construct a `Module` from its three component pieces.
pub fn module(
header header: String,
imports imports: List(String),
declarations declarations: List(Declaration),
) -> Module {
Module(header:, imports:, declarations:, header_records: [])
}
/// Construct a `Module` with header records.
pub fn module_with_header_records(
header header: String,
imports imports: List(String),
declarations declarations: List(Declaration),
header_records header_records: List(ResponseHeaderRecord),
) -> Module {
Module(header:, imports:, declarations:, header_records:)
}
/// Module imports, in the order they should be rendered.
pub fn module_imports(m: Module) -> List(String) {
m.imports
}
/// Top-level declarations inside the module.
pub fn module_declarations(m: Module) -> List(Declaration) {
m.declarations
}
/// A top-level declaration with optional doc comment.
///
/// Opaque: construct via `declaration/2`, read via `declaration_doc/1`
/// and `declaration_type_def/1`.
pub opaque type Declaration {
Declaration(doc: Option(String), type_def: TypeDef)
}
/// Construct a `Declaration` from its optional doc and type definition.
pub fn declaration(
doc doc: Option(String),
type_def type_def: TypeDef,
) -> Declaration {
Declaration(doc:, type_def:)
}
/// Optional doc comment attached to this declaration.
pub fn declaration_doc(d: Declaration) -> Option(String) {
d.doc
}
/// The type definition carried by this declaration.
pub fn declaration_type_def(d: Declaration) -> TypeDef {
d.type_def
}
/// The shapes of type definition that the OpenAPI generator produces.
pub type TypeDef {
/// `pub type Foo = Bar`
TypeAlias(name: String, target: String)
/// `pub type Foo { Foo(field1: Type1, field2: Type2) }`
RecordType(name: String, fields: List(Field))
/// `pub type Foo { FooBar(Bar) FooBaz(Baz) }`
UnionType(name: String, variants: List(Variant))
/// `pub type Status { StatusActive StatusInactive }`
EnumType(name: String, variants: List(String))
}
/// A named, typed field in a record constructor.
pub type Field {
Field(name: String, type_expr: String)
}
/// A variant in a union type.
pub type Variant {
/// Variant with a wrapped type: `FooBar(Bar)`
VariantWithType(name: String, inner_type: String)
/// Variant with no payload: `FooNone`
VariantEmpty(name: String)
}
/// A typed record for response headers.
pub type ResponseHeaderRecord {
ResponseHeaderRecord(name: String, fields: List(Field))
}
/// Response header records inside the module.
pub fn module_header_records(m: Module) -> List(ResponseHeaderRecord) {
m.header_records
}