// generateUserTypes iterates through the user types and generates the data structures and // marshaling code. func (g *Generator) generateUserTypes(api *design.APIDefinition) error { utFile := filepath.Join(AppOutputDir(), "user_types.go") utWr, err := NewUserTypesWriter(utFile) if err != nil { panic(err) // bug } title := fmt.Sprintf("%s: Application User Types", api.Context()) imports := []*codegen.ImportSpec{ codegen.SimpleImport("github.com/goadesign/goa"), codegen.SimpleImport("fmt"), codegen.SimpleImport("time"), } utWr.WriteHeader(title, TargetPackage, imports) err = api.IterateUserTypes(func(t *design.UserTypeDefinition) error { return utWr.Execute(t) }) g.genfiles = append(g.genfiles, utFile) if err != nil { return err } return utWr.FormatCode() }
func (g *Generator) generateClientResources(clientPkg string, funcs template.FuncMap, api *design.APIDefinition) error { userTypeTmpl := template.Must(template.New("userType").Funcs(funcs).Parse(userTypeTmpl)) typeDecodeTmpl := template.Must(template.New("typeDecode").Funcs(funcs).Parse(typeDecodeTmpl)) err := api.IterateResources(func(res *design.ResourceDefinition) error { return g.generateResourceClient(res, funcs) }) if err != nil { return err } types := make(map[string]*design.UserTypeDefinition) for _, res := range api.Resources { for n, ut := range res.UserTypes() { types[n] = ut } } filename := filepath.Join(codegen.OutputDir, typesFileName+".go") file, err := codegen.SourceFileFor(filename) if err != nil { return err } imports := []*codegen.ImportSpec{ codegen.SimpleImport("github.com/goadesign/goa"), codegen.SimpleImport("fmt"), codegen.SimpleImport("io"), codegen.SimpleImport("time"), codegen.NewImport("uuid", "github.com/satori/go.uuid"), } if err := file.WriteHeader("User Types", "client", imports); err != nil { return err } g.genfiles = append(g.genfiles, filename) // Generate user and media types used by action payloads and parameters err = api.IterateUserTypes(func(userType *design.UserTypeDefinition) error { if _, ok := g.generatedTypes[userType.TypeName]; ok { return nil } if _, ok := types[userType.TypeName]; ok { g.generatedTypes[userType.TypeName] = true return userTypeTmpl.Execute(file, userType) } return nil }) if err != nil { return err } // Generate media types used by action responses and their load helpers err = api.IterateResources(func(res *design.ResourceDefinition) error { return res.IterateActions(func(a *design.ActionDefinition) error { return a.IterateResponses(func(r *design.ResponseDefinition) error { if mt := api.MediaTypeWithIdentifier(r.MediaType); mt != nil { if _, ok := g.generatedTypes[mt.TypeName]; !ok { g.generatedTypes[mt.TypeName] = true if !mt.IsBuiltIn() { if err := userTypeTmpl.Execute(file, mt); err != nil { return err } } typeName := mt.TypeName if mt.IsBuiltIn() { elems := strings.Split(typeName, ".") typeName = elems[len(elems)-1] } if err := typeDecodeTmpl.Execute(file, mt); err != nil { return err } } } return nil }) }) }) if err != nil { return err } // Generate media types used in payloads but not in responses err = api.IterateMediaTypes(func(mediaType *design.MediaTypeDefinition) error { if mediaType.IsBuiltIn() { return nil } if _, ok := g.generatedTypes[mediaType.TypeName]; ok { return nil } if _, ok := types[mediaType.TypeName]; ok { g.generatedTypes[mediaType.TypeName] = true return userTypeTmpl.Execute(file, mediaType) } return nil }) if err != nil { return err } return file.FormatCode() }