From 39c822e6ebd930b4bdd29d985be56cd7759017ea Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Wed, 19 Feb 2025 21:37:28 -0500 Subject: remove this broken thing Signed-off-by: Xe Iaso --- .../internal/generator/aliases.go | 82 - .../internal/generator/generator.go | 187 --- .../internal/generator/generator_test.go | 317 ---- .../internal/generator/handlers.go | 579 ------- .../internal/generator/testdata/doc.json | 413 ----- .../testdata/gen/go/payment/v1alpha1/payment.pb.go | 263 --- .../generator/testdata/gen/go/pet/v1/pet.pb.go | 896 ---------- .../generator/testdata/gen/go/pet/v1/pet.twirp.go | 1705 -------------------- .../paymentapis/payment/v1alpha1/payment.proto | 24 - .../internal/generator/testdata/pet-api-doc.json | 321 ---- .../internal/generator/testdata/pet-api-doc.yaml | 297 ---- .../generator/testdata/petapis/pet/v1/pet.proto | 115 -- 12 files changed, 5199 deletions(-) delete mode 100644 cmd/twirp-openapi-gen/internal/generator/aliases.go delete mode 100644 cmd/twirp-openapi-gen/internal/generator/generator.go delete mode 100644 cmd/twirp-openapi-gen/internal/generator/generator_test.go delete mode 100644 cmd/twirp-openapi-gen/internal/generator/handlers.go delete mode 100644 cmd/twirp-openapi-gen/internal/generator/testdata/doc.json delete mode 100644 cmd/twirp-openapi-gen/internal/generator/testdata/gen/go/payment/v1alpha1/payment.pb.go delete mode 100644 cmd/twirp-openapi-gen/internal/generator/testdata/gen/go/pet/v1/pet.pb.go delete mode 100644 cmd/twirp-openapi-gen/internal/generator/testdata/gen/go/pet/v1/pet.twirp.go delete mode 100644 cmd/twirp-openapi-gen/internal/generator/testdata/paymentapis/payment/v1alpha1/payment.proto delete mode 100644 cmd/twirp-openapi-gen/internal/generator/testdata/pet-api-doc.json delete mode 100644 cmd/twirp-openapi-gen/internal/generator/testdata/pet-api-doc.yaml delete mode 100644 cmd/twirp-openapi-gen/internal/generator/testdata/petapis/pet/v1/pet.proto (limited to 'cmd/twirp-openapi-gen/internal') diff --git a/cmd/twirp-openapi-gen/internal/generator/aliases.go b/cmd/twirp-openapi-gen/internal/generator/aliases.go deleted file mode 100644 index 660d345..0000000 --- a/cmd/twirp-openapi-gen/internal/generator/aliases.go +++ /dev/null @@ -1,82 +0,0 @@ -package generator - -var typeAliases = map[string]struct { - Type, Format string -}{ - // proto numeric types - "int32": {Type: "integer", Format: "int32"}, - "uint32": {Type: "integer", Format: "uint32"}, - "sint32": {Type: "integer", Format: "int32"}, - "fixed32": {Type: "integer", Format: "int32"}, - "sfixed32": {Type: "integer", Format: "int32"}, - - // proto numeric types, 64bit - "int64": {Type: "string", Format: "int64"}, - "uint64": {Type: "string", Format: "uint64"}, - "sint64": {Type: "string", Format: "int64"}, - "fixed64": {Type: "string", Format: "int64"}, - "sfixed64": {Type: "string", Format: "int64"}, - - "double": {Type: "number", Format: "double"}, - "float": {Type: "number", Format: "float"}, - - // effectively copies google.protobuf.BytesValue - "bytes": { - Type: "string", - Format: "byte", - }, - - // It is what it is - "bool": { - Type: "boolean", - Format: "boolean", - }, - - "google.protobuf.Timestamp": { - Type: "string", - Format: "date-time", - }, - "google.protobuf.Duration": { - Type: "string", - }, - "google.protobuf.StringValue": { - Type: "string", - }, - "google.protobuf.BytesValue": { - Type: "string", - Format: "byte", - }, - "google.protobuf.Int32Value": { - Type: "integer", - Format: "int32", - }, - "google.protobuf.UInt32Value": { - Type: "integer", - Format: "uint32", - }, - "google.protobuf.Int64Value": { - Type: "string", - Format: "int64", - }, - "google.protobuf.UInt64Value": { - Type: "string", - Format: "uint64", - }, - "google.protobuf.FloatValue": { - Type: "number", - Format: "float", - }, - "google.protobuf.DoubleValue": { - Type: "number", - Format: "double", - }, - "google.protobuf.BoolValue": { - Type: "boolean", - Format: "boolean", - }, - - "google.type.DateTime": { - Type: "string", - Format: "date-time", - }, -} diff --git a/cmd/twirp-openapi-gen/internal/generator/generator.go b/cmd/twirp-openapi-gen/internal/generator/generator.go deleted file mode 100644 index 2a08055..0000000 --- a/cmd/twirp-openapi-gen/internal/generator/generator.go +++ /dev/null @@ -1,187 +0,0 @@ -package generator - -import ( - "encoding/json" - "fmt" - "log/slog" - "os" - "path/filepath" - - "github.com/emicklei/proto" - "github.com/getkin/kin-openapi/openapi3" - "github.com/invopop/yaml" -) - -type generatorConfig struct { - protoPaths []string - servers []string - title string - docVersion string - pathPrefix string - format string -} - -type Option func(config *generatorConfig) error - -func ProtoPaths(paths []string) Option { - return func(config *generatorConfig) error { - config.protoPaths = paths - return nil - } -} - -func Servers(servers []string) Option { - return func(config *generatorConfig) error { - config.servers = servers - return nil - } -} - -func Title(title string) Option { - return func(config *generatorConfig) error { - config.title = title - return nil - } -} - -func DocVersion(version string) Option { - return func(config *generatorConfig) error { - config.docVersion = version - return nil - } -} - -func PathPrefix(pathPrefix string) Option { - return func(config *generatorConfig) error { - config.pathPrefix = pathPrefix - return nil - } -} - -func Format(format string) Option { - return func(config *generatorConfig) error { - config.format = format - return nil - } -} - -type generator struct { - openAPIV3 *openapi3.T - - conf *generatorConfig - inputFiles []string - packageName string - - importedFiles map[string]struct{} -} - -func NewGenerator(inputFiles []string, options ...Option) (*generator, error) { - conf := generatorConfig{} - for _, opt := range options { - if err := opt(&conf); err != nil { - return nil, err - } - } - - if len(inputFiles) < 1 { - return nil, fmt.Errorf("missing input files") - } - - openAPIV3 := openapi3.T{ - OpenAPI: "3.0.0", - Info: &openapi3.Info{ - Title: conf.title, - Version: conf.docVersion, - }, - Paths: openapi3.Paths{}, - Components: &openapi3.Components{ - Schemas: map[string]*openapi3.SchemaRef{}, - }, - } - - for _, server := range conf.servers { - openAPIV3.Servers = append(openAPIV3.Servers, &openapi3.Server{URL: server}) - } - - slog.Debug("generating doc", "format", conf.format, "inputFiles", inputFiles) - - return &generator{ - inputFiles: inputFiles, - openAPIV3: &openAPIV3, - conf: &conf, - importedFiles: map[string]struct{}{}, - }, nil -} - -func (gen *generator) Generate(filename string) error { - if _, err := gen.Parse(); err != nil { - return err - } - - if err := gen.Save(filename); err != nil { - return err - } - - return nil -} - -func (gen *generator) Parse() (*openapi3.T, error) { - for _, filename := range gen.inputFiles { - protoFile, err := readProtoFile(filename, gen.conf.protoPaths) - if err != nil { - return nil, fmt.Errorf("readProtoFile: %w", err) - } - proto.Walk(protoFile, gen.Handlers()...) - } - - slog.Debug("generated", "paths", len(gen.openAPIV3.Paths), "components", len(gen.openAPIV3.Components.Schemas)) - return gen.openAPIV3, nil -} - -func (gen *generator) Save(filename string) error { - var by []byte - var err error - switch gen.conf.format { - case "json": - by, err = gen.JSON() - case "yaml", "yml": - by, err = gen.YAML() - default: - return fmt.Errorf("missing format") - } - if err != nil { - return err - } - - return os.WriteFile(filename, by, os.ModePerm^0111) -} - -func (gen *generator) JSON() ([]byte, error) { - return json.MarshalIndent(gen.openAPIV3, "", " ") -} - -func (gen *generator) YAML() ([]byte, error) { - return yaml.Marshal(gen.openAPIV3) -} - -func readProtoFile(filename string, protoPaths []string) (*proto.Proto, error) { - var file *os.File - var err error - for _, path := range append(protoPaths, "") { - file, err = os.Open(filepath.Join(path, filename)) - if err != nil { - if os.IsNotExist(err) { - continue - } - return nil, fmt.Errorf("Open: %w", err) - } - break - } - if file == nil { - return nil, fmt.Errorf("could not read file %q", filename) - } - defer file.Close() - - parser := proto.NewParser(file) - return parser.Parse() -} diff --git a/cmd/twirp-openapi-gen/internal/generator/generator_test.go b/cmd/twirp-openapi-gen/internal/generator/generator_test.go deleted file mode 100644 index 78af950..0000000 --- a/cmd/twirp-openapi-gen/internal/generator/generator_test.go +++ /dev/null @@ -1,317 +0,0 @@ -package generator - -import ( - "flag" - "log/slog" - "os" - "strings" - "testing" -) - -type ProtoRPC struct { - name string - input string - output string - desc string -} - -type ProtoMessage struct { - name string - fields []ProtoField -} - -type ProtoField struct { - name string - fieldType string - format string - desc string - enums []string - ref string - itemsRef string - itemsType string -} - -var ( - verbose = flag.Bool("slog.verbose", false, "print debug logs to the console") -) - -func init() { - if *verbose { - h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{ - AddSource: true, - Level: slog.LevelDebug, - }) - slog.SetDefault(slog.New(h)) - } else { - slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{ - AddSource: true, - }))) - } -} - -func TestGenerator(t *testing.T) { - flag.Parse() - - opts := []Option{ - ProtoPaths([]string{"./testdata/paymentapis", "./testdata/petapis"}), - Servers([]string{"https://example.com"}), - Title("Test"), - DocVersion("0.1"), - Format("json"), - } - gen, err := NewGenerator([]string{"./testdata/petapis/pet/v1/pet.proto"}, opts...) - if err != nil { - t.Fatal(err) - } - openAPI, err := gen.Parse() - if err != nil { - t.Fatal(err) - } - - if err := gen.Save("./testdata/doc.json"); err != nil { - t.Fatal(err) - } - - pkgName := "pet.v1" - serviceName := "PetStoreService" - rpcs := []ProtoRPC{ - { - name: "GetPet", - input: "GetPetRequest", - output: "GetPetResponse", - }, - } - messages := []ProtoMessage{ - { - name: "GetPetRequest", - fields: []ProtoField{ - { - name: "pet_id", - fieldType: "string", - }, - }, - }, - { - name: "Pet", - fields: []ProtoField{ - { - name: "pet_type", - fieldType: "object", - ref: "#/components/schemas/pet.v1.PetType", - enums: []string{ - "PET_TYPE_UNSPECIFIED", - "PET_TYPE_CAT", - "PET_TYPE_DOG", - "PET_TYPE_SNAKE", - "PET_TYPE_HAMSTER", - }, - }, - { - name: "pet_types", - fieldType: "array", - itemsRef: "#/components/schemas/pet.v1.PetType", - }, - { - name: "tags", - fieldType: "array", - itemsType: "string", - }, - { - name: "pet_id", - fieldType: "string", - desc: "pet_id is an auto-generated id for the pet\\nthe id uniquely identifies a pet in the system", - }, - { - name: "name", - fieldType: "string", - }, - { - name: "created_at", - fieldType: "string", - format: "date-time", - }, - { - name: "vet", - fieldType: "object", - ref: "#/components/schemas/pet.v1.Vet", - }, - { - name: "vets", - fieldType: "array", - itemsRef: "#/components/schemas/pet.v1.Vet", - itemsType: "object", - }, - }, - }, - } - - t.Run("RPC", func(t *testing.T) { - for _, rpc := range rpcs { - pathName := "/" + pkgName + "." + serviceName + "/" + rpc.name - path, ok := openAPI.Paths[pathName] - if !ok { - t.Errorf("%s: missing rpc %q", pathName, rpc.name) - } - - if path.Description != rpc.desc { - t.Errorf("%s: expected desc %q but got %q", pathName, rpc.desc, path.Description) - } - - post := path.Post - if post == nil { - t.Errorf("%s: missing post", pathName) - continue - } - - if post.Summary != rpc.name { - t.Errorf("%s: expected summary %q but got %q", pathName, rpc.name, post.Summary) - } - - requestBodyRef := post.RequestBody - if requestBodyRef == nil { - t.Errorf("%s: missing request body", pathName) - continue - } - - // request - { - requestBody := requestBodyRef.Value - if requestBody == nil { - t.Errorf("%s: missing request body", pathName) - continue - } - - mediaType, ok := requestBody.Content["application/json"] - if !ok { - t.Errorf("%s: missing content type", pathName) - continue - } - - if mediaType.Schema == nil { - t.Errorf("%s: missing media type schema", pathName) - continue - } - - expectedRef := "#/components/schemas/" + pkgName + "." + rpc.input - if mediaType.Schema.Ref != expectedRef { - t.Errorf("%s: expected ref %q but got %q", pathName, expectedRef, mediaType.Schema.Ref) - } - } - - // response - { - respRef := post.Responses["200"] - if respRef == nil { - t.Errorf("%s: missing resp", pathName) - continue - } - - resp := respRef.Value - if resp == nil { - t.Errorf("%s: missing resp", pathName) - continue - } - - mediaType, ok := resp.Content["application/json"] - if !ok { - t.Errorf("%s: missing content type", pathName) - continue - } - - if mediaType.Schema == nil { - t.Errorf("%s: missing media type schema", pathName) - continue - } - - expectedRef := "#/components/schemas/" + pkgName + "." + rpc.output - if mediaType.Schema.Ref != expectedRef { - t.Errorf("%s: expected ref %q but got %q", pathName, expectedRef, mediaType.Schema.Ref) - } - } - } - }) - - t.Run("Messages", func(*testing.T) { - for _, message := range messages { - schemaName := "" + pkgName + "." + message.name - schema, ok := openAPI.Components.Schemas[schemaName] - if !ok { - t.Errorf("%s: missing message %q", schemaName, message.name) - } - if schema.Value == nil { - t.Errorf("%s: missing component", schemaName) - continue - } - properties := schema.Value.Properties - for _, messageField := range message.fields { - propertyRef, ok := properties[messageField.name] - if !ok { - t.Errorf("%s: missing property %q", schemaName, messageField.name) - } - - if propertyRef == nil || propertyRef.Value == nil { - t.Errorf("%s: missing property ref", schemaName) - continue - } - - property := propertyRef.Value - if property.Type != messageField.fieldType { - t.Errorf("%s: %q expected property type %q but got %q", schemaName, message.name, messageField.fieldType, property.Type) - continue - } - - if messageField.format != "" { - if messageField.format != "" && property.Format != messageField.format { - t.Errorf("%s: expected property format %q but got %q", schemaName, messageField.format, property.Format) - continue - } - } - - if propertyRef.Ref != messageField.ref { - t.Errorf("%s: %q expected reference %q but got %q", schemaName, messageField.name, messageField.ref, propertyRef.Ref) - } - - // check the reference schema - if messageField.ref != "" { - refParts := strings.Split(messageField.ref, "/") - // the reference schema has the format of #/components/schemas/ so we need to get the last part - schemaRef, ok := openAPI.Components.Schemas[refParts[len(refParts)-1]] - if !ok { - t.Errorf("%s: %q expected reference schema %q but got nil", schemaName, messageField.name, messageField.ref) - } else { - // check if the schema reference has the expected enum values - if len(messageField.enums) > 0 { - if schemaRef.Value.Enum == nil { - t.Errorf("%s: %q expected reference schema enums %q but got nil", schemaName, messageField.name, messageField.ref) - } else { - enums := map[string]struct{}{} - for _, e := range schemaRef.Value.Enum { - enums[e.(string)] = struct{}{} - } - for _, e := range messageField.enums { - if _, ok := enums[e]; !ok { - t.Errorf("%s: %q expected reference schema enum %q to have %q but got nil", schemaName, messageField.name, messageField.ref, e) - } - } - } - } - } - } - - if property.Type == "array" { - if property.Items == nil || property.Items.Value == nil { - t.Errorf("%s: missing property enum array items", schemaName) - } - // only check the array items type if it's not a reference - if messageField.itemsRef == "" && (property.Items.Value.Type != messageField.itemsType) { - t.Errorf("%s: expected %s items type %q but got %q", schemaName, messageField.name, messageField.itemsType, property.Items.Value.Type) - } - // check the array items reference schema - if property.Items.Ref != messageField.itemsRef { - t.Errorf("%s: expected %s items ref %q but got %q", schemaName, messageField.name, messageField.itemsRef, property.Items.Ref) - } - } - } - } - }) -} diff --git a/cmd/twirp-openapi-gen/internal/generator/handlers.go b/cmd/twirp-openapi-gen/internal/generator/handlers.go deleted file mode 100644 index 219000f..0000000 --- a/cmd/twirp-openapi-gen/internal/generator/handlers.go +++ /dev/null @@ -1,579 +0,0 @@ -package generator - -import ( - "encoding/json" - "fmt" - "log" - "log/slog" - "path/filepath" - "strings" - "unicode" - - "github.com/emicklei/proto" - "github.com/getkin/kin-openapi/openapi3" -) - -const ( - googleAnyType = "google.protobuf.Any" - googleListValueType = "google.protobuf.ListValue" - googleStructType = "google.protobuf.Struct" - googleValueType = "google.protobuf.Value" - googleEmptyType = "google.protobuf.Empty" - - googleMoneyType = "google.type.Money" -) - -var ( - successDescription = "Success" -) - -func (gen *generator) Handlers() []proto.Handler { - return []proto.Handler{ - proto.WithPackage(gen.Package), - proto.WithImport(gen.Import), - proto.WithRPC(gen.RPC), - proto.WithEnum(gen.Enum), - proto.WithMessage(gen.Message), - } -} - -func (gen *generator) Package(pkg *proto.Package) { - slog.Debug("Package handler", "package", pkg.Name) - gen.packageName = pkg.Name -} - -func (gen *generator) Import(i *proto.Import) { - slog.Debug("Import handler", "package", gen.packageName, "filename", i.Filename) - - if _, ok := gen.importedFiles[i.Filename]; ok { - return - } - gen.importedFiles[i.Filename] = struct{}{} - - // Instead of loading and generating the OpenAPI docs for the google proto definitions, - // its known types are mapped to OpenAPI types; see aliases.go. - if strings.Contains(i.Filename, "google/") { - return - } - - protoFile, err := readProtoFile(i.Filename, gen.conf.protoPaths) - if err != nil { - slog.Error("could not import file", "filename", i.Filename, "error", err) - return - } - - oldPackageName := gen.packageName - - // Override the package name for the next round of Walk calls to preserve the types full import path - withPackage := func(pkg *proto.Package) { - gen.packageName = pkg.Name - } - - // additional files walked for messages and imports only - proto.Walk(protoFile, - proto.WithPackage(withPackage), - proto.WithImport(gen.Import), - proto.WithRPC(gen.RPC), - proto.WithEnum(gen.Enum), - proto.WithMessage(gen.Message), - ) - - gen.packageName = oldPackageName -} - -func (gen *generator) RPC(rpc *proto.RPC) { - slog.Debug("RPC handler", "package", gen.packageName, "rpc", rpc.Name, "requestType", rpc.RequestType, "returnsType", rpc.ReturnsType) - - parent, ok := rpc.Parent.(*proto.Service) - if !ok { - log.Panicf("parent is not proto.service") - } - pathName := filepath.Join("/"+gen.conf.pathPrefix+"/", gen.packageName+"."+parent.Name, rpc.Name) - - var reqMediaType *openapi3.MediaType - switch rpc.RequestType { - case "google.protobuf.Empty": - gen.addGoogleEmptySchema() - default: - } - if strings.Contains(rpc.RequestType, ".") { - reqMediaType = &openapi3.MediaType{ - Schema: &openapi3.SchemaRef{ - Ref: fmt.Sprintf("#/components/schemas/%s", rpc.RequestType), - }, - } - } else { - reqMediaType = &openapi3.MediaType{ - Schema: &openapi3.SchemaRef{ - Ref: fmt.Sprintf("#/components/schemas/%s.%s", gen.packageName, rpc.RequestType), - }, - } - } - - var resMediaType *openapi3.MediaType - switch rpc.ReturnsType { - case "google.protobuf.Empty": - gen.addGoogleEmptySchema() - default: - } - - if strings.Contains(rpc.ReturnsType, ".") { - resMediaType = &openapi3.MediaType{ - Schema: &openapi3.SchemaRef{ - Ref: fmt.Sprintf("#/components/schemas/%s", rpc.ReturnsType), - }, - } - } else { - resMediaType = &openapi3.MediaType{ - Schema: &openapi3.SchemaRef{ - Ref: fmt.Sprintf("#/components/schemas/%s.%s", gen.packageName, rpc.ReturnsType), - }, - } - } - - // NOTE: Redocly does not read the "examples" (plural) field, only the "example" (singular) one. - commentMsg, reqExamples, resExamples, err := parseComment(rpc.Comment) - if err != nil { - // TODO(dm): how can we surface the errors from the parser instead of panicking? - log.Panicf("failed to parse comment %s ", err) - } - - if len(reqExamples) > 0 { - exampleObj := make(map[string]interface{}) - for i, example := range reqExamples { - exampleObj[fmt.Sprintf("example %d", i)] = example - } - reqMediaType.Example = exampleObj - } - if len(resExamples) > 0 { - exampleObj := make(map[string]interface{}) - for i, example := range resExamples { - exampleObj[fmt.Sprintf("example %d", i)] = example - } - resMediaType.Example = exampleObj - } - - gen.openAPIV3.Paths[pathName] = &openapi3.PathItem{ - Post: &openapi3.Operation{ - Description: commentMsg, - Summary: rpc.Name, - RequestBody: &openapi3.RequestBodyRef{ - Value: &openapi3.RequestBody{ - Content: openapi3.Content{"application/json": reqMediaType}, - }, - }, - Responses: map[string]*openapi3.ResponseRef{ - "200": { - Value: &openapi3.Response{ - Description: &successDescription, - Content: openapi3.Content{"application/json": resMediaType}, - }, - }, - }, - }, - } -} - -func (gen *generator) Enum(enum *proto.Enum) { - slog.Debug("Enum handler", "package", gen.packageName, "enum", enum.Name) - values := []interface{}{} - for _, element := range enum.Elements { - enumField := element.(*proto.EnumField) - values = append(values, enumField.Name) - } - - gen.openAPIV3.Components.Schemas[gen.packageName+"."+enum.Name] = &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: description(enum.Comment), - Type: "string", - Enum: values, - }, - } -} - -func (gen *generator) Message(msg *proto.Message) { - slog.Debug("Message handler", "package", gen.packageName, "message", msg.Name) - - schemaProps := openapi3.Schemas{} - - for _, element := range msg.Elements { - switch val := element.(type) { - case *proto.Message: - //logger.logd("proto.Message") - gen.Message(val) - case *proto.Comment: - //logger.logd("proto.Comment") - case *proto.Oneof: - //logger.logd("proto.Oneof") - case *proto.OneOfField: - //logger.logd("proto.OneOfField") - gen.addField(schemaProps, val.Field, false) - case *proto.MapField: - //logger.logd("proto.MapField") - gen.addField(schemaProps, val.Field, false) - case *proto.NormalField: - //logger.logd("proto.NormalField %q %q", val.Field.Type, val.Field.Name) - gen.addField(schemaProps, val.Field, val.Repeated) - default: - slog.Error("unknown field type", "type", fmt.Sprintf("%T", element)) - } - } - - gen.openAPIV3.Components.Schemas[gen.packageName+"."+msg.Name] = &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: description(msg.Comment), - Type: "object", - Properties: schemaProps, - }, - } -} - -func (gen *generator) addField(schemaPropsV3 openapi3.Schemas, field *proto.Field, repeated bool) { - fieldDescription := description(field.Comment) - fieldName := field.Name - fieldType := field.Type - fieldFormat := field.Type - // map proto types to openapi - if p, ok := typeAliases[fieldType]; ok { - fieldType = p.Type - fieldFormat = p.Format - } - - if fieldType == fieldFormat { - fieldFormat = "" - } - - switch fieldType { - // Build the schema for native types that don't need to reference other schemas - // https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#data-types - case "boolean", "integer", "number", "string", "object": - fieldSchemaV3 := openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: fieldDescription, - Type: fieldType, - Format: fieldFormat, - }, - } - if !repeated { - schemaPropsV3[fieldName] = &fieldSchemaV3 - return - } - schemaPropsV3[fieldName] = &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: fieldDescription, - Type: "array", - Format: fieldFormat, - Items: &fieldSchemaV3, - }, - } - return - - // generate the schema for google well known complex types: https://protobuf.dev/reference/protobuf/google.protobuf/#index - case googleAnyType: - slog.Debug("any", "name", fieldName, "type", fieldType, "format", fieldFormat) - gen.addGoogleAnySchema() - case googleListValueType: - slog.Debug("ListValue", "name", fieldName, "type", fieldType, "format", fieldFormat) - gen.addGoogleListValueSchema() - case googleStructType: - slog.Debug("Struct", "name", fieldName, "type", fieldType, "format", fieldFormat) - gen.addGoogleValueSchema() // struct depends on value - gen.addGoogleStructSchema() - case googleValueType: - slog.Debug("Value", "name", fieldName, "type", fieldType, "format", fieldFormat) - gen.addGoogleValueSchema() - case googleMoneyType: - slog.Debug("Money", "name", fieldName, "type", fieldType, "format", fieldFormat) - gen.addGoogleMoneySchema() - case googleEmptyType: - slog.Debug("Empty", "name", fieldName, "type", fieldType, "format", fieldFormat) - gen.addGoogleEmptySchema() - default: - slog.Debug("Default", "name", fieldName, "type", fieldType, "format", fieldFormat) - } - - // prefix custom types with the package name - ref := fmt.Sprintf("#/components/schemas/%s", fieldType) - if !strings.Contains(fieldType, ".") { - ref = fmt.Sprintf("#/components/schemas/%s.%s", gen.packageName, fieldType) - } - - if !repeated { - schemaPropsV3[fieldName] = &openapi3.SchemaRef{ - Ref: ref, - Value: &openapi3.Schema{ - Description: fieldDescription, - Type: "object", - }, - } - return - } - - schemaPropsV3[fieldName] = &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: fieldDescription, - Type: "array", - Items: &openapi3.SchemaRef{ - Ref: ref, - Value: &openapi3.Schema{ - Type: "object", - }, - }, - }, - } -} - -func (gen *generator) addGoogleEmptySchema() { - if _, ok := gen.openAPIV3.Components.Schemas[googleEmptyType]; ok { - return - } - gen.openAPIV3.Components.Schemas[googleEmptyType] = &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: "A generic empty message that you can re-use to avoid defining duplicated empty messages in your APIs. A typical example is to use it as the request or the response type of an API method. For instance:", - Type: "object", - }, - } -} - -// addGoogleAnySchema adds a schema item for the google.protobuf.Any type. -func (gen *generator) addGoogleAnySchema() { - if _, ok := gen.openAPIV3.Components.Schemas[googleAnyType]; ok { - return - } - gen.openAPIV3.Components.Schemas[googleAnyType] = &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: ` -The JSON representation of an Any value uses the regular -representation of the deserialized, embedded message, with an -additional field @type which contains the type URL. Example: - - package google.profile; - message Person { - string first_name = 1; - string last_name = 2; - } - - { - "@type": "type.googleapis.com/google.profile.Person", - "firstName": , - "lastName": - } - -If the embedded message type is well-known and has a custom JSON -representation, that representation will be embedded adding a field -value which holds the custom JSON in addition to the @type -field. Example (for message [google.protobuf.Duration][]): - - { - "@type": "type.googleapis.com/google.protobuf.Duration", - "value": "1.212s" - } -`, - Type: "object", - Properties: openapi3.Schemas{ - "@type": &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: "", - Type: "string", - Format: "", - }, - }, - }, - }, - } -} - -// addGoogleAnySchema adds a schema item for the google.protobuf.ListValue type. -func (gen *generator) addGoogleListValueSchema() { - if _, ok := gen.openAPIV3.Components.Schemas[googleListValueType]; ok { - return - } - gen.openAPIV3.Components.Schemas[googleListValueType] = &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: ` -ListValue is a wrapper around a repeated field of values. -The JSON representation for ListValue is JSON array. -`, - Type: "array", - Items: &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - OneOf: openapi3.SchemaRefs{ - &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Type: "string", - }, - }, - &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Type: "number", - }, - }, - &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Type: "integer", - }, - }, - &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Type: "boolean", - }, - }, - &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Type: "array", - }, - }, - &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Type: "object", - }, - }, - }, - }, - }, - }, - } -} - -func (gen *generator) addGoogleStructSchema() { - if _, ok := gen.openAPIV3.Components.Schemas[googleStructType]; ok { - return - } - - gen.openAPIV3.Components.Schemas[googleStructType] = &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: ` -Struct represents a structured data value, consisting of fields -which map to dynamically typed values. In some languages, -Struct might be supported by a native representation. For example, -in scripting languages like JS a struct is represented as -an object. The details of that representation are described -together with the proto support for the language. - -The JSON representation for Struct is JSON object. -`, - Type: "object", - Properties: openapi3.Schemas{ - "fields": &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: "Unordered map of dynamically typed values.", - Type: "object", - AdditionalProperties: openapi3.AdditionalProperties{ - Schema: &openapi3.SchemaRef{ - Ref: "#/components/schemas/google.protobuf.Value", - }, - }, - }, - }, - }, - }, - } -} - -func (gen *generator) addGoogleValueSchema() { - if _, ok := gen.openAPIV3.Components.Schemas[googleValueType]; ok { - return - } - - gen.openAPIV3.Components.Schemas[googleValueType] = &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: ` -Value represents a dynamically typed value which can be either -null, a number, a string, a boolean, a recursive struct value, or a -list of values. A producer of value is expected to set one of that -variants, absence of any variant indicates an error. - -The JSON representation for Value is JSON value. -`, - OneOf: openapi3.SchemaRefs{ - &openapi3.SchemaRef{Value: &openapi3.Schema{Type: "string"}}, - &openapi3.SchemaRef{Value: &openapi3.Schema{Type: "number"}}, - &openapi3.SchemaRef{Value: &openapi3.Schema{Type: "integer"}}, - &openapi3.SchemaRef{Value: &openapi3.Schema{Type: "boolean"}}, - &openapi3.SchemaRef{Ref: "#/components/schemas/google.protobuf.Struct"}, - &openapi3.SchemaRef{Ref: "#/components/schemas/google.protobuf.ListValue"}, - }, - }, - } -} - -func (gen *generator) addGoogleMoneySchema() { - if _, ok := gen.openAPIV3.Components.Schemas[googleMoneyType]; ok { - return - } - - gen.openAPIV3.Components.Schemas[googleMoneyType] = &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: `Represents an amount of money with its currency type`, - Type: "object", - Properties: openapi3.Schemas{ - "currency_code": &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: "The 3-letter currency code defined in ISO 4217.", - Type: "string", - }, - }, - "units": &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: "The whole units of the amount.\nFor example if `currencyCode` is `\"USD\"`, then 1 unit is one US dollar.", - Type: "integer", - Format: "int64", - }, - }, - "nanos": &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Description: "Number of nano (10^-9) units of the amount.\nThe value must be between -999,999,999 and +999,999,999 inclusive.\nIf `units` is positive, `nanos` must be positive or zero.\nIf `units` is zero, `nanos` can be positive, zero, or negative.\nIf `units` is negative, `nanos` must be negative or zero.\nFor example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000.", - Type: "integer", - Format: "int32", - }, - }, - }, - }, - } -} - -func description(comment *proto.Comment) string { - if comment == nil { - return "" - } - result := []string{} - for _, line := range comment.Lines { - line = strings.TrimSpace(line) - if len(line) > 0 { - result = append(result, line) - } - } - return strings.Join(result, "\n") -} - -// parseComment parses the comment for an RPC method and returns the description, request examples, and response examples. -// it looks for the labels req-example: and res-example: to extract the JSON payload samples. -func parseComment(comment *proto.Comment) (string, []map[string]interface{}, []map[string]interface{}, error) { - if comment == nil { - return "", nil, nil, nil - } - reqExamples := []map[string]interface{}{} - respExamples := []map[string]interface{}{} - message := "" - for _, line := range comment.Lines { - line = strings.TrimLeftFunc(line, unicode.IsSpace) - if strings.HasPrefix(line, "req-example:") { - parts := strings.Split(line, "req-example:") - example := map[string]interface{}{} - if err := json.Unmarshal([]byte(parts[1]), &example); err != nil { - return "", nil, nil, fmt.Errorf("failed to parse req-example %q: %v", parts[1], err) - } - reqExamples = append(reqExamples, example) - } else if strings.HasPrefix(line, "res-example:") { - parts := strings.Split(line, "res-example:") - example := map[string]interface{}{} - if err := json.Unmarshal([]byte(parts[1]), &example); err != nil { - return "", nil, nil, fmt.Errorf("failed to parse res-example %q: %v", parts[1], err) - } - respExamples = append(respExamples, example) - } else { - message = fmt.Sprintf("%s\n%s", message, line) - } - } - return message, reqExamples, respExamples, nil -} diff --git a/cmd/twirp-openapi-gen/internal/generator/testdata/doc.json b/cmd/twirp-openapi-gen/internal/generator/testdata/doc.json deleted file mode 100644 index 8f6df0f..0000000 --- a/cmd/twirp-openapi-gen/internal/generator/testdata/doc.json +++ /dev/null @@ -1,413 +0,0 @@ -{ - "components": { - "schemas": { - "google.protobuf.Any": { - "description": "\nThe JSON representation of an Any value uses the regular\nrepresentation of the deserialized, embedded message, with an\nadditional field @type which contains the type URL. Example:\n\n\tpackage google.profile;\n\tmessage Person {\n\t string first_name = 1;\n\t string last_name = 2;\n\t}\n\n\t{\n\t \"@type\": \"type.googleapis.com/google.profile.Person\",\n\t \"firstName\": \u003cstring\u003e,\n\t \"lastName\": \u003cstring\u003e\n\t}\n\nIf the embedded message type is well-known and has a custom JSON\nrepresentation, that representation will be embedded adding a field\nvalue which holds the custom JSON in addition to the @type\nfield. Example (for message [google.protobuf.Duration][]):\n\n\t{\n\t \"@type\": \"type.googleapis.com/google.protobuf.Duration\",\n\t \"value\": \"1.212s\"\n\t}\n", - "properties": { - "@type": { - "type": "string" - } - }, - "type": "object" - }, - "google.protobuf.Empty": { - "description": "A generic empty message that you can re-use to avoid defining duplicated empty messages in your APIs. A typical example is to use it as the request or the response type of an API method. For instance:", - "type": "object" - }, - "google.protobuf.ListValue": { - "description": "\nListValue is a wrapper around a repeated field of values.\nThe JSON representation for ListValue is JSON array.\n", - "items": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "integer" - }, - { - "type": "boolean" - }, - { - "type": "array" - }, - { - "type": "object" - } - ] - }, - "type": "array" - }, - "google.protobuf.Struct": { - "description": "\nStruct represents a structured data value, consisting of fields\nwhich map to dynamically typed values. In some languages, \nStruct might be supported by a native representation. For example,\nin scripting languages like JS a struct is represented as\nan object. The details of that representation are described\ntogether with the proto support for the language.\n\nThe JSON representation for Struct is JSON object.\n", - "properties": { - "fields": { - "additionalProperties": { - "$ref": "#/components/schemas/google.protobuf.Value" - }, - "description": "Unordered map of dynamically typed values.", - "type": "object" - } - }, - "type": "object" - }, - "google.protobuf.Value": { - "description": "\nValue represents a dynamically typed value which can be either\nnull, a number, a string, a boolean, a recursive struct value, or a\nlist of values. A producer of value is expected to set one of that\nvariants, absence of any variant indicates an error.\n\t\t\t\t\nThe JSON representation for Value is JSON value.\n", - "oneOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "integer" - }, - { - "type": "boolean" - }, - { - "$ref": "#/components/schemas/google.protobuf.Struct" - }, - { - "$ref": "#/components/schemas/google.protobuf.ListValue" - } - ] - }, - "google.type.Money": { - "description": "Represents an amount of money with its currency type", - "properties": { - "currency_code": { - "description": "The 3-letter currency code defined in ISO 4217.", - "type": "string" - }, - "nanos": { - "description": "Number of nano (10^-9) units of the amount.\nThe value must be between -999,999,999 and +999,999,999 inclusive.\nIf `units` is positive, `nanos` must be positive or zero.\nIf `units` is zero, `nanos` can be positive, zero, or negative.\nIf `units` is negative, `nanos` must be negative or zero.\nFor example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000.", - "format": "int32", - "type": "integer" - }, - "units": { - "description": "The whole units of the amount.\nFor example if `currencyCode` is `\"USD\"`, then 1 unit is one US dollar.", - "format": "int64", - "type": "integer" - } - }, - "type": "object" - }, - "payment.v1alpha1.Order": { - "description": "Order represents a monetary order.", - "properties": { - "amount": { - "$ref": "#/components/schemas/google.type.Money" - }, - "order_id": { - "type": "string" - }, - "payment_provider": { - "$ref": "#/components/schemas/payment.v1alpha1.PaymentProvider" - }, - "recipient_id": { - "type": "string" - } - }, - "type": "object" - }, - "payment.v1alpha1.PaymentProvider": { - "description": "PaymentProvider represents the supported set\nof payment providers.", - "enum": [ - "PAYMENT_PROVIDER_UNSPECIFIED", - "PAYMENT_PROVIDER_STRIPE", - "PAYMENT_PROVIDER_PAYPAL", - "PAYMENT_PROVIDER_APPLE" - ], - "type": "string" - }, - "pet.v1.DeletePetRequest": { - "properties": { - "pet_id": { - "type": "string" - } - }, - "type": "object" - }, - "pet.v1.GetPetRequest": { - "description": "GetPetRequest is the request object for GetPet\nThe message accepts a pet id as an input", - "properties": { - "pet_id": { - "type": "string" - } - }, - "type": "object" - }, - "pet.v1.GetPetResponse": { - "properties": { - "pet": { - "$ref": "#/components/schemas/pet.v1.Pet" - } - }, - "type": "object" - }, - "pet.v1.Pet": { - "description": "Pet represents a pet in the pet store.", - "properties": { - "created_at": { - "format": "date-time", - "type": "string" - }, - "details": { - "items": { - "$ref": "#/components/schemas/google.protobuf.Any" - }, - "type": "array" - }, - "labels": { - "$ref": "#/components/schemas/google.protobuf.ListValue" - }, - "metadata": { - "$ref": "#/components/schemas/google.protobuf.Struct" - }, - "name": { - "type": "string" - }, - "payment_provider": { - "$ref": "#/components/schemas/payment.v1alpha1.PaymentProvider" - }, - "pet_id": { - "description": "pet_id is an auto-generated id for the pet\nthe id uniquely identifies a pet in the system", - "type": "string" - }, - "pet_type": { - "$ref": "#/components/schemas/pet.v1.PetType" - }, - "pet_types": { - "items": { - "$ref": "#/components/schemas/pet.v1.PetType" - }, - "type": "array" - }, - "tags": { - "items": { - "type": "string" - }, - "type": "array" - }, - "vet": { - "$ref": "#/components/schemas/pet.v1.Vet" - }, - "vets": { - "items": { - "$ref": "#/components/schemas/pet.v1.Vet" - }, - "type": "array" - } - }, - "type": "object" - }, - "pet.v1.PetType": { - "description": "PetType represents the different types of pets in the pet store.", - "enum": [ - "PET_TYPE_UNSPECIFIED", - "PET_TYPE_CAT", - "PET_TYPE_DOG", - "PET_TYPE_SNAKE", - "PET_TYPE_HAMSTER" - ], - "type": "string" - }, - "pet.v1.PurchasePetRequest": { - "properties": { - "order": { - "$ref": "#/components/schemas/payment.v1alpha1.Order" - }, - "pet_id": { - "type": "string" - } - }, - "type": "object" - }, - "pet.v1.PurchasePetResponse": { - "type": "object" - }, - "pet.v1.PutPetRequest": { - "properties": { - "name": { - "type": "string" - }, - "pet_type": { - "$ref": "#/components/schemas/pet.v1.PetType" - } - }, - "type": "object" - }, - "pet.v1.PutPetResponse": { - "properties": { - "pet": { - "$ref": "#/components/schemas/pet.v1.Pet" - } - }, - "type": "object" - }, - "pet.v1.UpdatePetRequest": { - "properties": { - "metadata": { - "$ref": "#/components/schemas/google.protobuf.Struct" - }, - "pet_id": { - "type": "string" - } - }, - "type": "object" - }, - "pet.v1.UpdatePetResponse": { - "properties": { - "pet": { - "$ref": "#/components/schemas/pet.v1.Pet" - } - }, - "type": "object" - }, - "pet.v1.Vet": { - "properties": { - "name": { - "type": "string" - } - }, - "type": "object" - } - } - }, - "info": { - "title": "Test", - "version": "0.1" - }, - "openapi": "3.0.0", - "paths": { - "/pet.v1.PetStoreService/DeletePet": { - "post": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/pet.v1.DeletePetRequest" - } - } - } - }, - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/google.protobuf.Empty" - } - } - }, - "description": "Success" - } - }, - "summary": "DeletePet" - } - }, - "/pet.v1.PetStoreService/GetPet": { - "post": { - "description": "\nGetPet returns details about a pet\nIt accepts a pet id as an input and returns back the matching pet object", - "requestBody": { - "content": { - "application/json": { - "example": { - "example 0": { - "pet_id": "123" - }, - "example 1": { - "pet_id": "456" - } - }, - "schema": { - "$ref": "#/components/schemas/pet.v1.GetPetRequest" - } - } - } - }, - "responses": { - "200": { - "content": { - "application/json": { - "example": { - "example 0": { - "pet": { - "name": "toby" - } - } - }, - "schema": { - "$ref": "#/components/schemas/pet.v1.GetPetResponse" - } - } - }, - "description": "Success" - } - }, - "summary": "GetPet" - } - }, - "/pet.v1.PetStoreService/PurchasePet": { - "post": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/pet.v1.PurchasePetRequest" - } - } - } - }, - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/pet.v1.PurchasePetResponse" - } - } - }, - "description": "Success" - } - }, - "summary": "PurchasePet" - } - }, - "/pet.v1.PetStoreService/UpdatePet": { - "post": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/pet.v1.UpdatePetRequest" - } - } - } - }, - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/pet.v1.UpdatePetResponse" - } - } - }, - "description": "Success" - } - }, - "summary": "UpdatePet" - } - } - }, - "servers": [ - { - "url": "https://example.com" - } - ] -} \ No newline at end of file diff --git a/cmd/twirp-openapi-gen/internal/generator/testdata/gen/go/payment/v1alpha1/payment.pb.go b/cmd/twirp-openapi-gen/internal/generator/testdata/gen/go/payment/v1alpha1/payment.pb.go deleted file mode 100644 index 6b84da8..0000000 --- a/cmd/twirp-openapi-gen/internal/generator/testdata/gen/go/payment/v1alpha1/payment.pb.go +++ /dev/null @@ -1,263 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc (unknown) -// source: payment/v1alpha1/payment.proto - -package v1alpha1 - -import ( - money "google.golang.org/genproto/googleapis/type/money" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// PaymentProvider represents the supported set -// of payment providers. -type PaymentProvider int32 - -const ( - PaymentProvider_PAYMENT_PROVIDER_UNSPECIFIED PaymentProvider = 0 - PaymentProvider_PAYMENT_PROVIDER_STRIPE PaymentProvider = 1 - PaymentProvider_PAYMENT_PROVIDER_PAYPAL PaymentProvider = 2 - PaymentProvider_PAYMENT_PROVIDER_APPLE PaymentProvider = 3 -) - -// Enum value maps for PaymentProvider. -var ( - PaymentProvider_name = map[int32]string{ - 0: "PAYMENT_PROVIDER_UNSPECIFIED", - 1: "PAYMENT_PROVIDER_STRIPE", - 2: "PAYMENT_PROVIDER_PAYPAL", - 3: "PAYMENT_PROVIDER_APPLE", - } - PaymentProvider_value = map[string]int32{ - "PAYMENT_PROVIDER_UNSPECIFIED": 0, - "PAYMENT_PROVIDER_STRIPE": 1, - "PAYMENT_PROVIDER_PAYPAL": 2, - "PAYMENT_PROVIDER_APPLE": 3, - } -) - -func (x PaymentProvider) Enum() *PaymentProvider { - p := new(PaymentProvider) - *p = x - return p -} - -func (x PaymentProvider) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (PaymentProvider) Descriptor() protoreflect.EnumDescriptor { - return file_payment_v1alpha1_payment_proto_enumTypes[0].Descriptor() -} - -func (PaymentProvider) Type() protoreflect.EnumType { - return &file_payment_v1alpha1_payment_proto_enumTypes[0] -} - -func (x PaymentProvider) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use PaymentProvider.Descriptor instead. -func (PaymentProvider) EnumDescriptor() ([]byte, []int) { - return file_payment_v1alpha1_payment_proto_rawDescGZIP(), []int{0} -} - -// Order represents a monetary order. -type Order struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - OrderId string `protobuf:"bytes,1,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` - RecipientId string `protobuf:"bytes,2,opt,name=recipient_id,json=recipientId,proto3" json:"recipient_id,omitempty"` - Amount *money.Money `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount,omitempty"` - PaymentProvider PaymentProvider `protobuf:"varint,4,opt,name=payment_provider,json=paymentProvider,proto3,enum=payment.v1alpha1.PaymentProvider" json:"payment_provider,omitempty"` -} - -func (x *Order) Reset() { - *x = Order{} - if protoimpl.UnsafeEnabled { - mi := &file_payment_v1alpha1_payment_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Order) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Order) ProtoMessage() {} - -func (x *Order) ProtoReflect() protoreflect.Message { - mi := &file_payment_v1alpha1_payment_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Order.ProtoReflect.Descriptor instead. -func (*Order) Descriptor() ([]byte, []int) { - return file_payment_v1alpha1_payment_proto_rawDescGZIP(), []int{0} -} - -func (x *Order) GetOrderId() string { - if x != nil { - return x.OrderId - } - return "" -} - -func (x *Order) GetRecipientId() string { - if x != nil { - return x.RecipientId - } - return "" -} - -func (x *Order) GetAmount() *money.Money { - if x != nil { - return x.Amount - } - return nil -} - -func (x *Order) GetPaymentProvider() PaymentProvider { - if x != nil { - return x.PaymentProvider - } - return PaymentProvider_PAYMENT_PROVIDER_UNSPECIFIED -} - -var File_payment_v1alpha1_payment_proto protoreflect.FileDescriptor - -var file_payment_v1alpha1_payment_proto_rawDesc = []byte{ - 0x0a, 0x1e, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x10, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x1a, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x2f, - 0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbf, 0x01, 0x0a, 0x05, - 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, - 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, - 0x74, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x74, 0x79, 0x70, - 0x65, 0x2e, 0x4d, 0x6f, 0x6e, 0x65, 0x79, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, - 0x4c, 0x0a, 0x10, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x70, 0x61, 0x79, 0x6d, - 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x0f, 0x70, 0x61, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2a, 0x89, 0x01, - 0x0a, 0x0f, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x12, 0x20, 0x0a, 0x1c, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x50, 0x52, 0x4f, - 0x56, 0x49, 0x44, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x50, - 0x52, 0x4f, 0x56, 0x49, 0x44, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x50, 0x45, 0x10, 0x01, - 0x12, 0x1b, 0x0a, 0x17, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x56, - 0x49, 0x44, 0x45, 0x52, 0x5f, 0x50, 0x41, 0x59, 0x50, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x1a, 0x0a, - 0x16, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x44, 0x45, - 0x52, 0x5f, 0x41, 0x50, 0x50, 0x4c, 0x45, 0x10, 0x03, 0x42, 0xe4, 0x01, 0x0a, 0x14, 0x63, 0x6f, - 0x6d, 0x2e, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x42, 0x0c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x5d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x2f, 0x74, 0x77, 0x69, 0x72, - 0x70, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x2d, 0x67, 0x65, 0x6e, 0x2f, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, - 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, - 0x2f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0xa2, 0x02, 0x03, 0x50, 0x58, 0x58, 0xaa, 0x02, 0x10, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x10, 0x50, 0x61, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x1c, - 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x11, 0x50, - 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_payment_v1alpha1_payment_proto_rawDescOnce sync.Once - file_payment_v1alpha1_payment_proto_rawDescData = file_payment_v1alpha1_payment_proto_rawDesc -) - -func file_payment_v1alpha1_payment_proto_rawDescGZIP() []byte { - file_payment_v1alpha1_payment_proto_rawDescOnce.Do(func() { - file_payment_v1alpha1_payment_proto_rawDescData = protoimpl.X.CompressGZIP(file_payment_v1alpha1_payment_proto_rawDescData) - }) - return file_payment_v1alpha1_payment_proto_rawDescData -} - -var file_payment_v1alpha1_payment_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_payment_v1alpha1_payment_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_payment_v1alpha1_payment_proto_goTypes = []interface{}{ - (PaymentProvider)(0), // 0: payment.v1alpha1.PaymentProvider - (*Order)(nil), // 1: payment.v1alpha1.Order - (*money.Money)(nil), // 2: google.type.Money -} -var file_payment_v1alpha1_payment_proto_depIdxs = []int32{ - 2, // 0: payment.v1alpha1.Order.amount:type_name -> google.type.Money - 0, // 1: payment.v1alpha1.Order.payment_provider:type_name -> payment.v1alpha1.PaymentProvider - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_payment_v1alpha1_payment_proto_init() } -func file_payment_v1alpha1_payment_proto_init() { - if File_payment_v1alpha1_payment_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_payment_v1alpha1_payment_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Order); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_payment_v1alpha1_payment_proto_rawDesc, - NumEnums: 1, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_payment_v1alpha1_payment_proto_goTypes, - DependencyIndexes: file_payment_v1alpha1_payment_proto_depIdxs, - EnumInfos: file_payment_v1alpha1_payment_proto_enumTypes, - MessageInfos: file_payment_v1alpha1_payment_proto_msgTypes, - }.Build() - File_payment_v1alpha1_payment_proto = out.File - file_payment_v1alpha1_payment_proto_rawDesc = nil - file_payment_v1alpha1_payment_proto_goTypes = nil - file_payment_v1alpha1_payment_proto_depIdxs = nil -} diff --git a/cmd/twirp-openapi-gen/internal/generator/testdata/gen/go/pet/v1/pet.pb.go b/cmd/twirp-openapi-gen/internal/generator/testdata/gen/go/pet/v1/pet.pb.go deleted file mode 100644 index 1dfbaa7..0000000 --- a/cmd/twirp-openapi-gen/internal/generator/testdata/gen/go/pet/v1/pet.pb.go +++ /dev/null @@ -1,896 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc (unknown) -// source: pet/v1/pet.proto - -package v1 - -import ( - v1alpha1 "github.com/blockthrough/twirp-openapi-gen/internal/generator/testdata/gen/go/payment/v1alpha1" - datetime "google.golang.org/genproto/googleapis/type/datetime" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - anypb "google.golang.org/protobuf/types/known/anypb" - emptypb "google.golang.org/protobuf/types/known/emptypb" - structpb "google.golang.org/protobuf/types/known/structpb" - _ "google.golang.org/protobuf/types/known/wrapperspb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// PetType represents the different types of pets in the pet store. -type PetType int32 - -const ( - PetType_PET_TYPE_UNSPECIFIED PetType = 0 - PetType_PET_TYPE_CAT PetType = 1 - PetType_PET_TYPE_DOG PetType = 2 - PetType_PET_TYPE_SNAKE PetType = 3 - PetType_PET_TYPE_HAMSTER PetType = 4 -) - -// Enum value maps for PetType. -var ( - PetType_name = map[int32]string{ - 0: "PET_TYPE_UNSPECIFIED", - 1: "PET_TYPE_CAT", - 2: "PET_TYPE_DOG", - 3: "PET_TYPE_SNAKE", - 4: "PET_TYPE_HAMSTER", - } - PetType_value = map[string]int32{ - "PET_TYPE_UNSPECIFIED": 0, - "PET_TYPE_CAT": 1, - "PET_TYPE_DOG": 2, - "PET_TYPE_SNAKE": 3, - "PET_TYPE_HAMSTER": 4, - } -) - -func (x PetType) Enum() *PetType { - p := new(PetType) - *p = x - return p -} - -func (x PetType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (PetType) Descriptor() protoreflect.EnumDescriptor { - return file_pet_v1_pet_proto_enumTypes[0].Descriptor() -} - -func (PetType) Type() protoreflect.EnumType { - return &file_pet_v1_pet_proto_enumTypes[0] -} - -func (x PetType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use PetType.Descriptor instead. -func (PetType) EnumDescriptor() ([]byte, []int) { - return file_pet_v1_pet_proto_rawDescGZIP(), []int{0} -} - -// GetPetRequest is the request object for GetPet -// The message accepts a pet id as an input -type GetPetRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PetId string `protobuf:"bytes,1,opt,name=pet_id,json=petId,proto3" json:"pet_id,omitempty"` -} - -func (x *GetPetRequest) Reset() { - *x = GetPetRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pet_v1_pet_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetPetRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetPetRequest) ProtoMessage() {} - -func (x *GetPetRequest) ProtoReflect() protoreflect.Message { - mi := &file_pet_v1_pet_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetPetRequest.ProtoReflect.Descriptor instead. -func (*GetPetRequest) Descriptor() ([]byte, []int) { - return file_pet_v1_pet_proto_rawDescGZIP(), []int{0} -} - -func (x *GetPetRequest) GetPetId() string { - if x != nil { - return x.PetId - } - return "" -} - -type GetPetResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Pet *Pet `protobuf:"bytes,1,opt,name=pet,proto3" json:"pet,omitempty"` -} - -func (x *GetPetResponse) Reset() { - *x = GetPetResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pet_v1_pet_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetPetResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetPetResponse) ProtoMessage() {} - -func (x *GetPetResponse) ProtoReflect() protoreflect.Message { - mi := &file_pet_v1_pet_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.Load