github.com/qiniu/go-sdk/v7@v7.27.0/internal/api-generator/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 8 "github.com/dave/jennifer/jen" 9 "github.com/iancoleman/strcase" 10 goflags "github.com/jessevdk/go-flags" 11 "gopkg.in/yaml.v3" 12 ) 13 14 const ( 15 PackageNameHTTPClient = "github.com/qiniu/go-sdk/v7/storagev2/http_client" 16 PackageNameAuth = "github.com/qiniu/go-sdk/v7/auth" 17 PackageNameCredentials = "github.com/qiniu/go-sdk/v7/storagev2/credentials" 18 PackageNameRegion = "github.com/qiniu/go-sdk/v7/storagev2/region" 19 PackageNameUpToken = "github.com/qiniu/go-sdk/v7/storagev2/uptoken" 20 PackageNameErrors = "github.com/qiniu/go-sdk/v7/storagev2/errors" 21 PackageNameUtils = "github.com/qiniu/go-sdk/v7/storagev2/internal/utils" 22 PackageNameUplog = "github.com/qiniu/go-sdk/v7/internal/uplog" 23 PackageNameInternalIo = "github.com/qiniu/go-sdk/v7/internal/io" 24 ) 25 26 var flags struct { 27 ApiSpecsPaths []string `long:"api-specs" required:"true"` 28 OutputDirPath string `long:"output" required:"true"` 29 ApiPackagePath string `long:"api-package" required:"true"` 30 StructName string `long:"struct-name" required:"true"` 31 } 32 33 func main() { 34 _, err := goflags.ParseArgs(&flags, os.Args[2:]) 35 if err != nil { 36 fmt.Fprintf(os.Stderr, "%s\n", err) 37 os.Exit(1) 38 } 39 os.RemoveAll(flags.OutputDirPath) 40 for _, apiSpecsPath := range flags.ApiSpecsPaths { 41 entries, err := os.ReadDir(apiSpecsPath) 42 if err != nil { 43 fmt.Fprintf(os.Stderr, "Failed to read directory %s: %s\n", apiSpecsPath, err) 44 os.Exit(1) 45 } 46 47 for _, entry := range entries { 48 apiSpecName := extractApiSpecName(entry.Name()) 49 generatedApiDirPath := filepath.Join(flags.OutputDirPath, apiSpecName) 50 if err = os.MkdirAll(generatedApiDirPath, 0755); err != nil { 51 fmt.Fprintf(os.Stderr, "Failed to create directory %s: %s\n", generatedApiDirPath, err) 52 os.Exit(1) 53 } 54 if err = writeGolangPackages(apiSpecName, filepath.Join(apiSpecsPath, entry.Name()), flags.OutputDirPath); err != nil { 55 fmt.Fprintf(os.Stderr, "Failed to write go package %s: %s\n", apiSpecName, err) 56 os.Exit(1) 57 } 58 } 59 } 60 if err = writeApiClient(flags.OutputDirPath); err != nil { 61 fmt.Fprintf(os.Stderr, "Failed to write api client: %s\n", err) 62 os.Exit(1) 63 } 64 } 65 66 func writeGolangPackages(apiSpecName, apiSpecPath, generatedDirPath string) (err error) { 67 generatedApiDirPath := filepath.Join(generatedDirPath, apiSpecName) 68 apiSpecFile, err := os.Open(apiSpecPath) 69 if err != nil { 70 return 71 } 72 defer apiSpecFile.Close() 73 74 var apiSpec ApiDetailedDescription 75 decoder := yaml.NewDecoder(apiSpecFile) 76 decoder.KnownFields(true) 77 if err = decoder.Decode(&apiSpec); err != nil { 78 return 79 } 80 if err = apiSpecFile.Close(); err != nil { 81 return 82 } 83 84 if err = writeSubPackage(apiSpecName, generatedApiDirPath, &apiSpec); err != nil { 85 return 86 } 87 return writeApiPackage(apiSpecName, generatedDirPath, &apiSpec) 88 } 89 90 func writeSubPackage(apiSpecName, generatedDirPath string, apiSpec *ApiDetailedDescription) error { 91 packageFile := jen.NewFile(apiSpecName) 92 packageFile.HeaderComment("THIS FILE IS GENERATED BY api-generator, DO NOT EDIT DIRECTLY!") 93 packageFile.PackageComment(apiSpec.Documentation) 94 if err := apiSpec.generateSubPackages(packageFile.Group, CodeGeneratorOptions{ 95 Name: apiSpecName, 96 CamelCaseName: apiSpec.CamelCaseName, 97 SnakeCaseName: apiSpec.SnakeCaseName, 98 Documentation: apiSpec.Documentation, 99 }); err != nil { 100 return err 101 } 102 return packageFile.Save(filepath.Join(generatedDirPath, "api.go")) 103 } 104 105 func writeApiPackage(apiSpecName, generatedDirPath string, apiSpec *ApiDetailedDescription) error { 106 apisPackageFile := jen.NewFile("apis") 107 apisPackageFile.HeaderComment("THIS FILE IS GENERATED BY api-generator, DO NOT EDIT DIRECTLY!") 108 if err := apiSpec.generatePackage(apisPackageFile.Group, CodeGeneratorOptions{ 109 Name: apiSpecName, 110 CamelCaseName: apiSpec.CamelCaseName, 111 SnakeCaseName: apiSpec.SnakeCaseName, 112 Documentation: apiSpec.Documentation, 113 }); err != nil { 114 return err 115 } 116 return apisPackageFile.Save(filepath.Join(generatedDirPath, "api_"+apiSpecName+".go")) 117 } 118 119 func writeApiClient(generatedDirPath string) error { 120 apiPackageFile := jen.NewFile("apis") 121 apiPackageFile.HeaderComment("THIS FILE IS GENERATED BY api-generator, DO NOT EDIT DIRECTLY!") 122 generateApiClient(apiPackageFile.Group) 123 return apiPackageFile.Save(filepath.Join(generatedDirPath, "apis.go")) 124 } 125 126 func generateApiClient(group *jen.Group) { 127 structName := strcase.ToCamel(flags.StructName) 128 group.Add(jen.Comment("API 客户端")) 129 group.Add( 130 jen.Type().Id(structName).StructFunc(func(group *jen.Group) { 131 group.Add(jen.Id("client").Op("*").Qual(PackageNameHTTPClient, "Client")) 132 }), 133 ) 134 group.Add(jen.Comment("创建 API 客户端")) 135 group.Add( 136 jen.Func(). 137 Id("New" + structName). 138 Params(jen.Id("options").Op("*").Qual(PackageNameHTTPClient, "Options")). 139 Params(jen.Op("*").Id(structName)). 140 BlockFunc(func(group *jen.Group) { 141 group.Return(jen.Op("&").Id(structName).ValuesFunc(func(group *jen.Group) { 142 group.Add(jen.Id("client").Op(":").Qual(PackageNameHTTPClient, "NewClient").Call(jen.Id("options"))) 143 })) 144 }), 145 ) 146 147 group.Add(jen.Comment("API 客户端选项")) 148 group.Add( 149 jen.Type().Id("Options").StructFunc(func(group *jen.Group) { 150 group.Add(jen.Id("OverwrittenBucketHosts").Qual(PackageNameRegion, "EndpointsProvider")) 151 group.Add(jen.Id("OverwrittenBucketName").String()) 152 group.Add(jen.Id("OverwrittenEndpoints").Qual(PackageNameRegion, "EndpointsProvider")) 153 group.Add(jen.Id("OverwrittenRegion").Qual(PackageNameRegion, "RegionsProvider")) 154 group.Add(jen.Id("OnRequestProgress").Func().Params( 155 jen.Uint64(), 156 jen.Uint64(), 157 )) 158 }), 159 ) 160 } 161 162 func isStorageAPIs() bool { 163 structName := strcase.ToCamel(flags.StructName) 164 return structName == "Storage" 165 }