// Generate is the generator entry point called by the meta generator. func Generate(api *design.APIDefinition) (_ []string, err error) { var genfiles []string cleanup := func() { for _, f := range genfiles { os.Remove(f) } } go utils.Catch(nil, cleanup) defer func() { if err != nil { cleanup() } }() app := kingpin.New("Swagger generator", "Swagger spec generator") codegen.RegisterFlags(app) _, err = app.Parse(os.Args[1:]) if err != nil { return nil, fmt.Errorf(`invalid command line: %s. Command line was "%s"`, err, strings.Join(os.Args, " ")) } s, err := New(api) if err != nil { return } b, err := json.Marshal(s) if err != nil { return } swaggerDir := filepath.Join(codegen.OutputDir, "swagger") os.RemoveAll(swaggerDir) if err = os.MkdirAll(swaggerDir, 0755); err != nil { return } genfiles = append(genfiles, swaggerDir) swaggerFile := filepath.Join(swaggerDir, "swagger.json") err = ioutil.WriteFile(swaggerFile, b, 0644) if err != nil { return } genfiles = append(genfiles, swaggerFile) controllerFile := filepath.Join(swaggerDir, "swagger.go") genfiles = append(genfiles, controllerFile) gg := codegen.NewGoGenerator(controllerFile) imports := []*codegen.ImportSpec{ codegen.SimpleImport("github.com/julienschmidt/httprouter"), codegen.SimpleImport("github.com/raphael/goa"), } gg.WriteHeader(fmt.Sprintf("%s Swagger Spec", api.Name), "swagger", imports) gg.Write([]byte(swagger)) if err = gg.FormatCode(); err != nil { return } return 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 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, "enumOptions": enumOptions, "defaultPath": defaultPath, } gopath := filepath.SplitList(os.Getenv("GOPATH"))[0] clientPkg, err := filepath.Rel(gopath, codegen.OutputDir) if err != nil { return } clientPkg = strings.TrimPrefix(filepath.ToSlash(clientPkg), "src/") 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() } }() if Host == "" { Host = api.Host } if Host == "" { return nil, fmt.Errorf("missing host value, specify it with --host") } if err = makeOutputDir(g); err != nil { return } funcs := template.FuncMap{ "title": strings.Title, "join": strings.Join, "toLower": strings.ToLower, "params": params, } // Generate client.js exampleAction, err := g.generateJS(filepath.Join(codegen.OutputDir, "client.js"), funcs, api) if err != nil { return } if exampleAction != nil { // Generate index.html if err = g.generateIndexHTML(filepath.Join(codegen.OutputDir, "index.html"), api, exampleAction, funcs); err != nil { return } // Generate axios.html if err = g.generateAxiosJS(); err != nil { return } // Generate example if err = g.generateExample(api); err != nil { return } } return g.genfiles, nil }
func main() { var ( files []string err error terminatedByUser bool ) // First check for the presence of `goimports`. _, err = exec.LookPath("goimports") if err != nil { fmt.Fprintln(os.Stderr, "Command goimports not found. Install with:\ngo get golang.org/x/tools/cmd/goimports") os.Exit(1) } // Now proceed with code generation cleanup := func() { for _, f := range files { os.RemoveAll(f) } } go utils.Catch(nil, func() { terminatedByUser = true }) files, err = command().Run() if terminatedByUser { cleanup() return } if err != nil { cleanup() fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } rels := make([]string, len(files)) cwd, err := os.Getwd() for i, f := range files { r, err := filepath.Rel(cwd, f) if err == nil { rels[i] = r } else { rels[i] = f } } fmt.Println(strings.Join(rels, "\n")) }
// Generate the application code, implement codegen.Generator. func (g *Generator) Generate(api *design.APIDefinition) (_ []string, err error) { if api == nil { return nil, fmt.Errorf("missing API definition, make sure design.Design is properly initialized") } go utils.Catch(nil, func() { g.Cleanup() }) defer func() { if err != nil { g.Cleanup() } }() outdir := AppOutputDir() err = api.IterateVersions(func(v *design.APIVersionDefinition) error { verdir := outdir if v.Version != "" { verdir = filepath.Join(verdir, codegen.VersionPackage(v.Version)) } if err := os.MkdirAll(verdir, 0755); err != nil { return err } if err := g.generateContexts(verdir, api, v); err != nil { return err } if err := g.generateControllers(verdir, v); err != nil { return err } if err := g.generateHrefs(verdir, v); err != nil { return err } if err := g.generateMediaTypes(verdir, v); err != nil { return err } if err := g.generateUserTypes(verdir, v); err != nil { return err } return nil }) if err != nil { return nil, err } 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() } }() os.RemoveAll(JSONSchemaDir()) os.MkdirAll(JSONSchemaDir(), 0755) g.genfiles = append(g.genfiles, JSONSchemaDir()) s := APISchema(api) js, err := s.JSON() if err != nil { return } schemaFile := filepath.Join(JSONSchemaDir(), "schema.json") if err = ioutil.WriteFile(schemaFile, js, 0644); err != nil { return } g.genfiles = append(g.genfiles, schemaFile) controllerFile := filepath.Join(JSONSchemaDir(), "schema.go") file, err := codegen.SourceFileFor(controllerFile) if err != nil { return } imports := []*codegen.ImportSpec{ codegen.SimpleImport("github.com/julienschmidt/httprouter"), codegen.SimpleImport("github.com/raphael/goa"), } g.genfiles = append(g.genfiles, controllerFile) file.WriteHeader(fmt.Sprintf("%s JSON Hyper-schema", api.Name), "schema", imports) file.Write([]byte(jsonSchemaCtrl)) if err = file.FormatCode(); 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, "goify": codegen.Goify, "okResp": okResp, "newControllerVersion": newControllerVersion, "versionPkg": codegen.VersionPackage, "targetPkg": func() string { return TargetPackage }, } gopath := filepath.SplitList(os.Getenv("GOPATH"))[0] if err != nil { var tmpl *template.Template tmpl, err = template.New("main").Funcs(funcs).Parse(mainTmpl) if err != nil { panic(err.Error()) // bug } gg := codegen.NewGoGenerator(mainFile) var outPkg string outPkg, err = filepath.Rel(gopath, codegen.OutputDir) if err != nil { return } outPkg = strings.TrimPrefix(filepath.ToSlash(outPkg), "src/") appPkg := path.Join(outPkg, "app") swaggerPkg := path.Join(outPkg, "swagger") imports := []*codegen.ImportSpec{ codegen.SimpleImport("github.com/raphael/goa"), codegen.SimpleImport(appPkg), codegen.SimpleImport(swaggerPkg), codegen.NewImport("log", "gopkg.in/inconshreveable/log15.v2"), } if generateSwagger() { jsonSchemaPkg := path.Join(outPkg, "schema") imports = append(imports, codegen.SimpleImport(jsonSchemaPkg)) } gg.WriteHeader("", "main", imports) data := map[string]interface{}{ "Name": AppName, "API": api, } if err = tmpl.Execute(gg, data); err != nil { return } if err = gg.FormatCode(); err != nil { return } } tmpl, err := template.New("ctrl").Funcs(funcs).Parse(ctrlTmpl) if err != nil { panic(err.Error()) // bug } imp, err := filepath.Rel(filepath.Join(gopath, "src"), codegen.OutputDir) if err != nil { return } imp = path.Join(filepath.ToSlash(imp), "app") imports := []*codegen.ImportSpec{codegen.SimpleImport(imp)} api.IterateVersions(func(v *design.APIVersionDefinition) error { if v.IsDefault() { return nil } imports = append(imports, codegen.SimpleImport(imp+"/"+codegen.Goify(v.Version, false))) 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 { resGen := codegen.NewGoGenerator(filename) resGen.WriteHeader("", "main", imports) err := tmpl.Execute(resGen, r) if err != nil { return err } if err := resGen.FormatCode(); err != nil { return err } } return nil }) if err != nil { return } return g.genfiles, nil }
// Generate the application code, implement codegen.Generator. func (g *Generator) Generate(api *design.APIDefinition) (_ []string, err error) { go utils.Catch(nil, func() { g.Cleanup() }) defer func() { if err != nil { g.Cleanup() } }() if api == nil { return nil, fmt.Errorf("missing API definition, make sure design.Design is properly initialized") } title := fmt.Sprintf("%s: Application Contexts", api.Name) imports := []*codegen.ImportSpec{ codegen.SimpleImport("fmt"), codegen.SimpleImport("strconv"), codegen.SimpleImport("github.com/raphael/goa"), } g.ContextsWriter.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" ctxData := ContextTemplateData{ Name: ctxName, ResourceName: r.Name, ActionName: a.Name, Payload: a.Payload, Params: a.AllParams(), Headers: r.Headers.Merge(a.Headers), Routes: a.Routes, Responses: MergeResponses(r.Responses, a.Responses), API: api, } return g.ContextsWriter.Execute(&ctxData) }) }) g.genfiles = append(g.genfiles, g.contextsFilename) if err != nil { return } if err = g.ContextsWriter.FormatCode(); err != nil { return } title = fmt.Sprintf("%s: Application Controllers", api.Name) imports = []*codegen.ImportSpec{ codegen.SimpleImport("github.com/julienschmidt/httprouter"), codegen.SimpleImport("github.com/raphael/goa"), } g.ControllersWriter.WriteHeader(title, TargetPackage, imports) var controllersData []*ControllerTemplateData api.IterateResources(func(r *design.ResourceDefinition) error { data := &ControllerTemplateData{Resource: codegen.Goify(r.Name, true)} err := r.IterateActions(func(a *design.ActionDefinition) error { context := fmt.Sprintf("%s%sContext", 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, } data.Actions = append(data.Actions, action) return nil }) if err != nil { return err } if len(data.Actions) > 0 { controllersData = append(controllersData, data) } return nil }) g.genfiles = append(g.genfiles, g.controllersFilename) if err = g.ControllersWriter.Execute(controllersData); err != nil { return } if err = g.ControllersWriter.FormatCode(); err != nil { return } title = fmt.Sprintf("%s: Application Resource Href Factories", api.Name) g.ResourcesWriter.WriteHeader(title, TargetPackage, nil) err = api.IterateResources(func(r *design.ResourceDefinition) error { m := api.MediaTypeWithIdentifier(r.MediaType) var identifier string if m != nil { identifier = m.Identifier } else { identifier = "plain/text" } canoTemplate := r.URITemplate() canoTemplate = design.WildcardRegex.ReplaceAllLiteralString(canoTemplate, "/%v") var canoParams []string if ca := r.CanonicalAction(); ca != nil { if len(ca.Routes) > 0 { canoParams = ca.Routes[0].Params() } } data := ResourceData{ Name: codegen.Goify(r.Name, true), Identifier: identifier, Description: r.Description, Type: m, CanonicalTemplate: canoTemplate, CanonicalParams: canoParams, } return g.ResourcesWriter.Execute(&data) }) g.genfiles = append(g.genfiles, g.resourcesFilename) if err != nil { return } if err = g.ResourcesWriter.FormatCode(); err != nil { return } title = fmt.Sprintf("%s: Application Media Types", api.Name) imports = []*codegen.ImportSpec{ codegen.SimpleImport("github.com/raphael/goa"), codegen.SimpleImport("fmt"), } g.MediaTypesWriter.WriteHeader(title, TargetPackage, imports) err = api.IterateMediaTypes(func(mt *design.MediaTypeDefinition) error { if mt.Type.IsObject() || mt.Type.IsArray() { return g.MediaTypesWriter.Execute(mt) } return nil }) g.genfiles = append(g.genfiles, g.mediaTypesFilename) if err != nil { return } if err = g.MediaTypesWriter.FormatCode(); err != nil { return } title = fmt.Sprintf("%s: Application User Types", api.Name) imports = []*codegen.ImportSpec{ codegen.SimpleImport("github.com/raphael/goa"), } g.UserTypesWriter.WriteHeader(title, TargetPackage, imports) err = api.IterateUserTypes(func(t *design.UserTypeDefinition) error { return g.UserTypesWriter.Execute(t) }) g.genfiles = append(g.genfiles, g.userTypesFilename) if err != nil { return } if err = g.UserTypesWriter.FormatCode(); 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/raphael/goa"), codegen.SimpleImport(appPkg), codegen.SimpleImport(swaggerPkg), codegen.NewImport("log", "gopkg.in/inconshreveable/log15.v2"), } 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(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 }