// NewUserTypesWriter returns a contexts code writer. // User types contain custom data structured defined in the DSL with "Type". func NewUserTypesWriter(filename string) (*UserTypesWriter, error) { file, err := codegen.SourceFileFor(filename) if err != nil { return nil, err } return &UserTypesWriter{SourceFile: file}, nil }
// NewControllersWriter returns a handlers code writer. // Handlers provide the glue between the underlying request data and the user controller. func NewControllersWriter(filename string) (*ControllersWriter, error) { file, err := codegen.SourceFileFor(filename) if err != nil { return nil, err } return &ControllersWriter{SourceFile: file}, nil }
func (g *Generator) generateJS(jsFile string, api *design.APIDefinition) (_ *design.ActionDefinition, err error) { file, err := codegen.SourceFileFor(jsFile) if err != nil { return } g.genfiles = append(g.genfiles, jsFile) if Scheme == "" && len(api.Schemes) > 0 { Scheme = api.Schemes[0] } data := map[string]interface{}{ "API": api, "Host": Host, "Scheme": Scheme, "Timeout": int64(Timeout / time.Millisecond), } if err = file.ExecuteTemplate("module", moduleT, nil, data); err != nil { return } actions := make(map[string][]*design.ActionDefinition) api.IterateResources(func(res *design.ResourceDefinition) error { return res.IterateActions(func(action *design.ActionDefinition) error { if as, ok := actions[action.Name]; ok { actions[action.Name] = append(as, action) } else { actions[action.Name] = []*design.ActionDefinition{action} } return nil }) }) var exampleAction *design.ActionDefinition keys := []string{} for n := range actions { keys = append(keys, n) } sort.Strings(keys) for _, n := range keys { for _, a := range actions[n] { if exampleAction == nil && a.Routes[0].Verb == "GET" { exampleAction = a } data := map[string]interface{}{ "Action": a, "Version": design.Design.APIVersionDefinition, } funcs := template.FuncMap{"params": params} if err = file.ExecuteTemplate("jsFuncs", jsFuncsT, funcs, data); err != nil { return } } } _, err = file.Write([]byte(moduleTend)) return exampleAction, err }
func (g *Generator) generateIndexHTML(htmlFile string, api *design.APIDefinition, exampleAction *design.ActionDefinition) error { file, err := codegen.SourceFileFor(htmlFile) if err != nil { return err } g.genfiles = append(g.genfiles, htmlFile) argNames := params(exampleAction) var args string if len(argNames) > 0 { query := exampleAction.QueryParams.Type.ToObject() argValues := make([]string, len(argNames)) for i, n := range argNames { q := query[n].Type.ToArray().ElemType // below works because we deal with simple types in query strings argValues[i] = fmt.Sprintf("%v", api.Example(q.Type)) } args = strings.Join(argValues, ", ") } examplePath := exampleAction.Routes[0].FullPath(design.Design.APIVersionDefinition) pathParams := exampleAction.Routes[0].Params(design.Design.APIVersionDefinition) if len(pathParams) > 0 { pathVars := exampleAction.AllParams().Type.ToObject() pathValues := make([]interface{}, len(pathParams)) for i, n := range pathParams { pathValues[i] = api.Example(pathVars[n].Type) } format := design.WildcardRegex.ReplaceAllLiteralString(examplePath, "/%v") examplePath = fmt.Sprintf(format, pathValues...) } if len(argNames) > 0 { args = ", " + args } exampleFunc := fmt.Sprintf( `%s%s ("%s"%s)`, exampleAction.Name, strings.Title(exampleAction.Parent.Name), examplePath, args, ) data := map[string]interface{}{ "API": api, "ExampleFunc": exampleFunc, } return file.ExecuteTemplate("exampleHTML", exampleT, nil, data) }
// 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 }
func (g *Generator) generateExample(api *design.APIDefinition) error { controllerFile := filepath.Join(codegen.OutputDir, "example.go") file, err := codegen.SourceFileFor(controllerFile) if err != nil { return err } imports := []*codegen.ImportSpec{ codegen.SimpleImport("net/http"), codegen.SimpleImport("github.com/julienschmidt/httprouter"), codegen.SimpleImport("github.com/raphael/goa"), } if err := file.WriteHeader(fmt.Sprintf("%s JavaScript Client Example", api.Name), "js", imports); err != nil { return err } g.genfiles = append(g.genfiles, controllerFile) data := map[string]interface{}{"ServeDir": codegen.OutputDir} if err := file.ExecuteTemplate("examples", exampleCtrlT, nil, data); err != nil { return err } return file.FormatCode() }
// 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) file, err := codegen.SourceFileFor(controllerFile) if err != nil { return } imports := []*codegen.ImportSpec{ codegen.SimpleImport("github.com/julienschmidt/httprouter"), codegen.SimpleImport("github.com/raphael/goa"), } file.WriteHeader(fmt.Sprintf("%s Swagger Spec", api.Name), "swagger", imports) file.Write([]byte(swagger)) if err = file.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() } }() 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 }