Skip to content

Commit

Permalink
Auto-download modules and first build
Browse files Browse the repository at this point in the history
  • Loading branch information
adampresley committed Jun 3, 2021
1 parent 140f18f commit 6ab9764
Show file tree
Hide file tree
Showing 19 changed files with 157 additions and 69 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

All notable changes will be docmented here.

## 1.2.0

* Fixed VueJS linter errors
* Using DbName in all places instead of AppName
* Better help messages when answering questions
* Go moduels, Node modules are automatically installed for you
* The Vue app is built for you for the first time. This reduces errors when just trying to do a first run

## 1.1.0

* Add ability to generate Go model files from database tables
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ endif
# Build tasks
#

run: ## Run the app
go run .

build-windows: ## Create a compiled Windows binary
GOOS=windows GOARCH=amd64 ${GC}.exe

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.0
1.2.0
188 changes: 139 additions & 49 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import (
"io"
"io/fs"
"os"
"os/exec"
"strings"
"text/template"
"time"

"github.com/AlecAivazis/survey/v2"
"github.com/AlecAivazis/survey/v2/terminal"
"github.com/app-nerds/postgresr"
"github.com/iancoleman/strcase"
"github.com/jackc/pgx/v4"
Expand Down Expand Up @@ -52,14 +54,6 @@ type appValues struct {
GithubToken string
}

type dbValues struct {
DbHost string
DbUser string
DbPassword string
DbName string
WantModel bool
}

type tableStruct struct {
Name string
Columns []tableColumn
Expand Down Expand Up @@ -100,48 +94,61 @@ func main() {
WantDatabase: false,
}

fmt.Printf("Welcome to App Nerds Web Application Generator (%s)\n\n", Version)
fmt.Printf("\n🙏 Welcome to App Nerds Web Application Generator (%s)\n\n", Version)
fmt.Printf("Please note that you'll need the following tools to develop in this application:\n")
fmt.Printf(" Go - https://golang.org\n")
fmt.Printf(" Swag - https://github.com/swaggo/swag\n")
fmt.Printf(" NodeJS - https://nodejs.org\n")
fmt.Printf(" Vue CLI - https://cli.vuejs.org\n")
fmt.Printf("\n")

firstQuestions := []*survey.Question{
{
Name: "GithubPath",
Prompt: &survey.Input{Message: "Enter the Github path for this application's home repo"},
Name: "GithubPath",
Prompt: &survey.Input{
Message: "Enter the Github path for this application's home repo",
Help: "This should be the path to a Github repository. eg. github.com/app-nerds/my-new-app",
},
Validate: survey.Required,
},
{
Name: "CompanyName",
Prompt: &survey.Input{Message: "Company name"},
Prompt: &survey.Input{Message: "Company name", Default: "App Nerds"},
},
{
Name: "Title",
Prompt: &survey.Input{Message: "Title", Help: "Used in browser and README"},
Name: "Title",
Prompt: &survey.Input{
Message: "Title",
Help: "This value is used in the browser title and README",
},
},
{
Name: "AppName",
Prompt: &survey.Input{Message: "Application name", Help: "No spaces"},
Validate: func(val interface{}) error {
value := val.(string)

if hasSpace(value) {
return errors.New("Application name cannot contain spaces!")
}

return nil
Name: "AppName",
Prompt: &survey.Input{
Message: "Application name",
Help: "This is used primary as the final executable name. There should be no spaces in this name. Spaces will be replaced with hyphens",
},
Transform: survey.TransformString(func(s string) string {
lower := strings.ToLower(s)
nospaces := strings.ReplaceAll(lower, " ", "-")
notabs := strings.ReplaceAll(nospaces, "\t", "-")

return notabs
}),
},
{
Name: "EnvPrefix",
Prompt: &survey.Input{Message: "Environment variable prefix", Help: "No spaces"},
Transform: survey.TransformString(strings.ToUpper),
Validate: func(val interface{}) error {
value := val.(string)

if hasSpace(value) {
return errors.New("Environment prefix cannot have spaces!")
}

return nil
Name: "EnvPrefix",
Prompt: &survey.Input{
Message: "Environment variable prefix",
Help: "This prefix will be applied to configuration values pulled from the environment. eg. PREFIX_SERVER_HOST. No spaces allowed.",
},
Transform: survey.TransformString(func(s string) string {
upper := strings.ToUpper(s)
nospaces := strings.ReplaceAll(upper, " ", "")
notabs := strings.ReplaceAll(nospaces, "\t", "")

return notabs
}),
},
{
Name: "Description",
Expand All @@ -152,16 +159,24 @@ func main() {
Prompt: &survey.Input{Message: "Enter your email address"},
},
{
Name: "GithubToken",
Prompt: &survey.Input{Message: "Enter your Github Personal Access Token", Help: "This is used for accessing private repos in Docker builds"},
Name: "GithubToken",
Prompt: &survey.Input{
Message: "Enter your Github Personal Access Token",
Help: "This is used for accessing private repos in Docker builds. See https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token",
},
},
{
Name: "WantDatabase",
Prompt: &survey.Confirm{Message: "Would you like to use a database?"},
Prompt: &survey.Confirm{Message: "Would you like to use a database?", Default: false},
},
}

if err = survey.Ask(firstQuestions, &values); err != nil {
if err == terminal.InterruptErr {
fmt.Printf("\nCancelling.\n")
os.Exit(-1)
}

logrus.WithError(err).Fatalf("There was an error!")
}

Expand Down Expand Up @@ -194,6 +209,11 @@ func main() {
}

if err = survey.Ask(dbQuestions, &values); err != nil {
if err == terminal.InterruptErr {
fmt.Printf("\nCancelling.\n")
os.Exit(-1)
}

logrus.WithError(err).Fatalf("There was an error!")
}

Expand All @@ -208,7 +228,14 @@ func main() {
Options: tableNames,
}

survey.AskOne(whichTablesPrompt, &selectedTables)
if err = survey.AskOne(whichTablesPrompt, &selectedTables); err != nil {
if err == terminal.InterruptErr {
fmt.Printf("\nCancelling.\n")
os.Exit(-1)
}

logrus.WithError(err).Fatalf("There was an error!")
}

if tables, err = getColumnsForTables(values, selectedTables); err != nil {
logrus.WithError(err).Fatalf("Error getting column information!")
Expand Down Expand Up @@ -269,6 +296,10 @@ func main() {
"templates/app/app-nerds-logo.jpg": "app/src/assets/images/app-nerds-logo.jpg",
}

fmt.Printf("\nCreating your new application!\n")
fmt.Printf(" This might take a couple of minutes... ☕️\n")
fmt.Printf("\n")

/*
* Create directories
*/
Expand Down Expand Up @@ -390,17 +421,22 @@ func main() {
}
}

/*
* Do the steps the initialze the new app
*/
if err = modDownload(); err != nil {
logrus.WithError(err).Fatalf("Error downloading Go modules")
}

if err = npmInstall(); err != nil {
logrus.WithError(err).Fatalf("Error installing Node modules")
}

if err = buildNode(); err != nil {
logrus.WithError(err).Fatalf("Error building NodeJS app")
}

fmt.Printf("\n🎉 Congratulations! Your new application is ready.\n")
fmt.Printf("Please note that you'll need the following tools to develop in this application:\n")
fmt.Printf(" Go - https://golang.org\n")
fmt.Printf(" Swag - https://github.com/swaggo/swag\n")
fmt.Printf(" NodeJS - https://nodejs.org\n")
fmt.Printf(" Vue CLI - https://cli.vuejs.org\n")
fmt.Printf("\nTo begin execute the following:\n\n")
fmt.Printf(" cd %s/app\n", values.AppName)
fmt.Printf(" npm install && npm run build\n")
fmt.Printf(" cd ..\n")
fmt.Printf(" go get\n")

if values.WantDatabase {
fmt.Printf("\n👩‍💻 Since you opted to have a database setup, in a new terminal window run: \n")
Expand Down Expand Up @@ -608,3 +644,57 @@ type {{.Name}} struct {
func hasSpace(value string) bool {
return strings.ContainsAny(value, " \t")
}

func modDownload() error {
cmd := exec.Command("go", "mod", "download")
fmt.Printf("Downloading Go modules...\n")

err := cmd.Run()
return err
}

func npmInstall() error {
var (
err error
)

if err = os.Chdir("app"); err != nil {
return errors.New("error changing to app directory in npmInstall()")
}

cmd := exec.Command("npm", "install")
fmt.Printf("Installing NodeJS modules...\n")

if err = cmd.Run(); err != nil {
return err
}

if err = os.Chdir(".."); err != nil {
return errors.New("error changing back to project root directory in npmInstall()")
}

return nil
}

func buildNode() error {
var (
err error
)

if err = os.Chdir("app"); err != nil {
return errors.New("error changing to app directory in buildNode()")
}

cmd := exec.Command("npm", "run", "build")
fmt.Printf("Building NodeJS app...\n")

if err = cmd.Run(); err != nil {
return err
}

if err = os.Chdir(".."); err != nil {
return errors.New("error changing back to project root directory in buildNode()")
}

return nil
}
7 changes: 3 additions & 4 deletions templates/Config.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"flag"
"fmt"
"strings"

"github.com/spf13/pflag"
"github.com/spf13/viper"
Expand All @@ -23,11 +22,11 @@ func NewConfig(serverVersion string) *viper.Viper {

result.SetDefault("server.cert", "")
result.BindEnv("server.cert", fmt.Sprintf("%s_SERVER_CERT", ENV_PREFIX))
flag.String("server.cert", "", "SSL certificate file name (minus extension)")
flag.String("server.cert", "", "SSL certificate file name (minus extension)"){{if .WantDatabase}}

result.SetDefault("database.url", fmt.Sprintf("postgres://%s:%s@%s/%s", DEFAULT_DB_USER, DEFAULT_DB_PASSWORD, DEFAULT_DB_HOST, strings.ToLower(APP_NAME)))
result.SetDefault("database.url", fmt.Sprintf("postgres://%s:%s@%s/%s", DEFAULT_DB_USER, DEFAULT_DB_PASSWORD, DEFAULT_DB_HOST, DEFAULT_DB_NAME))
result.BindEnv("database.url", fmt.Sprintf("%s_DATABASE_URL", ENV_PREFIX))
flag.String("database.url", fmt.Sprintf("postgres://%s:%s@%s/%s", DEFAULT_DB_USER, DEFAULT_DB_PASSWORD, DEFAULT_DB_HOST, strings.ToLower(APP_NAME)), "URL for connecting to a database")
flag.String("database.url", fmt.Sprintf("postgres://%s:%s@%s/%s", DEFAULT_DB_USER, DEFAULT_DB_PASSWORD, DEFAULT_DB_HOST, DEFAULT_DB_NAME), "URL for connecting to a database"){{end}}

pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.Parse()
Expand Down
1 change: 0 additions & 1 deletion templates/app/AlertService.js.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,3 @@ export class AlertService {
export function AlertServiceInstaller(Vue) {
Vue.prototype.alertService = new AlertService(Vue.toasted);
}

1 change: 0 additions & 1 deletion templates/app/App.vue.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,3 @@ export default {
},
};
</script>

1 change: 0 additions & 1 deletion templates/app/AppFooter.vue.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,3 @@ export default {
},
};
</script>

1 change: 0 additions & 1 deletion templates/app/AppHeader.vue.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,3 @@ export default {
},
};
</script>

1 change: 0 additions & 1 deletion templates/app/BaseURL.js.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ export const baseURL =
process.env.NODE_ENV === "development"
? "http://localhost:8080"
: process.env.VUE_APP_{{.EnvPrefix}}_SERVER_HOST;

1 change: 0 additions & 1 deletion templates/app/Home.vue.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,3 @@ export default {
},
};
</script>

1 change: 0 additions & 1 deletion templates/app/HttpInterceptors.js.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,3 @@ export function InstallHttpInterceptors(Vue) {
};
});
}

2 changes: 0 additions & 2 deletions templates/app/Logo.vue.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,4 @@
/*
* Copyright © {{.Year}}. {{.CompanyName}} All Rights Reserved
*/

</script>

1 change: 0 additions & 1 deletion templates/app/PageTwo.vue.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@ export default {
name: "PageTwo",
};
</script>

1 change: 0 additions & 1 deletion templates/app/VersionService.js.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,3 @@ export class VersionService {
export function VersionServiceInstaller(Vue) {
Vue.prototype.versionService = new VersionService(Vue.http);
}

1 change: 0 additions & 1 deletion templates/app/index.js.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,3 @@ router.beforeEach(async (to, from, next) => {
});

export default router;

1 change: 0 additions & 1 deletion templates/app/main.js.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,3 @@ new Vue({
router,
render: h => h(App),
}).$mount("#app");

2 changes: 1 addition & 1 deletion templates/env.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ STARTER_SERVER_LOGLEVEL=debug
STARTER_SERVER_CERT=
{{if .WantDatabase}}STARTER_DATABASE_URL=postgres://{{.DbUser}}:{{.DbPassword}}@postgres/{{.AppName}}{{end}}

POSTGRES_DB={{.AppName}}
POSTGRES_DB={{.DbName}}
POSTGRES_PORT=5432
POSTGRES_USER={{.DbUser}}
POSTGRES_PASSWORD={{.DbPassword}}
Expand Down
Loading

0 comments on commit 6ab9764

Please sign in to comment.