Skip to content

Commit

Permalink
Merge pull request #34 from edwinvautier/feat_make-entity
Browse files Browse the repository at this point in the history
Make entity command
  • Loading branch information
Edwin Vautier authored Apr 9, 2021
2 parents 41a04dc + 8caf0cd commit 9459fd6
Show file tree
Hide file tree
Showing 38 changed files with 466 additions and 9 deletions.
15 changes: 15 additions & 0 deletions cmd/create.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
package cmd
/*
Copyright © 2021 Edwin Vautier <edwin.vautier@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import (
"os"
Expand Down
2 changes: 1 addition & 1 deletion cmd/install.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package cmd
/*
Copyright © 2021 NAME HERE <EMAIL ADDRESS>
Copyright © 2021 Edwin Vautier <edwin.vautier@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
46 changes: 46 additions & 0 deletions cmd/make.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package cmd

/*
Copyright © 2021 Edwin Vautier <edwin.vautier@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import (
"github.com/edwinvautier/go-cli/services/makeCommand"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

// makeCmd represents the install command
var makeCmd = &cobra.Command{
Use: "make",
Short: "make is used to create new files, for example for models",
Long: `make is used to create new files, for example for models, it creates your model file after prompting you for fields`,
Run: func(cmd *cobra.Command, args []string) {
if !isAMakeCommand(args[0]) {
log.Fatal(args[0], " is not a make command!")
}
if err := makeCommand.MakeEntity(args[1]); err != nil {
log.Fatal(err)
}
},
}

func init() {
rootCmd.AddCommand(makeCmd)
}

func isAMakeCommand(commandName string) bool {
return commandName == "entity"
}
2 changes: 1 addition & 1 deletion config/create_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func InitCreateCmdConfig(config *CreateCmdConfig) {
config.DBMS = getDBMS()
config.UseDocker = chooseToUseDocker()
config.GoPackageFullPath = "github.com/" + strings.TrimSuffix(config.GitUserName, "\n") + "/" + config.AppName
config.Box = packr.New("My Box", "../templates")
config.Box = packr.New("My Box", "../templates/newProject")
config.AuthModule = viper.GetBool("auth-module")
}

Expand Down
62 changes: 62 additions & 0 deletions config/make_command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package config

import (
"os"

"github.com/edwinvautier/go-cli/prompt/entity"
"github.com/edwinvautier/go-cli/helpers"
"github.com/gobuffalo/packr/v2"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
)

// InitMakeCmdConfig creates the needed config for the create command by prompting user and doing other actions
func InitMakeCmdConfig(config *MakeCmdConfig) error {
workdir, err := os.Getwd()
if err != nil {
return err
}

viper.AddConfigPath(workdir)
viper.SetConfigName(".go-cli-config")
if err := viper.ReadInConfig(); err != nil {
return err
}

config.GoPackageFullPath = viper.GetString("package")
config.Box = packr.New("makeEntityBox", "../templates/makeEntity")
config.Entity.NameLowerCase = helpers.LowerCase(config.Entity.Name)
config.Entity.NamePascalCase = helpers.PascalCase(config.Entity.Name)
return entity.PromptUserForEntityFields(&config.Entity)
}

// AddModelToConfig set the new bundle to true in config after install
func AddModelToConfig(newEntity entity.NewEntity) error {
workdir, err := os.Getwd()
if err != nil {
return err
}

viper.AddConfigPath(workdir)
viper.SetConfigName(".go-cli-config")
viper.SetDefault("models", map[string]map[string]string{})
// If a config file is found, read it in.
if err := viper.ReadInConfig(); err != nil {
return err
}

models := viper.GetStringMap("models")
models[newEntity.Name] = newEntity
viper.Set("models", models)
log.Info("Using config file : ", viper.ConfigFileUsed())
viper.WriteConfig()

return nil
}

// MakeCmdConfig is the struct used to configure make command
type MakeCmdConfig struct {
GoPackageFullPath string
Box *packr.Box
Entity entity.NewEntity
}
32 changes: 27 additions & 5 deletions helpers/strings.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package helpers

import (
"strings"
"unicode"
)

// JoinString takes a pointer to a string and modify this string in order to remove spaces
Expand All @@ -11,16 +12,20 @@ func JoinString(str string) string {
}

// GetFilePartsFromName tries to get path and name from the file name, also try to find desired extension
func GetFilePartsFromName(name string) FileParts {
func GetFilePartsFromName(name string, outputName string) FileParts {
var fileParts FileParts

slices := strings.Split(name, "/")
fileParts.Name = slices[len(slices)-1]
fileParts.Path = strings.Join(slices[:len(slices)-1], "/") + "/"

fileParts.Name = slices[len(slices)-1]
slices = strings.Split(fileParts.Name, ".")
fileParts.OutputName = strings.Join(slices[:len(slices)-1], ".")


if outputName == "" {
fileParts.OutputName = strings.Join(slices[:len(slices)-1], ".")
} else {
fileParts.OutputName = outputName
}

return fileParts
}

Expand All @@ -30,3 +35,20 @@ type FileParts struct {
Path string
OutputName string
}

// UpperCaseFirstChar returns the input string with first letter capitalized
func UpperCaseFirstChar(word string) string {
a := []rune(word)
a[0] = unicode.ToUpper(a[0])
return string(a)
}

// LowerCase returns input string lowercased
func LowerCase(name string) string {
return strings.ToLower(name)
}

// PascalCase returns the string with uppercased first char
func PascalCase(name string) string {
return UpperCaseFirstChar(name)
}
135 changes: 135 additions & 0 deletions prompt/entity/entity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package entity

import (
"io/ioutil"
"os"
"strings"

"github.com/AlecAivazis/survey/v2"
"github.com/edwinvautier/go-cli/helpers"
log "github.com/sirupsen/logrus"
)


// EntityField represents a single field from an entity
type EntityField struct {
Type string
Name string
IsSlice bool
SliceType string
}

// NewEntity represents the full entity that user wants to create
type NewEntity struct {
Name string
NamePascalCase string
NameLowerCase string
HasDate bool
HasCustomTypes bool
Fields []EntityField
}

// PromptUserForEntityFields prompts user in the CLI to choose entity fields wanted
func PromptUserForEntityFields(entity *NewEntity) error{
for {
fieldName := ""
if err := promptForFieldName(&fieldName); err != nil {
return err
}

// If field name is empty then stop the function
if fieldName == "" {
break
}

var fieldType string
if err := promptForFieldType(&fieldType); err != nil {
return err
}

field := EntityField{
Name: helpers.UpperCaseFirstChar(fieldName),
Type: fieldType,
IsSlice: false,
}

if field.Type == "date" {
entity.HasDate = true
} else if field.Type == "slice" {
field.IsSlice = true

sliceTypePrompt := &survey.Select{
Message: "Slice type :",
Options: GetTypeOptions(),
}
survey.AskOne(sliceTypePrompt, &field.SliceType)

if choosedCustomType(field.SliceType) {
entity.HasCustomTypes = true
}
}

if choosedCustomType(field.Type) {
entity.HasCustomTypes = true
}

entity.Fields = append(entity.Fields, field)
}

return nil
}

// promptForFieldName asks the user for a string used as the app name
func promptForFieldName(fieldName *string) error {
prompt := &survey.Input{
Message: "Choose new field name (Press enter to stop adding fields)",
}
return survey.AskOne(prompt, fieldName)
}

func promptForFieldType(fieldType *string) error {
typePrompt := &survey.Select{
Message: "Choose type :",
Options: GetTypeOptions(),
}
return survey.AskOne(typePrompt, fieldType)
}

// GetTypeOptions returns a list of strings for user prompt of data types when creating new models
func GetTypeOptions() []string {
entitiesList := GetEntitiesList()
options := []string{"string", "boolean", "int", "uint", "float32", "float64", "date", "slice"}
options = append(options, entitiesList...)

return options
}

// GetEntitiesList returns a slice of strings with all the entities names found in the models/ dir
func GetEntitiesList() []string {
workdir, err := os.Getwd()
if err != nil {
log.Error(err)
}
files, err := ioutil.ReadDir(workdir + "/api/models")
if err != nil {
log.Fatal(err)
}
entities := make([]string, 0)
for _, file := range files {
name := helpers.UpperCaseFirstChar(strings.Split(file.Name(), ".go")[0])
entities = append(entities, name)
}

return entities
}

func choosedCustomType(cType string) bool{
entitiesList := GetEntitiesList()
for _, entityName := range entitiesList {
if entityName == cType {
return true
}
}

return false
}
2 changes: 1 addition & 1 deletion services/createCommand/generate_structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func generateTemplates(config config.CreateCmdConfig) error {

config.Box.Walk(func(path string, f packd.File) error {
fInfo, _ := f.FileInfo()
fileParts := helpers.GetFilePartsFromName(fInfo.Name())
fileParts := helpers.GetFilePartsFromName(fInfo.Name(), "")
GenerateFile(fileParts.Path, fileParts.Name, fileParts.OutputName, config)
return nil
})
Expand Down
2 changes: 1 addition & 1 deletion services/installCommand/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func executeTemplates(name string, installCmdConfig config.InstallCmdConfig) err

box.Walk(func(path string, f packd.File) error {
fInfo, _ := f.FileInfo()
fileParts := helpers.GetFilePartsFromName(fInfo.Name())
fileParts := helpers.GetFilePartsFromName(fInfo.Name(), "")
generateFile(fileParts.Path, fileParts.Name, fileParts.OutputName, installCmdConfig, box)
return nil
})
Expand Down
18 changes: 18 additions & 0 deletions services/makeCommand/make.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package makeCommand

import "github.com/edwinvautier/go-cli/config"

// MakeEntity creates the config and execute templates in order to create a new entity
func MakeEntity(entityName string) error {
var makeCmdConfig config.MakeCmdConfig
makeCmdConfig.Entity.Name = entityName
if err := config.InitMakeCmdConfig(&makeCmdConfig); err != nil {
return err
}

if err := executeTemplates(makeCmdConfig); err != nil {
return err
}

return config.AddModelToConfig(makeCmdConfig.Entity)
}
Loading

0 comments on commit 9459fd6

Please sign in to comment.