func (g *Generator) createMainFile(mainFile string, funcs template.FuncMap) error { g.genfiles = append(g.genfiles, mainFile) file, err := codegen.SourceFileFor(mainFile) if err != nil { return err } funcs["getPort"] = func(hostport string) string { _, port, err := net.SplitHostPort(hostport) if err != nil { return "8080" } return port } outPkg, err := codegen.PackagePath(g.OutDir) if err != nil { return err } appPkg := path.Join(outPkg, "app") imports := []*codegen.ImportSpec{ codegen.SimpleImport("time"), codegen.SimpleImport("github.com/goadesign/goa"), codegen.SimpleImport("github.com/goadesign/goa/middleware"), codegen.SimpleImport(appPkg), } file.Write([]byte("//go:generate goagen bootstrap -d " + g.DesignPkg + "\n\n")) file.WriteHeader("", "main", imports) data := map[string]interface{}{ "Name": g.API.Name, "API": g.API, } if err = file.ExecuteTemplate("main", mainT, funcs, data); err != nil { return err } return file.FormatCode() }
// Generate is the generator entry point called by the meta generator. func Generate() (files []string, err error) { var outDir, target, appPkg, ver string set := flag.NewFlagSet("gorma", flag.PanicOnError) set.String("design", "", "") set.StringVar(&outDir, "out", "", "") set.StringVar(&ver, "version", "", "") set.StringVar(&target, "pkg", "models", "") set.StringVar(&appPkg, "app", "app", "") set.Parse(os.Args[2:]) // First check compatibility if err := codegen.CheckVersion(ver); err != nil { return nil, err } // Now proceed appPkgPath, err := codegen.PackagePath(filepath.Join(outDir, appPkg)) if err != nil { return nil, fmt.Errorf("invalid app package: %s", err) } outDir = filepath.Join(outDir, target) g := &Generator{outDir: outDir, target: target, appPkg: appPkg, appPkgPath: appPkgPath} return g.Generate(design.Design) }
// Generate produces the skeleton main. func (g *Generator) Generate(api *design.APIDefinition) (_ []string, err error) { go utils.Catch(nil, func() { g.Cleanup() }) defer func() { if err != nil { g.Cleanup() } }() // Make tool directory toolDir, err := makeToolDir(g, api.Name) if err != nil { return } funcs := template.FuncMap{ "goify": codegen.Goify, "gotypedef": codegen.GoTypeDef, "gotyperefext": goTypeRefExt, "nativeType": codegen.GoNativeType, "joinNames": joinNames, "join": join, "toString": toString, "tempvar": codegen.Tempvar, "title": strings.Title, "flagType": flagType, "defaultPath": defaultPath, "toGo": toGo, } clientPkg, err := codegen.PackagePath(codegen.OutputDir) if err != nil { return } arrayToStringTmpl = template.Must(template.New("client").Funcs(funcs).Parse(arrayToStringT)) // Generate client/client-cli/main.go if err = g.generateMain(filepath.Join(toolDir, "main.go"), clientPkg, funcs, api); err != nil { return } // Generate client/client-cli/commands.go if err = g.generateCommands(filepath.Join(toolDir, "commands.go"), clientPkg, funcs, api); err != nil { return } // Generate client/client.go if err = g.generateClient(filepath.Join(codegen.OutputDir, "client.go"), clientPkg, funcs, api); err != nil { return } // Generate client/$res.go if err = g.generateClientResources(clientPkg, funcs, api); err != nil { return } return g.genfiles, nil }
// Generate produces the skeleton main. func (g *Generator) Generate(api *design.APIDefinition) (_ []string, err error) { go utils.Catch(nil, func() { g.Cleanup() }) defer func() { if err != nil { g.Cleanup() } }() // Make tool directory var toolDir string toolDir, err = makeToolDir(g, api.Name) if err != nil { return } funcs := template.FuncMap{ "add": func(a, b int) int { return a + b }, "cmdFieldType": cmdFieldType, "defaultPath": defaultPath, "escapeBackticks": escapeBackticks, "flagType": flagType, "goify": codegen.Goify, "gotypedef": codegen.GoTypeDef, "gotypedesc": codegen.GoTypeDesc, "gotyperef": codegen.GoTypeRef, "gotypename": codegen.GoTypeName, "gotyperefext": goTypeRefExt, "join": join, "multiComment": multiComment, "pathParams": pathParams, "pathParamNames": pathParamNames, "pathTemplate": pathTemplate, "tempvar": codegen.Tempvar, "title": strings.Title, "toString": toString, "typeName": typeName, "signerType": signerType, } clientPkg, err := codegen.PackagePath(codegen.OutputDir) if err != nil { return } arrayToStringTmpl = template.Must(template.New("client").Funcs(funcs).Parse(arrayToStringT)) // Generate client/client-cli/main.go if err = g.generateMain(filepath.Join(toolDir, "main.go"), clientPkg, funcs, api); err != nil { return } // Generate client/client-cli/commands.go if err = g.generateCommands(filepath.Join(toolDir, "commands.go"), clientPkg, funcs, api); err != nil { return } // Generate client/client.go if err = g.generateClient(filepath.Join(codegen.OutputDir, "client.go"), clientPkg, funcs, api); err != nil { return } // Generate client/$res.go and types.go if err = g.generateClientResources(clientPkg, funcs, api); err != nil { return } return g.genfiles, nil }
// Generate produces the skeleton main. func (g *Generator) Generate(api *design.APIDefinition) (_ []string, err error) { go utils.Catch(nil, func() { g.Cleanup() }) defer func() { if err != nil { g.Cleanup() } }() mainFile := filepath.Join(codegen.OutputDir, "main.go") if Force { os.Remove(mainFile) } g.genfiles = append(g.genfiles, mainFile) _, err = os.Stat(mainFile) funcs := template.FuncMap{ "tempvar": tempvar, "generateSwagger": generateSwagger, "okResp": okResp, "newControllerVersion": newControllerVersion, "targetPkg": func() string { return TargetPackage }, } if err != nil { file, err := codegen.SourceFileFor(mainFile) if err != nil { return nil, err } var outPkg string outPkg, err = codegen.PackagePath(codegen.OutputDir) if err != nil { return nil, err } outPkg = strings.TrimPrefix(filepath.ToSlash(outPkg), "src/") appPkg := path.Join(outPkg, "app") swaggerPkg := path.Join(outPkg, "swagger") imports := []*codegen.ImportSpec{ codegen.SimpleImport("github.com/goadesign/goa"), codegen.SimpleImport("github.com/goadesign/middleware"), codegen.SimpleImport(appPkg), codegen.SimpleImport(swaggerPkg), } if generateSwagger() { jsonSchemaPkg := path.Join(outPkg, "schema") imports = append(imports, codegen.SimpleImport(jsonSchemaPkg)) } file.WriteHeader("", "main", imports) data := map[string]interface{}{ "Name": AppName, "API": api, } if err = file.ExecuteTemplate("main", mainT, funcs, data); err != nil { return nil, err } if err = file.FormatCode(); err != nil { return nil, err } } imp, err := codegen.PackagePath(codegen.OutputDir) if err != nil { return } imp = path.Join(filepath.ToSlash(imp), "app") imports := []*codegen.ImportSpec{ codegen.SimpleImport("github.com/goadesign/goa"), codegen.SimpleImport(imp), } api.IterateVersions(func(v *design.APIVersionDefinition) error { if v.IsDefault() { return nil } imports = append(imports, codegen.SimpleImport(imp+"/"+codegen.VersionPackage(v.Version))) return nil }) err = api.IterateResources(func(r *design.ResourceDefinition) error { filename := filepath.Join(codegen.OutputDir, snakeCase(r.Name)+".go") if Force { if err := os.Remove(filename); err != nil { return err } } g.genfiles = append(g.genfiles, filename) if _, err := os.Stat(filename); err != nil { file, err := codegen.SourceFileFor(filename) if err != nil { return err } file.WriteHeader("", "main", imports) err = file.ExecuteTemplate("controller", ctrlT, funcs, r) if err != nil { return err } if err := file.FormatCode(); err != nil { return err } } return nil }) if err != nil { return } return g.genfiles, nil }
// Generate produces the skeleton main. func (g *Generator) Generate() (_ []string, err error) { go utils.Catch(nil, func() { g.Cleanup() }) defer func() { if err != nil { g.Cleanup() } }() if g.Target == "" { g.Target = "app" } codegen.Reserved[g.Target] = true mainFile := filepath.Join(g.OutDir, "main.go") if g.Force { os.Remove(mainFile) } funcs := template.FuncMap{ "tempvar": tempvar, "okResp": g.okResp, "targetPkg": func() string { return g.Target }, } imp, err := codegen.PackagePath(g.OutDir) if err != nil { return nil, err } imp = path.Join(filepath.ToSlash(imp), "app") _, err = os.Stat(mainFile) if err != nil { if err = g.createMainFile(mainFile, funcs); err != nil { return nil, err } } imports := []*codegen.ImportSpec{ codegen.SimpleImport("io"), codegen.SimpleImport("github.com/goadesign/goa"), codegen.SimpleImport(imp), codegen.SimpleImport("golang.org/x/net/websocket"), } err = g.API.IterateResources(func(r *design.ResourceDefinition) error { filename := filepath.Join(g.OutDir, codegen.SnakeCase(r.Name)+".go") if g.Force { os.Remove(filename) } if _, e := os.Stat(filename); e != nil { g.genfiles = append(g.genfiles, filename) file, err2 := codegen.SourceFileFor(filename) if err2 != nil { return err } file.WriteHeader("", "main", imports) if err2 = file.ExecuteTemplate("controller", ctrlT, funcs, r); err2 != nil { return err } err2 = r.IterateActions(func(a *design.ActionDefinition) error { if a.WebSocket() { return file.ExecuteTemplate("actionWS", actionWST, funcs, a) } return file.ExecuteTemplate("action", actionT, funcs, a) }) if err2 != nil { return err } if err2 = file.FormatCode(); err2 != nil { return err2 } } return nil }) if err != nil { return } return g.genfiles, nil }
func (g *Generator) generateResourceTest() error { if len(g.API.Resources) == 0 { return nil } funcs := template.FuncMap{"isSlice": isSlice} testTmpl := template.Must(template.New("test").Funcs(funcs).Parse(testTmpl)) outDir, err := makeTestDir(g, g.API.Name) if err != nil { return err } appPkg, err := codegen.PackagePath(g.OutDir) if err != nil { return err } imports := []*codegen.ImportSpec{ codegen.SimpleImport("bytes"), codegen.SimpleImport("fmt"), codegen.SimpleImport("io"), codegen.SimpleImport("log"), codegen.SimpleImport("net/http"), codegen.SimpleImport("net/http/httptest"), codegen.SimpleImport("net/url"), codegen.SimpleImport("strconv"), codegen.SimpleImport("strings"), codegen.SimpleImport("time"), codegen.SimpleImport(appPkg), codegen.SimpleImport("github.com/goadesign/goa"), codegen.SimpleImport("github.com/goadesign/goa/goatest"), codegen.SimpleImport("golang.org/x/net/context"), codegen.NewImport("uuid", "github.com/satori/go.uuid"), } return g.API.IterateResources(func(res *design.ResourceDefinition) error { filename := filepath.Join(outDir, codegen.SnakeCase(res.Name)+"_testing.go") file, err := codegen.SourceFileFor(filename) if err != nil { return err } title := fmt.Sprintf("%s: %s TestHelpers", g.API.Context(), res.Name) if err := file.WriteHeader(title, "test", imports); err != nil { return err } var methods []*TestMethod if err := res.IterateActions(func(action *design.ActionDefinition) error { if err := action.IterateResponses(func(response *design.ResponseDefinition) error { if response.Status == 101 { // SwitchingProtocols, Don't currently handle WebSocket endpoints return nil } for routeIndex, route := range action.Routes { mediaType := design.Design.MediaTypeWithIdentifier(response.MediaType) if mediaType == nil { methods = append(methods, g.createTestMethod(res, action, response, route, routeIndex, nil, nil)) } else { if err := mediaType.IterateViews(func(view *design.ViewDefinition) error { methods = append(methods, g.createTestMethod(res, action, response, route, routeIndex, mediaType, view)) return nil }); err != nil { return err } } } return nil }); err != nil { return err } return nil }); err != nil { return err } g.genfiles = append(g.genfiles, filename) err = testTmpl.Execute(file, methods) if err != nil { panic(err) } return file.FormatCode() }) }
// Generate generats the client package and CLI. func (g *Generator) Generate() (_ []string, err error) { go utils.Catch(nil, func() { g.Cleanup() }) defer func() { if err != nil { g.Cleanup() } }() if g.Target == "" { g.Target = "client" } if g.ToolDirName == "" { g.ToolDirName = "tool" } if g.Tool == "" { g.Tool = defaultToolName(g.API) } codegen.Reserved[g.Target] = true // Setup output directories as needed var pkgDir, toolDir, cliDir string { if !g.NoTool { toolDir = filepath.Join(g.OutDir, g.ToolDirName, g.Tool) if _, err = os.Stat(toolDir); err != nil { if err = os.MkdirAll(toolDir, 0755); err != nil { return } } cliDir = filepath.Join(g.OutDir, g.ToolDirName, "cli") if err = os.RemoveAll(cliDir); err != nil { return } if err = os.MkdirAll(cliDir, 0755); err != nil { return } } pkgDir = filepath.Join(g.OutDir, g.Target) if err = os.RemoveAll(pkgDir); err != nil { return } if err = os.MkdirAll(pkgDir, 0755); err != nil { return } } // Setup generation var funcs template.FuncMap var clientPkg, cliPkg string { funcs = template.FuncMap{ "add": func(a, b int) int { return a + b }, "cmdFieldType": cmdFieldType, "defaultPath": defaultPath, "escapeBackticks": escapeBackticks, "goify": codegen.Goify, "gotypedef": codegen.GoTypeDef, "gotypedesc": codegen.GoTypeDesc, "gotypename": codegen.GoTypeName, "gotyperef": codegen.GoTypeRef, "gotyperefext": goTypeRefExt, "join": join, "joinStrings": strings.Join, "multiComment": multiComment, "pathParamNames": pathParamNames, "pathParams": pathParams, "pathTemplate": pathTemplate, "signerType": signerType, "tempvar": codegen.Tempvar, "title": strings.Title, "toString": toString, "typeName": typeName, "format": format, "handleSpecialTypes": handleSpecialTypes, } clientPkg, err = codegen.PackagePath(pkgDir) if err != nil { return } cliPkg, err = codegen.PackagePath(cliDir) if err != nil { return } arrayToStringTmpl = template.Must(template.New("client").Funcs(funcs).Parse(arrayToStringT)) } if !g.NoTool { // Generate tool/main.go (only once) mainFile := filepath.Join(toolDir, "main.go") if _, err := os.Stat(mainFile); err != nil { g.genfiles = append(g.genfiles, toolDir) if err = g.generateMain(mainFile, clientPkg, cliPkg, funcs); err != nil { return nil, err } } // Generate tool/cli/commands.go g.genfiles = append(g.genfiles, cliDir) if err = g.generateCommands(filepath.Join(cliDir, "commands.go"), clientPkg, funcs); err != nil { return } } // Generate client/client.go g.genfiles = append(g.genfiles, pkgDir) if err = g.generateClient(filepath.Join(pkgDir, "client.go"), clientPkg, funcs); err != nil { return } // Generate client/$res.go and types.go if err = g.generateClientResources(pkgDir, clientPkg, funcs); err != nil { return } return g.genfiles, nil }