Example #1
0
// 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()
		}
	}()

	s := APISchema(g.API)
	js, err := s.JSON()
	if err != nil {
		return
	}

	g.OutDir = filepath.Join(g.OutDir, "schema")
	os.RemoveAll(g.OutDir)
	os.MkdirAll(g.OutDir, 0755)
	g.genfiles = append(g.genfiles, g.OutDir)
	schemaFile := filepath.Join(g.OutDir, "schema.json")
	if err = ioutil.WriteFile(schemaFile, js, 0644); err != nil {
		return
	}
	g.genfiles = append(g.genfiles, schemaFile)

	return g.genfiles, nil
}
Example #2
0
// 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.Timeout == 0 {
		g.Timeout = 20 * time.Second
	}
	if g.Scheme == "" && len(g.API.Schemes) > 0 {
		g.Scheme = g.API.Schemes[0]
	}
	if g.Scheme == "" {
		g.Scheme = "http"
	}
	if g.Host == "" {
		g.Host = g.API.Host
	}
	if g.Host == "" {
		return nil, fmt.Errorf("missing host value, set it with --host")
	}

	g.OutDir = filepath.Join(g.OutDir, "js")
	if err := os.RemoveAll(g.OutDir); err != nil {
		return nil, err
	}
	if err := os.MkdirAll(g.OutDir, 0755); err != nil {
		return nil, err
	}
	g.genfiles = append(g.genfiles, g.OutDir)

	// Generate client.js
	exampleAction, err := g.generateJS(filepath.Join(g.OutDir, "client.js"))
	if err != nil {
		return
	}

	// Generate axios.html
	if err = g.generateAxiosJS(); err != nil {
		return
	}

	if exampleAction != nil && !g.NoExample {
		// Generate index.html
		if err = g.generateIndexHTML(filepath.Join(g.OutDir, "index.html"), exampleAction); err != nil {
			return
		}

		// Generate example
		if err = g.generateExample(); err != nil {
			return
		}
	}

	return g.genfiles, nil
}
Example #3
0
File: main.go Project: RouGang/goa
func main() {
	var (
		files            []string
		err              error
		terminatedByUser bool
	)

	// Now proceed with code generation
	cleanup := func() {
		for _, f := range files {
			os.RemoveAll(f)
		}
	}

	go utils.Catch(nil, func() {
		terminatedByUser = true
	})

	for _, command := range Commands {
		run := command.Run
		sub := &cobra.Command{
			Use:   command.Name(),
			Short: command.Description(),
			Run: func(cmd *cobra.Command, args []string) {
				codegen.ExtraFlags = args
				files, err = run()
			},
		}
		command.RegisterFlags(sub)
		codegen.RegisterFlags(sub)
		RootCmd.AddCommand(sub)
	}
	codegen.RegisterFlags(RootCmd)
	RootCmd.Execute()

	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"))
}
Example #4
0
// 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
}
Example #5
0
// Generate produces the skeleton main.
func (g *Generator) 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()
		}
	}()

	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/goadesign/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
}
Example #6
0
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"))
}
Example #7
0
// 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()
		}
	}()

	s, err := New(g.API)
	if err != nil {
		return nil, err
	}

	swaggerDir := filepath.Join(g.OutDir, "swagger")
	os.RemoveAll(swaggerDir)
	if err = os.MkdirAll(swaggerDir, 0755); err != nil {
		return nil, err
	}
	g.genfiles = append(g.genfiles, swaggerDir)

	// JSON
	rawJSON, err := json.Marshal(s)
	if err != nil {
		return nil, err
	}
	swaggerFile := filepath.Join(swaggerDir, "swagger.json")
	if err := ioutil.WriteFile(swaggerFile, rawJSON, 0644); err != nil {
		return nil, err
	}
	g.genfiles = append(g.genfiles, swaggerFile)

	// YAML
	var yamlSource interface{}
	if err = json.Unmarshal(rawJSON, &yamlSource); err != nil {
		return nil, err
	}

	rawYAML, err := yaml.Marshal(yamlSource)
	if err != nil {
		return nil, err
	}
	swaggerFile = filepath.Join(swaggerDir, "swagger.yaml")
	if err := ioutil.WriteFile(swaggerFile, rawYAML, 0644); err != nil {
		return nil, err
	}
	g.genfiles = append(g.genfiles, swaggerFile)

	return g.genfiles, nil
}
Example #8
0
// Generate the application code, implement codegen.Generator.
func (g *Generator) Generate() (_ []string, err error) {
	if g.API == nil {
		return nil, fmt.Errorf("missing API definition, make sure design is properly initialized")
	}

	go utils.Catch(nil, func() { g.Cleanup() })

	defer func() {
		if err != nil {
			g.Cleanup()
		}
	}()

	codegen.Reserved[g.Target] = true

	os.RemoveAll(g.OutDir)

	if err := os.MkdirAll(g.OutDir, 0755); err != nil {
		return nil, err
	}
	g.genfiles = []string{g.OutDir}
	if err := g.generateContexts(); err != nil {
		return nil, err
	}
	if err := g.generateControllers(); err != nil {
		return nil, err
	}
	if err := g.generateSecurity(); err != nil {
		return nil, err
	}
	if err := g.generateHrefs(); err != nil {
		return nil, err
	}
	if err := g.generateMediaTypes(); err != nil {
		return nil, err
	}
	if err := g.generateUserTypes(); err != nil {
		return nil, err
	}
	if !g.NoTest {
		if err := g.generateResourceTest(); err != nil {
			return nil, err
		}
	}

	return g.genfiles, nil
}
Example #9
0
// 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
}
Example #10
0
// 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
	}

	// Generate client.js
	exampleAction, err := g.generateJS(filepath.Join(codegen.OutputDir, "client.js"), api)
	if err != nil {
		return
	}

	if exampleAction != nil {
		// Generate index.html
		if err = g.generateIndexHTML(filepath.Join(codegen.OutputDir, "index.html"), api, exampleAction); 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
}
Example #11
0
// 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 is properly initialized")
	}

	go utils.Catch(nil, func() { g.Cleanup() })

	defer func() {
		if err != nil {
			g.Cleanup()
		}
	}()

	os.RemoveAll(AppOutputDir())

	if err := os.MkdirAll(AppOutputDir(), 0755); err != nil {
		return nil, err
	}
	if err := g.generateContexts(api); err != nil {
		return nil, err
	}
	if err := g.generateControllers(api); err != nil {
		return nil, err
	}
	if err := g.generateSecurity(api); err != nil {
		return nil, err
	}
	if err := g.generateHrefs(api); err != nil {
		return nil, err
	}
	if err := g.generateMediaTypes(api); err != nil {
		return nil, err
	}
	if err := g.generateUserTypes(api); err != nil {
		return nil, err
	}
	if !NoGenTest {
		if err := g.generateResourceTest(api); err != nil {
			return nil, err
		}
	}

	return g.genfiles, nil
}
Example #12
0
// 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/goadesign/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
}
Example #13
0
// 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 := ModelOutputDir()
	if err := os.MkdirAll(outdir, 0755); err != nil {
		return nil, err
	}

	if err := g.generateUserTypes(outdir, api); err != nil {
		return g.genfiles, err
	}

	return g.genfiles, nil
}
Example #14
0
// Generate produces the skeleton main.
func (g *Generator) 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()
		}
	}()

	swaggerDir := filepath.Join(codegen.OutputDir, "swagger")
	os.RemoveAll(swaggerDir)
	if err = os.MkdirAll(swaggerDir, 0755); err != nil {
		return nil, err
	}
	genfiles = append(genfiles, swaggerDir)
	s, err := New(api)
	if err != nil {
		return nil, err
	}

	// JSON
	rawJSON, err := json.Marshal(s)
	if err != nil {
		return nil, err
	}
	swaggerFile := filepath.Join(swaggerDir, "swagger.json")
	if err := ioutil.WriteFile(swaggerFile, rawJSON, 0644); err != nil {
		return nil, err
	}
	genfiles = append(genfiles, swaggerFile)

	// YAML
	var yamlSource interface{}
	if err = json.Unmarshal(rawJSON, &yamlSource); err != nil {
		return nil, err
	}

	rawYAML, err := yaml.Marshal(yamlSource)
	if err != nil {
		return nil, err
	}
	swaggerFile = filepath.Join(swaggerDir, "swagger.yaml")
	if err := ioutil.WriteFile(swaggerFile, rawYAML, 0644); err != nil {
		return nil, err
	}
	genfiles = append(genfiles, swaggerFile)

	// Go endpoint
	controllerFile := filepath.Join(swaggerDir, "swagger.go")
	genfiles = append(genfiles, controllerFile)
	file, err := codegen.SourceFileFor(controllerFile)
	if err != nil {
		return nil, err
	}
	imports := []*codegen.ImportSpec{
		codegen.SimpleImport("github.com/goadesign/goa"),
	}
	file.WriteHeader(fmt.Sprintf("%s Swagger Spec", api.Name), "swagger", imports)
	err = file.ExecuteTemplate("swagger", swaggerT, nil, api)
	if err != nil {
		return nil, err
	}
	if err = file.FormatCode(); err != nil {
		return nil, err
	}

	return genfiles, nil
}
Example #15
0
File: main.go Project: ajoulie/goa
func main() {
	var (
		files            []string
		err              error
		terminatedByUser bool

		// RootCmd is the base command used when goagen is called with no argument.
		RootCmd = &cobra.Command{
			Use:   "goagen",
			Short: "goa code generation tool",
			Long: `The goagen tool generates various artifacts from a goa service design package.

Each command supported by the tool produces a specific type of artifacts. For example
the "app" command generates the code that supports the service controllers.

The "bootstrap" command runs the "app", "main", "client" and "swagger" commands generating the
controllers supporting code and main skeleton code (if not already present) as well as a client
package and tool and the Swagger specification for the API.
`}
	)

	// Now proceed with code generation
	cleanup := func() {
		for _, f := range files {
			os.RemoveAll(f)
		}
	}

	go utils.Catch(nil, func() {
		terminatedByUser = true
	})

	for _, command := range Commands {
		run := command.Run
		sub := &cobra.Command{
			Use:   command.Name(),
			Short: command.Description(),
			Run: func(cmd *cobra.Command, args []string) {
				codegen.ExtraFlags = args
				files, err = run()
			},
		}
		command.RegisterFlags(sub)
		codegen.RegisterFlags(sub)
		RootCmd.AddCommand(sub)
	}
	codegen.RegisterFlags(RootCmd)
	RootCmd.Execute()

	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"))
}
Example #16
0
// 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
}
Example #17
0
// 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/goadesign/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
}
Example #18
0
func main() {
	var (
		files            []string
		err              error
		terminatedByUser bool
	)

	// rootCmd is the base command used when goagen is called with no argument.
	rootCmd := &cobra.Command{
		Use:   "goagen",
		Short: "goa code generation tool",
		Long: `The goagen tool generates artifacts from a goa service design package.

Each command supported by the tool produces a specific type of artifacts. For example
the "app" command generates the code that supports the service controllers.

The "bootstrap" command runs the "app", "main", "client" and "swagger" commands generating the
controllers supporting code and main skeleton code (if not already present) as well as a client
package and tool and the Swagger specification for the API.
`}
	var (
		designPkg string
		debug     bool
	)

	rootCmd.PersistentFlags().StringP("out", "o", ".", "output directory")
	rootCmd.PersistentFlags().StringVarP(&designPkg, "design", "d", "", "design package import path")
	rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "enable debug mode, does not cleanup temporary files.")

	// versionCmd implements the "version" command
	versionCmd := &cobra.Command{
		Use:   "version",
		Short: "Print the version number of goagen",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println("goagen " + version.String() + "\nThe goa generation tool.")
		},
	}
	rootCmd.AddCommand(versionCmd)

	// appCmd implements the "app" command.
	var (
		pkg    string
		notest bool
	)
	appCmd := &cobra.Command{
		Use:   "app",
		Short: "Generate application code",
		Run:   func(c *cobra.Command, _ []string) { files, err = run("genapp", c) },
	}
	appCmd.Flags().StringVar(&pkg, "pkg", "app", "Name of generated Go package containing controllers supporting code (contexts, media types, user types etc.)")
	appCmd.Flags().BoolVar(&notest, "notest", false, "Prevent generation of test helpers")
	rootCmd.AddCommand(appCmd)

	// mainCmd implements the "main" command.
	var (
		force bool
	)
	mainCmd := &cobra.Command{
		Use:   "main",
		Short: "Generate application scaffolding",
		Run:   func(c *cobra.Command, _ []string) { files, err = run("genmain", c) },
	}
	mainCmd.Flags().BoolVar(&force, "force", false, "overwrite existing files")
	rootCmd.AddCommand(mainCmd)

	// clientCmd implements the "client" command.
	var (
		toolDir, tool string
		notool        bool
	)
	clientCmd := &cobra.Command{
		Use:   "client",
		Short: "Generate client package and tool",
		Run:   func(c *cobra.Command, _ []string) { files, err = run("genclient", c) },
	}
	clientCmd.Flags().StringVar(&pkg, "pkg", "client", "Name of generated client Go package")
	clientCmd.Flags().StringVar(&toolDir, "tooldir", "tool", "Name of generated tool directory")
	clientCmd.Flags().StringVar(&tool, "tool", "[API-name]-cli", "Name of generated tool")
	clientCmd.Flags().BoolVar(&notool, "notool", false, "Prevent generation of cli tool")
	rootCmd.AddCommand(clientCmd)

	// swaggerCmd implements the "swagger" command.
	swaggerCmd := &cobra.Command{
		Use:   "swagger",
		Short: "Generate Swagger",
		Run:   func(c *cobra.Command, _ []string) { files, err = run("genswagger", c) },
	}
	rootCmd.AddCommand(swaggerCmd)

	// jsCmd implements the "js" command.
	var (
		timeout      = time.Duration(20) * time.Second
		scheme, host string
		noexample    bool
	)
	jsCmd := &cobra.Command{
		Use:   "js",
		Short: "Generate JavaScript client",
		Run:   func(c *cobra.Command, _ []string) { files, err = run("genjs", c) },
	}
	jsCmd.Flags().DurationVar(&timeout, "timeout", timeout, `the duration before the request times out.`)
	jsCmd.Flags().StringVar(&scheme, "scheme", "", `the URL scheme used to make requests to the API, defaults to the scheme defined in the API design if any.`)
	jsCmd.Flags().StringVar(&host, "host", "", `the API hostname, defaults to the hostname defined in the API design if any`)
	jsCmd.Flags().BoolVar(&noexample, "noexample", false, `Skip generation of example HTML and controller`)
	rootCmd.AddCommand(jsCmd)

	// schemaCmd implements the "schema" command.
	schemaCmd := &cobra.Command{
		Use:   "schema",
		Short: "Generate JSON Schema",
		Run:   func(c *cobra.Command, _ []string) { files, err = run("genschema", c) },
	}
	rootCmd.AddCommand(schemaCmd)

	// genCmd implements the "gen" command.
	var (
		pkgPath string
	)
	genCmd := &cobra.Command{
		Use:   "gen",
		Short: "Run third-party generator",
		Run:   func(c *cobra.Command, _ []string) { files, err = runGen(c) },
	}
	genCmd.Flags().StringVar(&pkgPath, "pkg-path", "", "Package import path of generator. The package must implement the Generate global function.")
	rootCmd.AddCommand(genCmd)

	// boostrapCmd implements the "bootstrap" command.
	bootCmd := &cobra.Command{
		Use:   "bootstrap",
		Short: `Equivalent to running the "app", "main", "client" and "swagger" commands.`,
		Run: func(c *cobra.Command, a []string) {
			appCmd.Run(c, a)
			if err != nil {
				return
			}
			prev := files

			mainCmd.Run(c, a)
			if err != nil {
				return
			}
			prev = append(prev, files...)

			clientCmd.Run(c, a)
			if err != nil {
				return
			}
			prev = append(prev, files...)

			swaggerCmd.Run(c, a)
			files = append(prev, files...)
		},
	}
	bootCmd.Flags().AddFlagSet(appCmd.Flags())
	bootCmd.Flags().AddFlagSet(mainCmd.Flags())
	bootCmd.Flags().AddFlagSet(clientCmd.Flags())
	bootCmd.Flags().AddFlagSet(swaggerCmd.Flags())
	rootCmd.AddCommand(bootCmd)

	// cmdsCmd implements the commands command
	// It lists all the commands and flags in JSON to enable shell integrations.
	cmdsCmd := &cobra.Command{
		Use:   "commands",
		Short: "Lists all commands and flags in JSON",
		Run:   func(c *cobra.Command, _ []string) { runCommands(rootCmd) },
	}
	rootCmd.AddCommand(cmdsCmd)

	// Now proceed with code generation
	cleanup := func() {
		for _, f := range files {
			os.RemoveAll(f)
		}
	}

	go utils.Catch(nil, func() {
		terminatedByUser = true
	})

	rootCmd.Execute()

	if terminatedByUser {
		cleanup()
		return
	}

	if err != nil {
		cleanup()
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}

	rels := make([]string, len(files))
	cd, _ := os.Getwd()
	for i, f := range files {
		r, err := filepath.Rel(cd, f)
		if err == nil {
			rels[i] = r
		} else {
			rels[i] = f
		}
	}
	fmt.Println(strings.Join(rels, "\n"))
}
Example #19
0
// 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
}
Example #20
0
// 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
}
Example #21
0
// 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
}