add ability to set up a webapp
This commit is contained in:
214
cmd/cli/webapp.go
Normal file
214
cmd/cli/webapp.go
Normal file
@ -0,0 +1,214 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//go:embed templates/vue/AboutView.vue.tmpl
|
||||
var aboutViewTemplate string
|
||||
|
||||
//go:embed templates/vue/HomeView.vue.tmpl
|
||||
var homeViewTemplate string
|
||||
|
||||
func setupWebapp(name string) error {
|
||||
fmt.Println("Setting up webapp with Vue 3, TypeScript, Vue Router, Pinia, and ESLint with Prettier")
|
||||
cmd := exec.Command("npm", "create", "vue@latest", "--", "--ts", "--router", "--pinia", "--eslint-with-prettier", name)
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error setting up webapp | %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Switching to the new directory")
|
||||
// cd into the new directory
|
||||
err = os.Chdir(name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error changing directory | %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Installing base dependencies")
|
||||
// install all dependencies and format the code
|
||||
cmd = exec.Command("npm", "install", "&&", "npm", "run", "format")
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error changing directory | %w", err)
|
||||
}
|
||||
|
||||
// make src/assets/base.css and src/assets/main.css mostly empty files
|
||||
err = os.WriteFile("src/assets/base.css", []byte(""), 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing base.css | %w", err)
|
||||
}
|
||||
err = os.WriteFile("src/assets/main.css", []byte("@import './base.css';"), 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing main.css | %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Setting up Tailwind CSS")
|
||||
err = setupTailwind()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error setting up tailwind | %w", err)
|
||||
}
|
||||
|
||||
// clean up the default example files
|
||||
err = removeListOfFiles([]string{
|
||||
"src/components/HelloWorld.vue",
|
||||
"src/components/TheWelcome.vue",
|
||||
"src/components/WelcomeItem.vue",
|
||||
"src/views/AboutView.vue", // replace with new AboutView.vue
|
||||
"src/components/icons/IconCommunity.vue",
|
||||
"src/components/icons/IconDocumentation.vue",
|
||||
"src/components/icons/IconEcosystem.vue",
|
||||
"src/components/icons/IconSupport.vue",
|
||||
"src/components/icons/IconTooling.vue",
|
||||
"src/assets/logo.svg",
|
||||
})
|
||||
|
||||
// create a new about view from the aboutViewTemplate
|
||||
err = os.WriteFile("src/views/AboutView.vue", []byte(aboutViewTemplate), 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing new AboutView.vue | %w", err)
|
||||
}
|
||||
// create a new home view from the homeViewTemplate
|
||||
err = os.WriteFile("src/views/HomeView.vue", []byte(homeViewTemplate), 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing new HomeView.vue | %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Exiting the new directory")
|
||||
err = os.Chdir("..")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error changing directory | %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupTailwind() error {
|
||||
// check that there is a vite.config.ts file and a package.json file
|
||||
_, err := os.Stat("vite.config.ts")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error checking for vite.config.ts | %w", err)
|
||||
}
|
||||
_, err = os.Stat("package.json")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error checking for package.json | %w", err)
|
||||
}
|
||||
|
||||
cmd := exec.Command("npm", "install", "tailwindcss", "@tailwindcss/vite")
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error installing tailwindcss | %w", err)
|
||||
}
|
||||
|
||||
// In the vite.config.ts insert the following code after the last import statement `import tailwindcss from '@tailwindcss/vite'`
|
||||
err = insertImportStatement("import tailwindcss from '@tailwindcss/vite'", "vite.config.ts")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error inserting import statement | %w", err)
|
||||
}
|
||||
|
||||
// In the vite.config.ts insert the following code after the last plugin usage `tailwindcss(),`
|
||||
err = insertPluginUsage(" tailwindcss(),", "vite.config.ts")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error inserting plugin usage | %w", err)
|
||||
}
|
||||
|
||||
// in the base.css file add an @import statement for tailwind
|
||||
// check that './src/assets/base.css' exists
|
||||
_, err = os.Stat("./src/assets/base.css")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error checking for base.css | %w", err)
|
||||
}
|
||||
err = insertAtTopLineOfFile("@import \"tailwindcss\";", "./src/assets/base.css")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error inserting import statement | %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func insertImportStatement(importStatement string, filename string) error {
|
||||
fileContent, err := os.ReadFile(fmt.Sprintf(".%c%s", os.PathSeparator, filename))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading %s | %w", filename, err)
|
||||
}
|
||||
|
||||
fileLines := strings.Split(strings.ReplaceAll(string(fileContent), "\r\n", "\n"), "\n")
|
||||
lastImportIndex := -1
|
||||
// finds the last import statement in the file and appends after that one
|
||||
for i, line := range fileLines {
|
||||
if strings.HasPrefix(line, "import") {
|
||||
lastImportIndex = i
|
||||
}
|
||||
}
|
||||
if lastImportIndex != -1 {
|
||||
fileLines = append(fileLines[:lastImportIndex+1], append([]string{importStatement}, fileLines[lastImportIndex+1:]...)...)
|
||||
} else {
|
||||
// add the import to the top of the file
|
||||
fileLines = append([]string{importStatement}, fileLines...)
|
||||
}
|
||||
|
||||
err = os.WriteFile(filename, []byte(strings.Join(fileLines, "\n")), 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing vite.config.ts | %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func insertPluginUsage(pluginUsage string, filename string) error {
|
||||
fileContent, err := os.ReadFile(fmt.Sprintf(".%c%s", os.PathSeparator, filename))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading %s | %w", filename, err)
|
||||
}
|
||||
|
||||
fileLines := strings.Split(strings.ReplaceAll(string(fileContent), "\r\n", "\n"), "\n")
|
||||
startOfPluginsIndex := -1
|
||||
// finds the `plugins: [` line in the file and appends after that one
|
||||
for i, line := range fileLines {
|
||||
if strings.Contains(line, "plugins: [") {
|
||||
startOfPluginsIndex = i
|
||||
}
|
||||
}
|
||||
if startOfPluginsIndex != -1 {
|
||||
fileLines = append(fileLines[:startOfPluginsIndex+1], append([]string{pluginUsage}, fileLines[startOfPluginsIndex+1:]...)...)
|
||||
} else {
|
||||
// add the import to the top of the file
|
||||
fileLines = append([]string{pluginUsage}, fileLines...)
|
||||
}
|
||||
|
||||
err = os.WriteFile(filename, []byte(strings.Join(fileLines, "\n")), 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing vite.config.ts | %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func insertAtTopLineOfFile(content string, filename string) error {
|
||||
fileContent, err := os.ReadFile(fmt.Sprintf(".%c%s", os.PathSeparator, filename))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading %s | %w", filename, err)
|
||||
}
|
||||
|
||||
fileLines := strings.Split(strings.ReplaceAll(string(fileContent), "\r\n", "\n"), "\n")
|
||||
fileLines = append([]string{content}, fileLines...)
|
||||
|
||||
err = os.WriteFile(filename, []byte(strings.Join(fileLines, "\n")), 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing vite.config.ts | %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeListOfFiles(files []string) error {
|
||||
|
||||
for _, file := range files {
|
||||
err := os.Remove(file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error removing %s | %w", file, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user