// generateMediaTypes iterates through the media types and generate the data structures and // marshaling code. func (g *Generator) generateMediaTypes(api *design.APIDefinition) error { mtFile := filepath.Join(AppOutputDir(), "media_types.go") mtWr, err := NewMediaTypesWriter(mtFile) if err != nil { panic(err) // bug } title := fmt.Sprintf("%s: Application Media Types", api.Context()) imports := []*codegen.ImportSpec{ codegen.SimpleImport("github.com/goadesign/goa"), codegen.SimpleImport("fmt"), codegen.SimpleImport("time"), codegen.NewImport("uuid", "github.com/satori/go.uuid"), } mtWr.WriteHeader(title, TargetPackage, imports) err = api.IterateMediaTypes(func(mt *design.MediaTypeDefinition) error { if mt.IsBuiltIn() { return nil } if mt.Type.IsObject() || mt.Type.IsArray() { return mtWr.Execute(mt) } return nil }) g.genfiles = append(g.genfiles, mtFile) if err != nil { return err } return mtWr.FormatCode() }
// generateHrefs iterates through the API resources and generates the href factory methods. func (g *Generator) generateHrefs(api *design.APIDefinition) error { hrefFile := filepath.Join(AppOutputDir(), "hrefs.go") resWr, err := NewResourcesWriter(hrefFile) if err != nil { panic(err) // bug } title := fmt.Sprintf("%s: Application Resource Href Factories", api.Context()) imports := []*codegen.ImportSpec{ codegen.SimpleImport("fmt"), } resWr.WriteHeader(title, TargetPackage, imports) err = api.IterateResources(func(r *design.ResourceDefinition) error { m := api.MediaTypeWithIdentifier(r.MediaType) var identifier string if m != nil { identifier = m.Identifier } else { identifier = "text/plain" } data := ResourceData{ Name: codegen.Goify(r.Name, true), Identifier: identifier, Description: r.Description, Type: m, CanonicalTemplate: codegen.CanonicalTemplate(r), CanonicalParams: codegen.CanonicalParams(r), } return resWr.Execute(&data) }) g.genfiles = append(g.genfiles, hrefFile) if err != nil { return err } return resWr.FormatCode() }
// generateControllers iterates through the API resources and generates the low level // controllers. func (g *Generator) generateSecurity(api *design.APIDefinition) error { if len(api.SecuritySchemes) == 0 { return nil } secFile := filepath.Join(AppOutputDir(), "security.go") secWr, err := NewSecurityWriter(secFile) if err != nil { panic(err) // bug } title := fmt.Sprintf("%s: Application Security", api.Context()) imports := []*codegen.ImportSpec{ codegen.SimpleImport("net/http"), codegen.SimpleImport("errors"), codegen.SimpleImport("golang.org/x/net/context"), codegen.SimpleImport("github.com/goadesign/goa"), } secWr.WriteHeader(title, TargetPackage, imports) g.genfiles = append(g.genfiles, secFile) if err = secWr.Execute(design.Design.SecuritySchemes); err != nil { return err } return secWr.FormatCode() }
// generateUserTypes iterates through the user types and generates the data structures and // marshaling code. func (g *Generator) generateUserTypes(outdir string, api *design.APIDefinition) error { var modelname, filename string err := GormaDesign.IterateStores(func(store *RelationalStoreDefinition) error { err := store.IterateModels(func(model *RelationalModelDefinition) error { modelname = strings.ToLower(codegen.Goify(model.ModelName, false)) filename = fmt.Sprintf("%s.go", modelname) utFile := filepath.Join(outdir, filename) err := os.RemoveAll(utFile) if err != nil { fmt.Println(err) } utWr, err := NewUserTypesWriter(utFile) if err != nil { panic(err) // bug } title := fmt.Sprintf("%s: Models", api.Context()) imports := []*codegen.ImportSpec{ codegen.SimpleImport(g.appPkgPath), codegen.SimpleImport("time"), codegen.SimpleImport("github.com/goadesign/goa"), codegen.SimpleImport("github.com/jinzhu/gorm"), codegen.SimpleImport("golang.org/x/net/context"), codegen.SimpleImport("golang.org/x/net/context"), codegen.SimpleImport("github.com/goadesign/goa/uuid"), } if model.Cached { imp := codegen.NewImport("cache", "github.com/patrickmn/go-cache") imports = append(imports, imp) imp = codegen.SimpleImport("strconv") imports = append(imports, imp) } utWr.WriteHeader(title, g.target, imports) data := &UserTypeTemplateData{ APIDefinition: api, UserType: model, DefaultPkg: g.target, AppPkg: g.appPkgPath, } err = utWr.Execute(data) g.genfiles = append(g.genfiles, utFile) if err != nil { fmt.Println(err) return err } err = utWr.FormatCode() if err != nil { fmt.Println(err) } return err }) return err }) return err }
// generateContexts iterates through the API resources and actions and generates the action // contexts. func (g *Generator) generateContexts(api *design.APIDefinition) error { ctxFile := filepath.Join(AppOutputDir(), "contexts.go") ctxWr, err := NewContextsWriter(ctxFile) if err != nil { panic(err) // bug } title := fmt.Sprintf("%s: Application Contexts", api.Context()) imports := []*codegen.ImportSpec{ codegen.SimpleImport("fmt"), codegen.SimpleImport("golang.org/x/net/context"), codegen.SimpleImport("strconv"), codegen.SimpleImport("strings"), codegen.SimpleImport("time"), codegen.SimpleImport("github.com/goadesign/goa"), codegen.NewImport("uuid", "github.com/satori/go.uuid"), } ctxWr.WriteHeader(title, TargetPackage, imports) err = api.IterateResources(func(r *design.ResourceDefinition) error { return r.IterateActions(func(a *design.ActionDefinition) error { ctxName := codegen.Goify(a.Name, true) + codegen.Goify(a.Parent.Name, true) + "Context" headers := r.Headers.Merge(a.Headers) if headers != nil && len(headers.Type.ToObject()) == 0 { headers = nil // So that {{if .Headers}} returns false in templates } params := a.AllParams() if params != nil && len(params.Type.ToObject()) == 0 { params = nil // So that {{if .Params}} returns false in templates } ctxData := ContextTemplateData{ Name: ctxName, ResourceName: r.Name, ActionName: a.Name, Payload: a.Payload, Params: params, Headers: headers, Routes: a.Routes, Responses: BuildResponses(r.Responses, a.Responses), API: api, DefaultPkg: TargetPackage, Security: a.Security, } return ctxWr.Execute(&ctxData) }) }) g.genfiles = append(g.genfiles, ctxFile) if err != nil { return err } return ctxWr.FormatCode() }
// 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() }
// generateControllers iterates through the API resources and generates the low level // controllers. func (g *Generator) generateControllers(api *design.APIDefinition) error { ctlFile := filepath.Join(AppOutputDir(), "controllers.go") ctlWr, err := NewControllersWriter(ctlFile) if err != nil { panic(err) // bug } title := fmt.Sprintf("%s: Application Controllers", api.Context()) imports := []*codegen.ImportSpec{ codegen.SimpleImport("net/http"), codegen.SimpleImport("fmt"), codegen.SimpleImport("golang.org/x/net/context"), codegen.SimpleImport("github.com/goadesign/goa"), codegen.SimpleImport("github.com/goadesign/goa/cors"), } encoders, err := BuildEncoders(api.Produces, true) if err != nil { return err } decoders, err := BuildEncoders(api.Consumes, false) if err != nil { return err } encoderImports := make(map[string]bool) for _, data := range encoders { encoderImports[data.PackagePath] = true } for _, data := range decoders { encoderImports[data.PackagePath] = true } for packagePath := range encoderImports { if packagePath != "github.com/goadesign/goa" { imports = append(imports, codegen.SimpleImport(packagePath)) } } ctlWr.WriteHeader(title, TargetPackage, imports) ctlWr.WriteInitService(encoders, decoders) var controllersData []*ControllerTemplateData err = api.IterateResources(func(r *design.ResourceDefinition) error { data := &ControllerTemplateData{ API: api, Resource: codegen.Goify(r.Name, true), PreflightPaths: r.PreflightPaths(), } ierr := r.IterateActions(func(a *design.ActionDefinition) error { context := fmt.Sprintf("%s%sContext", codegen.Goify(a.Name, true), codegen.Goify(r.Name, true)) unmarshal := fmt.Sprintf("unmarshal%s%sPayload", codegen.Goify(a.Name, true), codegen.Goify(r.Name, true)) action := map[string]interface{}{ "Name": codegen.Goify(a.Name, true), "Routes": a.Routes, "Context": context, "Unmarshal": unmarshal, "Payload": a.Payload, "Security": a.Security, } data.Actions = append(data.Actions, action) return nil }) if ierr != nil { return ierr } if len(data.Actions) > 0 { data.Encoders = encoders data.Decoders = decoders data.Origins = r.AllOrigins() controllersData = append(controllersData, data) } return nil }) if err != nil { return err } g.genfiles = append(g.genfiles, ctlFile) if err = ctlWr.Execute(controllersData); err != nil { return err } return ctlWr.FormatCode() }