lex_gen 0.4.4
lex_gen: ^0.4.4 copied to clipboard
Provides a generator that automatically generates source code from the Lexicon in the AT Protocol.
Release Note #
0.4.4 #
- chore: bump
lexiconto^1.2.3.
0.4.3 #
- docs: fix the logo
alttext (atproto_core→lex_gen). - docs: add a real README documenting the programmatic API — the
Geninterface withServiceGen/CommandGenandexecute(), the config types (LexGenConfig,LexServiceRuleConfig,LexCommandRuleConfig,LexiconNamespaceRule), and thedoc_loaderhelpers — with a minimal configure-and-run snippet. - chore: bump
lexiconto^1.2.2.
0.4.2 #
Two-pass internal refactor of the code generator, plus emitter fixes. The net effect changes generated output (see the fixes below), so downstream regeneration is required. (Consolidates the previously-unreleased v0.4.2 and v0.4.3 entries.)
Emitter fixes (these change generated output):
- fix: lexicon descriptions and default values are escaped before interpolation, so text containing
",$,\, or newlines no longer produces uncompilable generated code. - fix: the generated repo-commit handler guards against a commit op whose block CID is absent from
blocks(previously threw aTypeError, aborting the whole commit). - fix: a bare
refto a record lexicon now resolves to the correct<Name>Recordtype instead of an empty class name.
IR migration (replaces the string-template emission mechanism with a small typed Dart intermediate representation (IR) + emitter; output byte-for-byte identical on its own):
- refactor: add
lib/src/ir/{dart_ir,dart_emitter}.dart— a purpose-built typed IR (DartFile/DartImport/DartClass/ members) with explicit member-order and blank-line control, rendered byemitDartFile. Because the codegen pipeline runsdart format, the emitter only needs to control member order, blank-line presence, comments and tokens;code_builderwas evaluated and rejected because it imposes its own member order and cannot express the intentional blank lines, so it cannot keep output byte-identical. - refactor: migrate every full-file emitter off its monolithic triple-quoted template onto the IR — the freezed data-class renderer (
object/{lex_object,lex_record,lex_input,lex_output}viarenderFreezedDataClass),LexKnownValues,LexUnion,LexService,RepoCommitHandler,AtUriExtension, and the command emitters (LexCommand's query/procedure/blobProcedure/record kinds,LexParentCommand,LexRootCommand). - refactor: model
importdirectives as structuredDartImports (uri +show/hide/as) instead of concatenated strings. This structurally eliminates the class of bug where an emittedimport '...';inside a template string was mis-hoisted byimport_sorter(the command emitters previously worked around this with a fragile concatenation and no longer need to). - test: add
srccheckmode toscripts/verify_gen_unchanged.sh(asserts the lex_gen source itself stays import_sorter-stable), and make it non-destructive to any uncommitted working-tree changes.
Structural/readability refactor (output byte-for-byte identical to v0.4.1 on its own, verified end-to-end by running the full pipeline gen_codes → build_runner → dart fix → import_sorter → dart format and asserting an empty git diff across atproto/bluesky/bluesky_cli):
- refactor: collapse
LexService's ~100-writelnrecord-accessor block into per-method emitters, unify the near-identicalcreate/putbodies and the query/procedure/subscription function↔method pairs, and split the import collector out of_getPackagePaths. - refactor: lift
RepoCommitHandler's constant DTO block out offormat()and unify theRepoCommitCreate/RepoCommitUpdateDTOs (which differ only bycreatedAt) into one parameterized emitter with a single-pass member builder. - refactor: remove the four duplicated
DartType.array(...)constructions inlex_property_generator's array switch, and replace the two parallel triple-nested ternaries (encoding the union/record/plain decision twice) with one resolved ref-variant. - refactor: extract a shared
FreezedModelbase holding the common fields and a single parameterized validate emitter forLexObject/LexRecord/LexInput/LexOutput. - refactor: flatten
lex_type_generator'sis ULexUserType*dispatch ladder into aswitch, and extract the byte-identical package-barrel writer and the doc-type classifier duplicated across the services orchestrators into a newservices_common.dart. - refactor: dedup the
*ForService/ absolute-path helper twins inservices/rule.dart(internal only; public API unchanged). - refactor: extract the repeated name/header preamble in the command emitter, dedup the three procedure templates, flatten the command def-dispatch loop into a classifier, and share the parent/root command import emitter.
- refactor: share the
isA-extension-getter idiom acrossutils/LexUnion/LexKnownValues(5 call sites) and nameLexKnownValues's inline@JsonValueelement builder. - refactor: rename the commands-world
LexParametertoLexCliParameterto remove the collision with the services-worldLexParameter(opposite meaning, zero shared code). - fix: make the record-command emitter import_sorter-safe. A source line reading
import '...';'''(an import flush against a triple-quoted string's closing''') was mis-hoisted byimport_sorterduringmelos fmt, corrupting the file even though the emitted output was unchanged; split the trailing import into a concatenated literal (emitted content identical). - test: add
scripts/verify_gen_unchanged.sh(output-invariance harness withcheck/full/srccheckmodes), used to verify this refactor.
0.4.1 #
Internal readability/standardization/optimization refactor. Generated output is byte-for-byte identical to v0.4.0 (verified by hashing the raw generator output across atproto/bluesky/bluesky_cli), so no downstream regeneration is required.
- refactor: introduce
Nsid/LexRefvalue objects (lib/src/model/) that parse a lexicon id / ref once, replacing ~40 inlinesplit('.')/split('#')sites across 8 files. - refactor: resolve a ref's related def in O(1) via a precomputed index instead of scanning every doc's every def per lookup (
getRelatedDocFromRef). - refactor: replace the mutually-exclusive
isQuery/isProcedure/isSubscription/isRecord(and commandisBlobProcedure) boolean sets withLexDefKind/LexCommandKindsealed enums dispatched by exhaustiveswitch. - refactor: unify the four byte-identical freezed data-class templates (
LexObject/LexRecord/LexInput/LexOutput) into a singlerenderFreezedDataClass. - perf:
getExtensionsname lookup is O(1) via a precomputed set (was O(n²));LexUnionresolves each ref name once instead of four times;RepoCommitHandlerresolves each record type name once instead of six times. - refactor: unify
RepoCommitHandler's near-identical_onCreate/_onUpdatefirehose event builders into a single parameterized_getMutationEvent. - refactor: split the 225-line
LexCommand._getRecordCommandinto per-subcommand emitters, unify the near-identicalcreate/putclasses into_recordMutationClass, and hoist the hardcodedcom.atproto.repo.getRecord/listRecordsmethod ids to named constants. - refactor: split
LexTypeinto a minimal base and aGeneratableTypesubtype, so the non-generatableLexMessagecontainer no longer throwsUnsupportedErrorfrom inheritedlexiconId/defName/getTypeName/formatmembers. - refactor: remove the module-level mutable state from both
rule.dartfiles (the_config/_defsByRefglobals and theirsetLexServiceRuleConfig/setLexiconDocs/setLexCommandRuleConfigsetters) in favour of an explicitGenContext(and the command config) threaded through the generators andrule.*helpers, so generation no longer depends on hidden global state or setter-call ordering and the helpers are unit-testable. - refactor: fix the
_LexLexXrpc*double-Lextype-name typos, deduplicate the record-accessorrkeyliteral handling and theLexOutputupload-ref predicate, remove deadgetDescriptionhelpers, and useputIfAbsentfor map aggregation. - test: add unit tests for
NsidandLexRef.
0.4.0 #
- fix: params-record refs are routed through the converter so a
$unknownmap picked up from a fetched object is no longer stored as a literal$unknownkey on records written to the PDS (G-1). - fix: generated
create()/put()now inject the record's$typeinto the record map, as required by the spec (G-2). - fix:
format: datetimeobject fields are UTC-normalized viaiso8601, so a localDateTime.now()no longer serializes to a timezone-less, spec-violating string (G-17). - fix:
required+nullablefields emitincludeIfNull: true, so a required-but-null key is no longer dropped from the wire JSON (G-19). - fix: deprecation detection is anchored to a leading
DEPRECATEDinstead of a substring match, so live fields are no longer silently removed (G-3). - fix: union
fromJsonsurfaces conversion errors instead of silently degrading valid-but-malformed payloads to.unknown(G-4). - fix: skip empty-
knownValuesenums (previously uncompilable) and map arrays of blobs toList<Blob>; escape string default values (G-7/G-8). - fix: a string with both
knownValuesand adefaultnow emits a const wrapper default (e.g.@Default(LabelValueDefinitionDefaultSetting.knownValue(data: KnownLabelValueDefinitionDefaultSetting.warn))) so the field is non-nullable and reports the spec default instead ofnull— e.g.com.atproto.label.defs#labelValueDefinition.defaultSetting(default: "warn"). Takes effect on the next downstream code regeneration (G-18). - docs: clarified that the
bytes(Map) /cid-link(String) IPLD mappings round-trip on every live path in the current corpus (firehose adapter pre-stringifies; JSON{"$bytes"}/{"$link"}shapes are stored/restored as-is); dedicated typed converters are deferred to avoid changing the shape firehose consumers read (G-6). - fix: generated CLI commands use a validated parse (
usageException), enforce required arrays, and share a record-args mixin (L-15). - test: new golden test harness (was zero tests) (G-15).
- chore: bump
lexiconto^1.2.0.
0.3.0 #
- feat: command generation (
bluesky_cli) is now fully aligned with the lexicon definitions:- Generate commands for procedures without input body (e.g.
com.atproto.server.refreshSession). - Generate commands for procedures with binary input via the new
BlobCommandbase class (e.g.com.atproto.repo.uploadBlob). - Generate commands for procedures whose input schema is a ref or union via a
--jsonoption (e.g.tools.ozone.set.upsertSet). - Emit typed values in request bodies: integers via
int.parse, JSON refs/unions/unknowns viajsonDecode, and arrays of objects decoded per element. - Guard omitted optional parameters with
wasParsedso they are no longer sent as empty arrays or default flags. - Record
get/listsubcommands send the correctcollection, usecom.atproto.repo.listRecords, and accept--repo. - Records include
$type,createno longer sends a"null"rkey, andput/deleterequire--rkey(literal record keys such asselfare applied automatically). - Kebab-case names keep digits attached to the preceding word (
search-posts-v2). - Usage lines show real option syntax (e.g.
--actor=<value>). - Multi-options whose items are JSON values are generated with
splitCommas: falseso JSON is not corrupted. lexCommandsis generated as a getter returning fresh command instances instead of a shared top-level list.
- Generate commands for procedures without input body (e.g.
0.2.1 #
- fix: sort loaded lexicon docs by NSID instead of file path so that generation results are deterministic across platforms and checkout locations.
0.2.0 #
- fix: generate
List<...>for object properties that reference a top-levelarraydefinition through a local ref (e.g.#draftEmbedGalleryItems). Such refs were previously treated as plain object refs and produced code pointing to a non-existent file. - feat: support lexicon ids with only three segments (e.g.
com.germnetwork.declaration), which previously threw aRangeErrorduring name generation. - feat: import records routed to the
atprotopackage (e.g.com.germnetwork.*) cross-package in the generatedRepoCommitHandler.
0.1.1 #
- Fixd minor functions.
0.1.0 #
- First release.