this repo has no description
at main 5.2 kB view raw
1// MIT License Bluesky Social 2// 3// Permission is hereby granted, free of charge, to any person obtaining a copy 4// of this software and associated documentation files (the "Software"), to deal 5// in the Software without restriction, including without limitation the rights 6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7// copies of the Software, and to permit persons to whom the Software is 8// furnished to do so, subject to the following conditions: 9// 10// The above copyright notice and this permission notice shall be included in all 11// copies or substantial portions of the Software. 12// 13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19// SOFTWARE. 20 21package main 22 23import ( 24 "errors" 25 "fmt" 26 "io/fs" 27 "log" 28 "os" 29 "path/filepath" 30 "strings" 31 32 "github.com/bluesky-social/indigo/lex" 33 "github.com/urfave/cli/v2" 34) 35 36func findSchemas(dir string, out []string) ([]string, error) { 37 err := filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error { 38 if err != nil { 39 return err 40 } 41 42 if info.IsDir() { 43 return nil 44 } 45 46 if strings.HasSuffix(path, ".json") { 47 out = append(out, path) 48 } 49 50 return nil 51 }) 52 if err != nil { 53 return out, err 54 } 55 56 return out, nil 57 58} 59 60// for direct .json lexicon files or directories containing lexicon .json files, get one flat list of all paths to .json files 61func expandArgs(args []string) ([]string, error) { 62 var out []string 63 for _, a := range args { 64 st, err := os.Stat(a) 65 if err != nil { 66 return nil, err 67 } 68 if st.IsDir() { 69 out, err = findSchemas(a, out) 70 if err != nil { 71 return nil, err 72 } 73 } else if strings.HasSuffix(a, ".json") { 74 out = append(out, a) 75 } 76 } 77 78 return out, nil 79} 80 81func main() { 82 app := cli.NewApp() 83 84 app.Flags = []cli.Flag{ 85 &cli.StringFlag{ 86 Name: "outdir", 87 }, 88 &cli.BoolFlag{ 89 Name: "gen-server", 90 }, 91 &cli.BoolFlag{ 92 Name: "gen-handlers", 93 }, 94 &cli.StringSliceFlag{ 95 Name: "types-import", 96 }, 97 &cli.StringSliceFlag{ 98 Name: "external-lexicons", 99 }, 100 &cli.StringFlag{ 101 Name: "package", 102 Value: "schemagen", 103 }, 104 &cli.StringFlag{ 105 Name: "build", 106 Value: "", 107 }, 108 &cli.StringFlag{ 109 Name: "build-file", 110 Value: "", 111 }, 112 } 113 app.Action = func(cctx *cli.Context) error { 114 paths, err := expandArgs(cctx.Args().Slice()) 115 if err != nil { 116 return err 117 } 118 119 var schemas []*lex.Schema 120 for _, arg := range paths { 121 if strings.HasSuffix(arg, "com/atproto/temp/importRepo.json") { 122 fmt.Printf("skipping schema: %s\n", arg) 123 continue 124 } 125 s, err := lex.ReadSchema(arg) 126 if err != nil { 127 return fmt.Errorf("failed to read file %q: %w", arg, err) 128 } 129 130 schemas = append(schemas, s) 131 } 132 133 externalPaths, err := expandArgs(cctx.StringSlice("external-lexicons")) 134 if err != nil { 135 return err 136 } 137 var externalSchemas []*lex.Schema 138 for _, arg := range externalPaths { 139 s, err := lex.ReadSchema(arg) 140 if err != nil { 141 return fmt.Errorf("failed to read file %q: %w", arg, err) 142 } 143 144 externalSchemas = append(externalSchemas, s) 145 } 146 147 buildLiteral := cctx.String("build") 148 buildPath := cctx.String("build-file") 149 var packages []lex.Package 150 if buildLiteral != "" { 151 if buildPath != "" { 152 return errors.New("must not set both --build and --build-file") 153 } 154 packages, err = lex.ParsePackages([]byte(buildLiteral)) 155 if err != nil { 156 return fmt.Errorf("--build error, %w", err) 157 } 158 if len(packages) == 0 { 159 return errors.New("--build must specify at least one Package{}") 160 } 161 } else if buildPath != "" { 162 blob, err := os.ReadFile(buildPath) 163 if err != nil { 164 return fmt.Errorf("--build-file error, %w", err) 165 } 166 packages, err = lex.ParsePackages(blob) 167 if err != nil { 168 return fmt.Errorf("--build-file error, %w", err) 169 } 170 if len(packages) == 0 { 171 return errors.New("--build-file must specify at least one Package{}") 172 } 173 } else { 174 return errors.New("need exactly one of --build or --build-file") 175 } 176 177 if cctx.Bool("gen-server") { 178 pkgname := cctx.String("package") 179 outdir := cctx.String("outdir") 180 if outdir == "" { 181 return fmt.Errorf("must specify output directory (--outdir)") 182 } 183 defmap := lex.BuildExtDefMap(append(schemas, externalSchemas...), packages) 184 _ = defmap 185 186 paths := cctx.StringSlice("types-import") 187 importmap := make(map[string]string) 188 for _, p := range paths { 189 parts := strings.Split(p, ":") 190 importmap[parts[0]] = parts[1] 191 } 192 193 handlers := cctx.Bool("gen-handlers") 194 195 if err := lex.CreateHandlerStub(pkgname, importmap, outdir, schemas, handlers); err != nil { 196 return err 197 } 198 199 } else { 200 return lex.Run(schemas, externalSchemas, packages) 201 } 202 203 return nil 204 } 205 206 if err := app.Run(os.Args); err != nil { 207 log.Fatal(err) 208 } 209}