Beispiel #1
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
}
Beispiel #2
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
}
Beispiel #3
0
// generateUserTypes iterates through the user types and generates the data structures and
// marshaling code.
func (g *Generator) generateUserTypes(outdir string, api *design.APIDefinition) error {
	err := api.IterateVersions(func(version *design.APIVersionDefinition) error {
		if version.Version != "" {
			return nil
		}
		var modelname, filename string
		err := GormaDesign.IterateStores(func(store *RelationalStoreDefinition) error {
			err := store.IterateModels(func(model *RelationalModelDefinition) error {
				modelname = strings.ToLower(codegen.Goify(model.Name, false))

				filename = fmt.Sprintf("%s_gen.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", version.Context())
				ap, err := AppPackagePath()
				if err != nil {
					panic(err)
				}
				imports := []*codegen.ImportSpec{
					codegen.SimpleImport(ap),
					codegen.SimpleImport("github.com/jinzhu/gorm"),
					codegen.SimpleImport("golang.org/x/net/context"),
				}
				needDate := false
				for _, field := range model.RelationalFields {
					if field.Datatype == Timestamp || field.Datatype == NullableTimestamp {
						needDate = true
					}
				}
				if needDate {
					imp := codegen.SimpleImport("time")
					imports = append(imports, imp)
				}
				utWr.WriteHeader(title, "genmodels", imports)
				data := &UserTypeTemplateData{
					APIDefinition: api,
					UserType:      model,
					DefaultPkg:    TargetPackage,
					AppPkg:        AppPackage,
				}
				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
	})
	return err
}