···67676868.PHONY: lexgen
6969lexgen: ## Run codegen tool for lexicons (lexicon JSON to Go packages)
7070- go run ./cmd/lexgen/ --package bsky --prefix app.bsky --outdir api/bsky $(LEXDIR)
7171- go run ./cmd/lexgen/ --package atproto --prefix com.atproto --outdir api/atproto $(LEXDIR)
7272- go run ./cmd/lexgen/ --package chat --prefix chat.bsky --outdir api/chat $(LEXDIR)
7373- go run ./cmd/lexgen/ --package ozone --prefix tools.ozone --outdir api/ozone $(LEXDIR)
7070+ go run ./cmd/lexgen/ $(LEXDIR)
74717572.PHONY: cborgen
7673cborgen: ## Run codegen tool for CBOR serialization
+11-37
cmd/lexgen/main.go
···1111 cli "github.com/urfave/cli/v2"
1212)
13131414-func findSchemas(dir string) ([]string, error) {
1515- var out []string
1414+func findSchemas(dir string, out []string) ([]string, error) {
1615 err := filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error {
1716 if err != nil {
1817 return err
···2928 return nil
3029 })
3130 if err != nil {
3232- return nil, err
3131+ return out, err
3332 }
34333534 return out, nil
36353736}
38373838+// for direct .json lexicon files or directories containing lexicon .json files, get one flat list of all paths to .json files
3939func expandArgs(args []string) ([]string, error) {
4040 var out []string
4141 for _, a := range args {
···4444 return nil, err
4545 }
4646 if st.IsDir() {
4747- s, err := findSchemas(a)
4747+ out, err = findSchemas(a, out)
4848 if err != nil {
4949 return nil, err
5050 }
5151- out = append(out, s...)
5251 } else if strings.HasSuffix(a, ".json") {
5352 out = append(out, a)
5453 }
···8281 },
8382 }
8483 app.Action = func(cctx *cli.Context) error {
8585- outdir := cctx.String("outdir")
8686- if outdir == "" {
8787- return fmt.Errorf("must specify output directory (--outdir)")
8888- }
8989-9090- prefix := cctx.String("prefix")
9191-9284 paths, err := expandArgs(cctx.Args().Slice())
9385 if err != nil {
9486 return err
···108100 schemas = append(schemas, s)
109101 }
110102111111- pkgname := cctx.String("package")
112112-113113- imports := map[string]string{
114114- "app.bsky": "github.com/bluesky-social/indigo/api/bsky",
115115- "com.atproto": "github.com/bluesky-social/indigo/api/atproto",
116116- }
117117-118103 if cctx.Bool("gen-server") {
119119- defmap := lex.BuildExtDefMap(schemas, []string{"com.atproto", "app.bsky"})
104104+ pkgname := cctx.String("package")
105105+ outdir := cctx.String("outdir")
106106+ if outdir == "" {
107107+ return fmt.Errorf("must specify output directory (--outdir)")
108108+ }
109109+ defmap := lex.BuildExtDefMap(schemas)
120110 _ = defmap
121111122112 paths := cctx.StringSlice("types-import")
···133123 }
134124135125 } else {
136136- defmap := lex.BuildExtDefMap(schemas, []string{"com.atproto", "app.bsky"})
137137-138138- // Run this twice as a hack to deal with indirect references referencing indirect references.
139139- // This part of the codegen needs to be redone
140140- lex.FixRecordReferences(schemas, defmap, prefix)
141141- lex.FixRecordReferences(schemas, defmap, prefix)
142142- for i, s := range schemas {
143143- if !strings.HasPrefix(s.ID, prefix) {
144144- continue
145145- }
146146-147147- fname := filepath.Join(outdir, s.Name()+".go")
148148-149149- if err := lex.GenCodeForSchema(pkgname, prefix, fname, true, s, defmap, imports); err != nil {
150150- return fmt.Errorf("failed to process schema %q: %w", paths[i], err)
151151- }
152152- }
126126+ return lex.Run(schemas)
153127 }
154128155129 return nil
+61-10
lex/gen.go
···2525)
26262727type Schema struct {
2828+ path string
2829 prefix string
29303031 Lexicon int `json:"lexicon"`
···5051}
51525253type TypeSchema struct {
5353- prefix string
5454- id string
5555- defName string
5454+ prefix string // prefix of a major package being processed, e.g. com.atproto
5555+ id string // parent Schema.ID
5656+ defName string // parent Schema.Defs[defName] points to this *TypeSchema
5657 defMap map[string]*ExtDef
5758 needsCbor bool
5859 needsType bool
···149150 if ts.Type == "ref" {
150151 refname := ts.Ref
151152 if strings.HasPrefix(refname, "#") {
152152- fmt.Println("Foo")
153153 refname = s.ID + ts.Ref
154154 }
155155···222222 if err := json.NewDecoder(fi).Decode(&s); err != nil {
223223 return nil, err
224224 }
225225+ s.path = f
225226226227 return &s, nil
227228}
228229229229-func BuildExtDefMap(ss []*Schema, prefixes []string) map[string]*ExtDef {
230230+// Build total map of all types defined inside schemas.
231231+// Return map from fully qualified type name to its *TypeSchema
232232+func BuildExtDefMap(ss []*Schema) map[string]*ExtDef {
230233 out := make(map[string]*ExtDef)
231234 for _, s := range ss {
232235 for k, d := range s.Defs {
···235238 d.defName = k
236239237240 var pref string
238238- for _, p := range prefixes {
239239- if strings.HasPrefix(s.ID, p) {
240240- pref = p
241241+ for _, pkg := range Packages {
242242+ if strings.HasPrefix(s.ID, pkg.Prefix) {
243243+ pref = pkg.Prefix
241244 break
242245 }
243246 }
···300303 }
301304}
302305303303-func GenCodeForSchema(pkg string, prefix string, fname string, reqcode bool, s *Schema, defmap map[string]*ExtDef, imports map[string]string) error {
306306+func GenCodeForSchema(pkg string, prefix string, fname string, reqcode bool, s *Schema, defmap map[string]*ExtDef) error {
304307 buf := new(bytes.Buffer)
305308 pf := printerf(buf)
306309···324327 pf("\tcbg \"github.com/whyrusleeping/cbor-gen\"\n")
325328 pf("\t\"github.com/bluesky-social/indigo/xrpc\"\n")
326329 pf("\t\"github.com/bluesky-social/indigo/lex/util\"\n")
327327- for k, v := range imports {
330330+ for k, v := range prefixToGoImport {
328331 if k != prefix {
329332 pf("\t%s %q\n", importNameForPrefix(k), v)
330333 }
···1470147314711474 return nil
14721475}
14761476+14771477+type Package struct {
14781478+ GoPackage string
14791479+ Prefix string
14801480+ Outdir string
14811481+}
14821482+14831483+var Packages []Package = []Package{
14841484+ Package{"bsky", "app.bsky", "api/bsky"},
14851485+ Package{"atproto", "com.atproto", "api/atproto"},
14861486+ Package{"chat", "chat.bsky", "api/chat"},
14871487+ Package{"ozone", "tools.ozone", "api/ozone"},
14881488+}
14891489+14901490+var prefixToGoImport map[string]string
14911491+14921492+func init() {
14931493+ prefixToGoImport = map[string]string{
14941494+ "app.bsky": "github.com/bluesky-social/indigo/api/bsky",
14951495+ "chat.bsky": "github.com/bluesky-social/indigo/api/chat",
14961496+ "com.atproto": "github.com/bluesky-social/indigo/api/atproto",
14971497+ "tools.ozone": "github.com/bluesky-social/indigo/api/ozone",
14981498+ }
14991499+}
15001500+15011501+func Run(schemas []*Schema) error {
15021502+ defmap := BuildExtDefMap(schemas)
15031503+15041504+ for _, pkg := range Packages {
15051505+ prefix := pkg.Prefix
15061506+ FixRecordReferences(schemas, defmap, prefix)
15071507+ }
15081508+15091509+ for _, pkg := range Packages {
15101510+ for _, s := range schemas {
15111511+ if !strings.HasPrefix(s.ID, pkg.Prefix) {
15121512+ continue
15131513+ }
15141514+15151515+ fname := filepath.Join(pkg.Outdir, s.Name()+".go")
15161516+15171517+ if err := GenCodeForSchema(pkg.GoPackage, pkg.Prefix, fname, true, s, defmap); err != nil {
15181518+ return fmt.Errorf("failed to process schema %q: %w", s.path, err)
15191519+ }
15201520+ }
15211521+ }
15221522+ return nil
15231523+}