add support for env variables to the DSL
This commit is contained in:
@ -140,23 +140,9 @@ func (hi *HTMLInterpreter) generatePageHTML(page *lang.Page) (string, error) {
|
||||
// JavaScript for interactivity
|
||||
html.WriteString(" <script>\n")
|
||||
|
||||
// API Base URL configuration
|
||||
apiBaseURL := "http://localhost:8080"
|
||||
if hi.server != nil {
|
||||
host := "localhost"
|
||||
port := 8080
|
||||
for _, setting := range hi.server.Settings {
|
||||
if setting.Host != nil {
|
||||
host = *setting.Host
|
||||
}
|
||||
if setting.Port != nil {
|
||||
port = *setting.Port
|
||||
}
|
||||
}
|
||||
apiBaseURL = fmt.Sprintf("http://%s:%d", host, port)
|
||||
}
|
||||
// Generate server configuration code that handles env vars and defaults at runtime
|
||||
html.WriteString(hi.generateServerConfigJS())
|
||||
|
||||
html.WriteString(fmt.Sprintf(" const API_BASE_URL = '%s';\n", apiBaseURL))
|
||||
html.WriteString(" \n")
|
||||
html.WriteString(" // API helper functions\n")
|
||||
html.WriteString(" async function apiRequest(method, endpoint, data = null) {\n")
|
||||
@ -348,6 +334,86 @@ func (hi *HTMLInterpreter) generatePageHTML(page *lang.Page) (string, error) {
|
||||
return html.String(), nil
|
||||
}
|
||||
|
||||
// generateServerConfigJS generates JavaScript code that handles server configuration at runtime
|
||||
func (hi *HTMLInterpreter) generateServerConfigJS() string {
|
||||
var js strings.Builder
|
||||
|
||||
// Default API base URL
|
||||
js.WriteString(" // Server configuration\n")
|
||||
js.WriteString(" let apiHost = 'localhost';\n")
|
||||
js.WriteString(" let apiPort = 8080;\n\n")
|
||||
|
||||
if hi.server != nil {
|
||||
for _, setting := range hi.server.Settings {
|
||||
if setting.Host != nil {
|
||||
js.WriteString(hi.generateConfigValueJS("apiHost", setting.Host))
|
||||
}
|
||||
if setting.Port != nil {
|
||||
js.WriteString(hi.generateIntValueJS("apiPort", setting.Port))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
js.WriteString(" const API_BASE_URL = `http://${apiHost}:${apiPort}`;\n")
|
||||
js.WriteString(" console.log('API Base URL:', API_BASE_URL);\n")
|
||||
|
||||
return js.String()
|
||||
}
|
||||
|
||||
// generateConfigValueJS generates JavaScript code to resolve a ConfigValue at runtime
|
||||
func (hi *HTMLInterpreter) generateConfigValueJS(varName string, configValue *lang.ConfigValue) string {
|
||||
var js strings.Builder
|
||||
|
||||
if configValue.Literal != nil {
|
||||
// Simple literal assignment
|
||||
js.WriteString(fmt.Sprintf(" %s = %q;\n", varName, *configValue.Literal))
|
||||
} else if configValue.EnvVar != nil {
|
||||
// Environment variable resolution in browser (note: this is limited in browsers)
|
||||
// For client-side, we'll need to use a different approach since browsers can't access server env vars
|
||||
// We'll generate code that looks for the env var in localStorage or a global config object
|
||||
js.WriteString(fmt.Sprintf(" // Check for %s in global config or localStorage\n", configValue.EnvVar.Name))
|
||||
js.WriteString(fmt.Sprintf(" if (window.CONFIG && window.CONFIG['%s']) {\n", configValue.EnvVar.Name))
|
||||
js.WriteString(fmt.Sprintf(" %s = window.CONFIG['%s'];\n", varName, configValue.EnvVar.Name))
|
||||
js.WriteString(fmt.Sprintf(" } else if (localStorage.getItem('%s')) {\n", configValue.EnvVar.Name))
|
||||
js.WriteString(fmt.Sprintf(" %s = localStorage.getItem('%s');\n", varName, configValue.EnvVar.Name))
|
||||
|
||||
if configValue.EnvVar.Default != nil {
|
||||
js.WriteString(" } else {\n")
|
||||
js.WriteString(fmt.Sprintf(" %s = %q;\n", varName, *configValue.EnvVar.Default))
|
||||
}
|
||||
js.WriteString(" }\n")
|
||||
}
|
||||
|
||||
return js.String()
|
||||
}
|
||||
|
||||
// generateIntValueJS generates JavaScript code to resolve an IntValue at runtime
|
||||
func (hi *HTMLInterpreter) generateIntValueJS(varName string, intValue *lang.IntValue) string {
|
||||
var js strings.Builder
|
||||
|
||||
if intValue.Literal != nil {
|
||||
// Simple literal assignment
|
||||
js.WriteString(fmt.Sprintf(" %s = %d;\n", varName, *intValue.Literal))
|
||||
} else if intValue.EnvVar != nil {
|
||||
// Environment variable resolution for integers
|
||||
js.WriteString(fmt.Sprintf(" // Check for %s in global config or localStorage\n", intValue.EnvVar.Name))
|
||||
js.WriteString(fmt.Sprintf(" if (window.CONFIG && window.CONFIG['%s']) {\n", intValue.EnvVar.Name))
|
||||
js.WriteString(fmt.Sprintf(" const val = parseInt(window.CONFIG['%s']);\n", intValue.EnvVar.Name))
|
||||
js.WriteString(fmt.Sprintf(" if (!isNaN(val)) %s = val;\n", varName))
|
||||
js.WriteString(fmt.Sprintf(" } else if (localStorage.getItem('%s')) {\n", intValue.EnvVar.Name))
|
||||
js.WriteString(fmt.Sprintf(" const val = parseInt(localStorage.getItem('%s'));\n", intValue.EnvVar.Name))
|
||||
js.WriteString(fmt.Sprintf(" if (!isNaN(val)) %s = val;\n", varName))
|
||||
|
||||
if intValue.EnvVar.Default != nil {
|
||||
js.WriteString(" } else {\n")
|
||||
js.WriteString(fmt.Sprintf(" %s = %s;\n", varName, *intValue.EnvVar.Default))
|
||||
}
|
||||
js.WriteString(" }\n")
|
||||
}
|
||||
|
||||
return js.String()
|
||||
}
|
||||
|
||||
// generateSectionHTML creates HTML for a section
|
||||
func (hi *HTMLInterpreter) generateSectionHTML(section *lang.Section, indent int) (string, error) {
|
||||
var html strings.Builder
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"go/format"
|
||||
"masonry/lang"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/cases"
|
||||
@ -69,6 +70,8 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
"github.com/google/uuid"
|
||||
@ -362,25 +365,95 @@ func (si *ServerInterpreter) generateMainFunction() string {
|
||||
}
|
||||
}
|
||||
|
||||
// Server configuration
|
||||
host := "localhost"
|
||||
port := 8080
|
||||
// Generate server configuration code that handles env vars and defaults at runtime
|
||||
code.WriteString("\n\t// Server configuration\n")
|
||||
code.WriteString(si.generateServerConfigCode())
|
||||
|
||||
if si.server != nil {
|
||||
for _, setting := range si.server.Settings {
|
||||
if setting.Host != nil {
|
||||
host = *setting.Host
|
||||
}
|
||||
if setting.Port != nil {
|
||||
port = *setting.Port
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
code.WriteString(fmt.Sprintf("\n\taddr := \"%s:%d\"\n", host, port))
|
||||
code.WriteString("\n\taddr := fmt.Sprintf(\"%s:%d\", host, port)\n")
|
||||
code.WriteString("\tfmt.Printf(\"Server starting on %s\\n\", addr)\n")
|
||||
code.WriteString("\tlog.Fatal(http.ListenAndServe(addr, r))\n")
|
||||
code.WriteString("}\n")
|
||||
|
||||
return code.String()
|
||||
}
|
||||
|
||||
// generateServerConfigCode generates Go code that handles server configuration at runtime
|
||||
func (si *ServerInterpreter) generateServerConfigCode() string {
|
||||
var code strings.Builder
|
||||
|
||||
// Default values
|
||||
hostDefault := "localhost"
|
||||
portDefault := 8080
|
||||
var hostConfigValueCode, portConfigValueCode string
|
||||
|
||||
if si.server != nil {
|
||||
for _, setting := range si.server.Settings {
|
||||
if setting.Host != nil {
|
||||
if setting.Host.EnvVar != nil && setting.Host.EnvVar.Default != nil {
|
||||
hostDefault = *setting.Host.EnvVar.Default
|
||||
}
|
||||
hostConfigValueCode = si.generateConfigValueCode("host", setting.Host)
|
||||
}
|
||||
if setting.Port != nil {
|
||||
if setting.Port.EnvVar != nil && setting.Port.EnvVar.Default != nil {
|
||||
if defInt, err := strconv.Atoi(*setting.Port.EnvVar.Default); err == nil {
|
||||
portDefault = defInt
|
||||
}
|
||||
}
|
||||
portConfigValueCode = si.generateIntValueCode("port", setting.Port)
|
||||
}
|
||||
}
|
||||
}
|
||||
code.WriteString(fmt.Sprintf("\thost := \"%s\"\n", hostDefault))
|
||||
code.WriteString(fmt.Sprintf("\tport := %d\n\n", portDefault))
|
||||
code.WriteString(hostConfigValueCode)
|
||||
code.WriteString(portConfigValueCode)
|
||||
|
||||
return code.String()
|
||||
}
|
||||
|
||||
// generateConfigValueCode generates Go code to resolve a ConfigValue at runtime
|
||||
func (si *ServerInterpreter) generateConfigValueCode(varName string, configValue *lang.ConfigValue) string {
|
||||
var code strings.Builder
|
||||
|
||||
if configValue.Literal != nil {
|
||||
// Simple literal assignment
|
||||
code.WriteString(fmt.Sprintf("\t%s = %q\n", varName, *configValue.Literal))
|
||||
} else if configValue.EnvVar != nil {
|
||||
// Environment variable with optional default
|
||||
code.WriteString(fmt.Sprintf("\tif envVal := os.Getenv(%q); envVal != \"\" {\n", configValue.EnvVar.Name))
|
||||
code.WriteString(fmt.Sprintf("\t\t%s = envVal\n", varName))
|
||||
|
||||
if configValue.EnvVar.Default != nil {
|
||||
code.WriteString("\t} else {\n")
|
||||
code.WriteString(fmt.Sprintf("\t\t%s = %q\n", varName, *configValue.EnvVar.Default))
|
||||
}
|
||||
code.WriteString("\t}\n")
|
||||
}
|
||||
|
||||
return code.String()
|
||||
}
|
||||
|
||||
// generateIntValueCode generates Go code to resolve an IntValue at runtime
|
||||
func (si *ServerInterpreter) generateIntValueCode(varName string, intValue *lang.IntValue) string {
|
||||
var code strings.Builder
|
||||
|
||||
if intValue.Literal != nil {
|
||||
// Simple literal assignment
|
||||
code.WriteString(fmt.Sprintf("\t%s = %d\n", varName, *intValue.Literal))
|
||||
} else if intValue.EnvVar != nil {
|
||||
// Environment variable with optional default
|
||||
code.WriteString(fmt.Sprintf("\tif envVal := os.Getenv(%q); envVal != \"\" {\n", intValue.EnvVar.Name))
|
||||
code.WriteString(fmt.Sprintf("\t\tif val, err := strconv.Atoi(envVal); err == nil {\n"))
|
||||
code.WriteString(fmt.Sprintf("\t\t\t%s = val\n", varName))
|
||||
code.WriteString("\t\t}\n")
|
||||
|
||||
if intValue.EnvVar.Default != nil {
|
||||
code.WriteString("\t} else {\n")
|
||||
code.WriteString(fmt.Sprintf("\t\t%s = %s\n", varName, *intValue.EnvVar.Default))
|
||||
}
|
||||
code.WriteString("\t}\n")
|
||||
}
|
||||
|
||||
return code.String()
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
@ -115,28 +116,58 @@ func (ti *TemplateInterpreter) Interpret(masonryInput string, tmplText string) (
|
||||
"getHost": func(settings []lang.ServerSetting) string {
|
||||
for _, s := range settings {
|
||||
if s.Host != nil {
|
||||
return *s.Host
|
||||
if s.Host.Literal != nil {
|
||||
return "\"" + *s.Host.Literal + "\""
|
||||
}
|
||||
return fmt.Sprintf(`func() string { if v := os.Getenv("%s"); v != "" { return v }; return "%s" }()`, s.Host.EnvVar.Name, func() string {
|
||||
if s.Host.EnvVar.Default != nil {
|
||||
return *s.Host.EnvVar.Default
|
||||
}
|
||||
return "localhost"
|
||||
}())
|
||||
}
|
||||
}
|
||||
return "localhost"
|
||||
},
|
||||
"getPort": func(settings []lang.ServerSetting) int {
|
||||
"getPort": func(settings []lang.ServerSetting) string {
|
||||
for _, s := range settings {
|
||||
if s.Port != nil {
|
||||
return *s.Port
|
||||
if s.Port.Literal != nil {
|
||||
return strconv.Itoa(*s.Port.Literal)
|
||||
}
|
||||
return fmt.Sprintf(`func() string { if v := os.Getenv("%s"); v != "" { return v }; return "%s" }()`, s.Port.EnvVar.Name, func() string {
|
||||
if s.Port.EnvVar.Default != nil {
|
||||
return *s.Port.EnvVar.Default
|
||||
}
|
||||
return "8080"
|
||||
}())
|
||||
}
|
||||
}
|
||||
return 8080
|
||||
return "8080"
|
||||
},
|
||||
"getServerHostPort": func(settings []lang.ServerSetting) string {
|
||||
host := "localhost"
|
||||
port := 8080
|
||||
for _, s := range settings {
|
||||
if s.Host != nil {
|
||||
host = *s.Host
|
||||
if s.Host.Literal != nil {
|
||||
host = *s.Host.Literal
|
||||
}
|
||||
if s.Host.EnvVar != nil && s.Host.EnvVar.Default != nil {
|
||||
host = *s.Host.EnvVar.Default
|
||||
}
|
||||
// If it's an env var, keep the default
|
||||
}
|
||||
if s.Port != nil {
|
||||
port = *s.Port
|
||||
if s.Port.Literal != nil {
|
||||
port = *s.Port.Literal
|
||||
}
|
||||
if s.Port.EnvVar != nil && s.Port.EnvVar.Default != nil {
|
||||
if p, err := strconv.Atoi(*s.Port.EnvVar.Default); err == nil {
|
||||
port = p
|
||||
}
|
||||
}
|
||||
// If it's an env var, keep the default
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("%s:%d", host, port)
|
||||
@ -234,28 +265,58 @@ func NewTemplateRegistry() *TemplateRegistry {
|
||||
"getHost": func(settings []lang.ServerSetting) string {
|
||||
for _, s := range settings {
|
||||
if s.Host != nil {
|
||||
return *s.Host
|
||||
if s.Host.Literal != nil {
|
||||
return "\"" + *s.Host.Literal + "\""
|
||||
}
|
||||
return fmt.Sprintf(`func() string { if v := os.Getenv("%s"); v != "" { return v }; return "%s" }()`, s.Host.EnvVar.Name, func() string {
|
||||
if s.Host.EnvVar.Default != nil {
|
||||
return *s.Host.EnvVar.Default
|
||||
}
|
||||
return "localhost"
|
||||
}())
|
||||
}
|
||||
}
|
||||
return "localhost"
|
||||
},
|
||||
"getPort": func(settings []lang.ServerSetting) int {
|
||||
"getPort": func(settings []lang.ServerSetting) string {
|
||||
for _, s := range settings {
|
||||
if s.Port != nil {
|
||||
return *s.Port
|
||||
if s.Port.Literal != nil {
|
||||
return strconv.Itoa(*s.Port.Literal)
|
||||
}
|
||||
return fmt.Sprintf(`func() string { if v := os.Getenv("%s"); v != "" { return v }; return "%s" }()`, s.Port.EnvVar.Name, func() string {
|
||||
if s.Port.EnvVar.Default != nil {
|
||||
return *s.Port.EnvVar.Default
|
||||
}
|
||||
return "8080"
|
||||
}())
|
||||
}
|
||||
}
|
||||
return 8080
|
||||
return "8080"
|
||||
},
|
||||
"getServerHostPort": func(settings []lang.ServerSetting) string {
|
||||
host := "localhost"
|
||||
port := 8080
|
||||
for _, s := range settings {
|
||||
if s.Host != nil {
|
||||
host = *s.Host
|
||||
if s.Host.Literal != nil {
|
||||
host = *s.Host.Literal
|
||||
}
|
||||
if s.Host.EnvVar != nil && s.Host.EnvVar.Default != nil {
|
||||
host = *s.Host.EnvVar.Default
|
||||
}
|
||||
// If it's an env var, keep the default
|
||||
}
|
||||
if s.Port != nil {
|
||||
port = *s.Port
|
||||
if s.Port.Literal != nil {
|
||||
port = *s.Port.Literal
|
||||
}
|
||||
if s.Port.EnvVar != nil && s.Port.EnvVar.Default != nil {
|
||||
if p, err := strconv.Atoi(*s.Port.EnvVar.Default); err == nil {
|
||||
port = p
|
||||
}
|
||||
}
|
||||
// If it's an env var, keep the default
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("%s:%d", host, port)
|
||||
|
Reference in New Issue
Block a user