diff --git a/CHANGELOG.md b/CHANGELOG.md index 86470bb6..501aef91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ In previous releases, the name "Hypermode" was used for all three._ - Fix CLI warnings about Go/TinyGo installation [#487](https://github.com/hypermodeinc/modus/pull/487) - Remove deprecated model fields [#488](https://github.com/hypermodeinc/modus/pull/488) - Improve dev first use log messages [#489](https://github.com/hypermodeinc/modus/pull/489) +- Highlight endpoints when running in dev [#490](https://github.com/hypermodeinc/modus/pull/490) ## 2024-10-02 - Version 0.12.7 diff --git a/runtime/go.mod b/runtime/go.mod index 8e307e97..2abfe99a 100644 --- a/runtime/go.mod +++ b/runtime/go.mod @@ -26,6 +26,7 @@ require ( github.com/dgraph-io/dgo/v230 v230.0.1 github.com/docker/docker v27.3.1+incompatible github.com/docker/go-connections v0.5.0 + github.com/fatih/color v1.18.0 github.com/getsentry/sentry-go v0.29.1 github.com/go-viper/mapstructure/v2 v2.2.1 github.com/goccy/go-json v0.10.3 @@ -122,7 +123,7 @@ require ( golang.org/x/crypto v0.27.0 // indirect golang.org/x/net v0.29.0 // indirect golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.25.0 // indirect + golang.org/x/sys v0.26.0 // indirect golang.org/x/text v0.18.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240924160255-9d4c2d233b61 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61 // indirect diff --git a/runtime/go.sum b/runtime/go.sum index 04e23230..15d17f48 100644 --- a/runtime/go.sum +++ b/runtime/go.sum @@ -79,6 +79,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dop251/goja v0.0.0-20240919115326-6c7d1df7ff05 h1:oK4+QcKsczZjHYTHD0JAdkvq5w74JEkG95J0XNBx/BI= github.com/dop251/goja v0.0.0-20240919115326-6c7d1df7ff05/go.mod h1:MxLav0peU43GgvwVgNbLAj1s/bSGboKkhuULvq/7hx4= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= @@ -325,8 +327,8 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= diff --git a/runtime/httpserver/server.go b/runtime/httpserver/server.go index 70045428..277872f3 100644 --- a/runtime/httpserver/server.go +++ b/runtime/httpserver/server.go @@ -21,6 +21,7 @@ import ( "syscall" "time" + "github.com/fatih/color" "github.com/hypermodeinc/modus/lib/manifest" "github.com/hypermodeinc/modus/runtime/config" "github.com/hypermodeinc/modus/runtime/graphql" @@ -129,6 +130,14 @@ func GetMainHandler(options ...func(map[string]http.Handler)) http.Handler { manifestdata.RegisterManifestLoadedCallback(func(ctx context.Context) error { routes := maps.Clone(defaultRoutes) + type endpoint struct { + apiType string + name string + url string + } + + var endpoints []endpoint + m := manifestdata.GetManifest() for name, ep := range m.Endpoints { switch ep.EndpointType() { @@ -148,9 +157,9 @@ func GetMainHandler(options ...func(map[string]http.Handler)) http.Handler { routes[info.Path] = metrics.InstrumentHandler(handler, name) - logger.Info(ctx). - Str("url", fmt.Sprintf("http://localhost:%d%s", config.Port, info.Path)). - Msg("Registered GraphQL endpoint.") + url := fmt.Sprintf("http://localhost:%d%s", config.Port, info.Path) + logger.Info(ctx).Str("url", url).Msg("Registered GraphQL endpoint.") + endpoints = append(endpoints, endpoint{"GraphQL", name, url}) default: logger.Warn(ctx).Str("endpoint", name).Msg("Unsupported endpoint type.") @@ -159,6 +168,33 @@ func GetMainHandler(options ...func(map[string]http.Handler)) http.Handler { mux.ReplaceRoutes(routes) + if len(endpoints) > 0 && config.IsDevEnvironment() { + fmt.Println() + + titleColor := color.New(color.FgHiGreen, color.Bold) + itemColor := color.New(color.FgHiBlue) + urlColor := color.New(color.FgHiCyan) + noticeColor := color.New(color.FgGreen, color.Italic) + + if len(endpoints) == 1 { + ep := endpoints[0] + titleColor.Println("Your local endpoint is ready!") + itemColor.Printf("• %s (%s): ", ep.apiType, ep.name) + urlColor.Println(ep.url) + } else { + titleColor.Println("Your local endpoints are ready!") + for _, ep := range endpoints { + itemColor.Printf("• %s (%s): ", ep.apiType, ep.name) + urlColor.Println(ep.url) + } + } + + fmt.Println() + noticeColor.Println("Changes will automatically be applied when you save your files.") + noticeColor.Println("Press Ctrl+C at any time to stop the server.") + fmt.Println() + } + return nil })