atproto_codegen/lower
One-way lowering from atproto_lexicon/ast.LexiconDoc to the flat view
plugins consume. ast stays the faithful, bidirectional representation;
this module intentionally drops anything today’s plugins do not need
(method defs, record key strategy, constraint fields, descriptions) while
keeping a handle on the source doc so a later constraint-aware plugin can
still reach it. Growing the flat shape (e.g. surfacing a constraint) is
fine; this module must never grow the ability to go the other way.
A record/object def whose properties use a field type this pipeline
cannot render becomes FlatUnsupported rather than emitted wrong. A
query/procedure def becomes a FlatMethod (consumed by the xrpc-client
plugin, not the per-unit codec path); any other non-record/object def
(subscription, token, …) becomes FlatIgnored, since no plugin
generates code for those yet.
Types
One unit of generated code: a def’s own type/codec, or a synthesized union type for one of its union-typed fields. Plugins iterate the same unit list (built once here) so their per-unit outputs line up position for position when the host interleaves them.
pub type CodecUnit {
DefUnit(def: FlatDef)
UnionUnit(
def: FlatDef,
field: FlatField,
refs: List(String),
closed: Bool,
)
}
Constructors
-
DefUnit(def: FlatDef) -
A query/procedure body: its wire encoding and, when it carries a typed
payload, a schema that is either a ref to a def or an inline object. A
None schema is a real case (e.g. a multipart/form-data binary upload).
pub type FlatBody {
FlatBody(
encoding: String,
schema: option.Option(FlatBodySchema),
)
}
Constructors
-
FlatBody(encoding: String, schema: option.Option(FlatBodySchema))
A body’s payload shape. BodyUnsupported keeps an unrenderable body
(a union body, or an inline object with an unrenderable field) as data
so the plugin can raise a generation-time error naming the method,
mirroring how TUnsupported carries an unrenderable object field type.
pub type FlatBodySchema {
BodyRef(ref: String)
BodyInline(properties: List(FlatField))
BodyUnsupported(reason: String)
}
Constructors
-
BodyRef(ref: String) -
BodyInline(properties: List(FlatField)) -
BodyUnsupported(reason: String)
pub type FlatLexicon {
FlatLexicon(
nsid: String,
doc: ast.LexiconDoc,
defs: List(FlatDef),
)
}
Constructors
-
FlatLexicon( nsid: String, doc: ast.LexiconDoc, defs: List(FlatDef), )
pub type FlatType {
TString
TInt
TBool
TCidLink
TBytes
TBlob
TUnknown
TRef(String)
TArray(FlatType)
TUnion(refs: List(String), closed: Bool)
TUnsupported(String)
}
Constructors
-
TString -
TInt -
TBool -
TCidLink -
TBytes -
TBlob -
TUnknown -
TRef(String) -
TArray(FlatType) -
TUnion(refs: List(String), closed: Bool) -
TUnsupported(String)
A lowered query/procedure. params reuse FlatField (with nullable
always False, since params has no nullable notion); the plugin
derives its function/type names from nsid.
pub type Method {
Method(
nsid: String,
kind: MethodKind,
params: List(FlatField),
input: option.Option(FlatBody),
output: option.Option(FlatBody),
errors: List(MethodError),
)
}
Constructors
-
Method( nsid: String, kind: MethodKind, params: List(FlatField), input: option.Option(FlatBody), output: option.Option(FlatBody), errors: List(MethodError), )
pub type MethodError {
MethodError(name: String, description: option.Option(String))
}
Constructors
-
MethodError(name: String, description: option.Option(String))
pub type MethodKind {
MethodQuery
MethodProcedure
}
Constructors
-
MethodQuery -
MethodProcedure
Values
pub fn codec_units(defs: List(FlatDef)) -> List(CodecUnit)
The ordered codec units for one module’s emittable defs: each def’s own
unit, immediately followed by one unit per union-typed field on it, in
field order. Both the types and decode-json plugins fold over this
same list so their outputs line up position for position.
pub fn is_emittable(def: FlatDef) -> Bool
pub fn lower(docs: List(ast.LexiconDoc)) -> List(FlatLexicon)
pub fn method_of(def: FlatDef) -> option.Option(Method)
The lowered method for a def, when it is one. Methods are not emittable
through the per-unit codec path (is_emittable is False for them); the
xrpc-client plugin reads them off lex.defs via this accessor instead.
pub fn union_of(
ft: FlatType,
) -> option.Option(#(List(String), Bool))