~repos /gromer

#golang#htmx#ssr

git clone https://pyrossh.dev/repos/gromer.git

gromer is a framework and cli to build multipage web apps in golang using htmx and alpinejs.


43cb0718 Peter John

3 years ago
fix favicon
_example/assets/favicon.ico ADDED
Binary file
_example/main.go CHANGED
@@ -4,6 +4,7 @@ package main
4
4
  import (
5
5
  "github.com/gorilla/mux"
6
6
  "github.com/pyros2097/gromer"
7
+ "github.com/pyros2097/gromer/assets"
7
8
  "github.com/pyros2097/gromer/gsx"
8
9
  "github.com/rs/zerolog/log"
9
10
  "gocloud.dev/server"
@@ -20,11 +21,8 @@ import (
20
21
  func init() {
21
22
  gsx.RegisterComponent(components.Todo, "todo")
22
23
  gsx.RegisterComponent(components.Checkbox, "value")
23
-
24
24
  gsx.RegisterComponent(containers.TodoCount, "filter")
25
25
  gsx.RegisterComponent(containers.TodoList, "page", "filter")
26
-
27
- gromer.RegisterAssets(assets.FS)
28
26
  }
29
27
 
30
28
  func main() {
@@ -34,8 +32,8 @@ func main() {
34
32
 
35
33
  staticRouter := baseRouter.NewRoute().Subrouter()
36
34
  staticRouter.Use(gromer.CacheMiddleware)
37
- gromer.GromerRoute(staticRouter, "/gromer/")
35
+ gromer.StaticRoute(staticRouter, "/gromer/", gromer_assets.FS)
38
- gromer.StaticRoute(staticRouter, "/assets/")
36
+ gromer.StaticRoute(staticRouter, "/assets/", assets.FS)
39
37
  gromer.StylesRoute(staticRouter, "/styles.css")
40
38
 
41
39
  pageRouter := baseRouter.NewRoute().Subrouter()
assets/assets.go CHANGED
@@ -1,4 +1,4 @@
1
- package assets
1
+ package gromer_assets
2
2
 
3
3
  import (
4
4
  "embed"
cmd/gromer/main.go CHANGED
@@ -182,6 +182,7 @@ package main
182
182
  import (
183
183
  "github.com/gorilla/mux"
184
184
  "github.com/pyros2097/gromer"
185
+ "github.com/pyros2097/gromer/assets"
185
186
  "github.com/pyros2097/gromer/gsx"
186
187
  "github.com/rs/zerolog/log"
187
188
  "gocloud.dev/server"
@@ -196,10 +197,8 @@ import (
196
197
 
197
198
  func init() {
198
199
  {{#each componentNames as |name| }}gsx.RegisterComponent(components.{{ name }})
200
+ {{/each}}{{#each containerNames as |name| }}gsx.RegisterComponent(containers.{{ name }})
199
201
  {{/each}}
200
- {{#each containerNames as |name| }}gsx.RegisterComponent(containers.{{ name }})
201
- {{/each}}
202
- gromer.RegisterAssets(assets.FS)
203
202
  }
204
203
 
205
204
  func main() {
@@ -209,8 +208,8 @@ func main() {
209
208
  {{/if}}
210
209
  staticRouter := baseRouter.NewRoute().Subrouter()
211
210
  staticRouter.Use(gromer.CacheMiddleware)
212
- gromer.GromerRoute(staticRouter, "/gromer/")
211
+ gromer.StaticRoute(staticRouter, "/gromer/", gromer_assets.FS)
213
- gromer.StaticRoute(staticRouter, "/assets/")
212
+ gromer.StaticRoute(staticRouter, "/assets/", assets.FS)
214
213
  gromer.StylesRoute(staticRouter, "/styles.css")
215
214
 
216
215
  pageRouter := baseRouter.NewRoute().Subrouter()
http.go CHANGED
@@ -22,7 +22,6 @@ import (
22
22
  "github.com/go-playground/validator/v10"
23
23
  "github.com/google/uuid"
24
24
  "github.com/gorilla/mux"
25
- "github.com/pyros2097/gromer/assets"
26
25
  "github.com/pyros2097/gromer/gsx"
27
26
  "github.com/rs/zerolog"
28
27
  "github.com/rs/zerolog/log"
@@ -30,8 +29,21 @@ import (
30
29
  "xojoc.pw/useragent"
31
30
  )
32
31
 
32
+ var (
33
- var info *debug.BuildInfo
33
+ info *debug.BuildInfo
34
- var IsCloundRun bool
34
+ IsCloundRun bool
35
+ routeDefs []RouteDefinition
36
+ pathParamsRegex = regexp.MustCompile(`{(.*?)}`)
37
+ )
38
+
39
+ type RouteDefinition struct {
40
+ Pkg string `json:"pkg"`
41
+ PkgPath string `json:"pkgPath"`
42
+ Method string `json:"method"`
43
+ Path string `json:"path"`
44
+ PathParams []string `json:"pathParams"`
45
+ Params interface{} `json:"params"`
46
+ }
35
47
 
36
48
  func init() {
37
49
  IsCloundRun = os.Getenv("K_REVISION") != ""
@@ -51,20 +63,6 @@ func init() {
51
63
  }
52
64
  gsx.RegisterFunc(GetStylesUrl)
53
65
  gsx.RegisterFunc(GetAssetUrl)
54
- gsx.RegisterFunc(GetAlpineJsUrl)
55
- gsx.RegisterFunc(GetHtmxJsUrl)
56
- }
57
-
58
- var RouteDefs []RouteDefinition
59
- var appAssets embed.FS
60
-
61
- type RouteDefinition struct {
62
- Pkg string `json:"pkg"`
63
- PkgPath string `json:"pkgPath"`
64
- Method string `json:"method"`
65
- Path string `json:"path"`
66
- PathParams []string `json:"pathParams"`
67
- Params interface{} `json:"params"`
68
66
  }
69
67
 
70
68
  func getFunctionName(temp interface{}) string {
@@ -72,10 +70,6 @@ func getFunctionName(temp interface{}) string {
72
70
  return strs[len(strs)-1]
73
71
  }
74
72
 
75
- func RegisterAssets(fs embed.FS) {
76
- appAssets = fs
77
- }
78
-
79
73
  func RespondError(w http.ResponseWriter, status int, err error) {
80
74
  w.Header().Set("Content-Type", "application/json")
81
75
  w.WriteHeader(status) // always write status last
@@ -94,8 +88,6 @@ func RespondError(w http.ResponseWriter, status int, err error) {
94
88
  w.Write(data)
95
89
  }
96
90
 
97
- var pathParamsRegex = regexp.MustCompile(`{(.*?)}`)
98
-
99
91
  func GetRouteParams(route string) []string {
100
92
  params := []string{}
101
93
  found := pathParamsRegex.FindAllString(route, -1)
@@ -117,7 +109,7 @@ func addRouteDef(method, route string, h interface{}) {
117
109
  }
118
110
  body = instance.Interface()
119
111
  }
120
- RouteDefs = append(RouteDefs, RouteDefinition{
112
+ routeDefs = append(routeDefs, RouteDefinition{
121
113
  Method: method,
122
114
  Path: route,
123
115
  PathParams: pathParams,
@@ -129,10 +121,10 @@ func PerformRequest(route string, h interface{}, ctx context.Context, w http.Res
129
121
  params := GetRouteParams(route)
130
122
  renderContext := gsx.NewContext(ctx, r.Header.Get("HX-Request") == "true")
131
123
  renderContext.Set("requestId", uuid.NewString())
132
- renderContext.Link("rel", GetAssetUrl("images/icon.png"), "", "")
133
124
  renderContext.Link("stylesheet", GetStylesUrl(), "", "")
134
- renderContext.Script(GetAlpineJsUrl(), true)
125
+ renderContext.Link("icon", "/assets/favicon.ico", "image/x-icon", "image")
135
- renderContext.Script(GetHtmxJsUrl(), false)
126
+ renderContext.Script("/gromer/js/htmx@1.7.0.js", false)
127
+ renderContext.Script("/gromer/js/alpinejs@3.9.6.js", true)
136
128
  args := []reflect.Value{reflect.ValueOf(renderContext)}
137
129
  funcType := reflect.TypeOf(h)
138
130
  icount := funcType.NumIn()
@@ -225,13 +217,6 @@ func PerformRequest(route string, h interface{}, ctx context.Context, w http.Res
225
217
  v.Write(renderContext, w)
226
218
  return
227
219
  }
228
- // if v, ok := response.(handlebars.CssContent); ok {
229
- // w.Header().Set("Content-Type", "text/css")
230
- // // This has to be at end always
231
- // w.WriteHeader(responseStatus)
232
- // w.Write([]byte(v))
233
- // return
234
- // }
235
220
  w.Header().Set("Content-Type", "application/json")
236
221
  // This has to be at end always
237
222
  w.WriteHeader(responseStatus)
@@ -369,12 +354,8 @@ func StatusHandler(h interface{}) http.Handler {
369
354
  })).(http.Handler)
370
355
  }
371
356
 
372
- func StaticRoute(router *mux.Router, path string) {
357
+ func StaticRoute(router *mux.Router, path string, fs embed.FS) {
373
- router.PathPrefix(path).Methods("GET").Handler(http.StripPrefix(path, http.FileServer(http.FS(appAssets))))
358
+ router.PathPrefix(path).Methods("GET").Handler(http.StripPrefix(path, http.FileServer(http.FS(fs))))
374
- }
375
-
376
- func GromerRoute(router *mux.Router, path string) {
377
- router.PathPrefix(path).Methods("GET").Handler(http.StripPrefix(path, http.FileServer(http.FS(assets.FS))))
378
359
  }
379
360
 
380
361
  func StylesRoute(router *mux.Router, path string) {
@@ -412,9 +393,9 @@ func getSum(k string, cb func() [16]byte) string {
412
393
  return sum
413
394
  }
414
395
 
415
- func GetAssetUrl(path string) string {
396
+ func GetAssetUrl(fs embed.FS, path string) string {
416
397
  sum := getSum(path, func() [16]byte {
417
- data, err := appAssets.ReadFile(path)
398
+ data, err := fs.ReadFile(path)
418
399
  if err != nil {
419
400
  panic(err)
420
401
  }
@@ -423,14 +404,6 @@ func GetAssetUrl(path string) string {
423
404
  return fmt.Sprintf("/assets/%s?hash=%s", path, sum)
424
405
  }
425
406
 
426
- func GetHtmxJsUrl() string {
427
- return "/gromer/js/htmx@1.7.0.js"
428
- }
429
-
430
- func GetAlpineJsUrl() string {
431
- return "/gromer/js/alpinejs@3.9.6.js"
432
- }
433
-
434
407
  func GetStylesUrl() string {
435
408
  sum := getSum("styles.css", func() [16]byte {
436
409
  return md5.Sum([]byte(gsx.GetStyles()))
readme.md CHANGED
@@ -116,50 +116,50 @@ And then run the gromer cli command annd it will generate the route handlers in
116
116
  package main
117
117
 
118
118
  import (
119
- "github.com/gorilla/mux"
119
+ "github.com/gorilla/mux"
120
- "github.com/pyros2097/gromer"
120
+ "github.com/pyros2097/gromer"
121
+ "github.com/pyros2097/gromer/assets"
122
+ "github.com/pyros2097/gromer/gsx"
121
- "github.com/rs/zerolog/log"
123
+ "github.com/rs/zerolog/log"
122
- "gocloud.dev/server"
124
+ "gocloud.dev/server"
123
-
125
+
124
- "github.com/pyros2097/gromer/_example/assets"
126
+ "github.com/pyros2097/gromer/_example/assets"
125
- "github.com/pyros2097/gromer/_example/components"
127
+ "github.com/pyros2097/gromer/_example/components"
126
- "github.com/pyros2097/gromer/_example/containers"
128
+ "github.com/pyros2097/gromer/_example/containers"
127
- "github.com/pyros2097/gromer/_example/routes/404"
129
+ "github.com/pyros2097/gromer/_example/routes/404"
128
- "github.com/pyros2097/gromer/_example/routes"
130
+ "github.com/pyros2097/gromer/_example/routes"
129
- "github.com/pyros2097/gromer/_example/routes/about"
131
+ "github.com/pyros2097/gromer/_example/routes/about"
130
- "github.com/pyros2097/gromer/gsx"
132
+
131
-
132
133
  )
133
134
 
134
135
  func init() {
135
- gsx.RegisterComponent(components.Todo, "todo")
136
+ gsx.RegisterComponent(components.Todo, "todo")
136
- gsx.RegisterComponent(components.Checkbox, "value")
137
+ gsx.RegisterComponent(components.Checkbox, "value")
137
-
138
- gsx.RegisterComponent(containers.TodoCount, "filter")
138
+ gsx.RegisterComponent(containers.TodoCount, "filter")
139
- gsx.RegisterComponent(containers.TodoList, "page", "filter")
139
+ gsx.RegisterComponent(containers.TodoList, "page", "filter")
140
- gromer.RegisterAssets(assets.FS)
141
140
  }
142
141
 
143
142
  func main() {
144
- baseRouter := mux.NewRouter()
143
+ baseRouter := mux.NewRouter()
145
- baseRouter.Use(gromer.LogMiddleware)
144
+ baseRouter.Use(gromer.LogMiddleware)
146
- baseRouter.NotFoundHandler = gromer.StatusHandler(not_found_404.GET)
145
+ baseRouter.NotFoundHandler = gromer.StatusHandler(not_found_404.GET)
147
-
146
+
148
- staticRouter := baseRouter.NewRoute().Subrouter()
147
+ staticRouter := baseRouter.NewRoute().Subrouter()
149
- staticRouter.Use(gromer.CacheMiddleware)
148
+ staticRouter.Use(gromer.CacheMiddleware)
150
- gromer.GromerRoute(staticRouter, "/gromer/")
149
+ gromer.StaticRoute(staticRouter, "/gromer/", gromer_assets.FS)
151
- gromer.StaticRoute(staticRouter, "/assets/")
150
+ gromer.StaticRoute(staticRouter, "/assets/", assets.FS)
152
- gromer.StylesRoute(staticRouter, "/styles.css")
151
+ gromer.StylesRoute(staticRouter, "/styles.css")
153
-
152
+
154
- pageRouter := baseRouter.NewRoute().Subrouter()
153
+ pageRouter := baseRouter.NewRoute().Subrouter()
155
- gromer.Handle(pageRouter, "GET", "/", routes.GET)
154
+ gromer.Handle(pageRouter, "GET", "/", routes.GET)
156
- gromer.Handle(pageRouter, "POST", "/", routes.POST)
155
+ gromer.Handle(pageRouter, "POST", "/", routes.POST)
157
- gromer.Handle(pageRouter, "GET", "/about", about.GET)
156
+ gromer.Handle(pageRouter, "GET", "/about", about.GET)
157
+
158
- log.Info().Msg("http server listening on http://localhost:3000")
158
+ log.Info().Msg("http server listening on http://localhost:3000")
159
- srv := server.New(baseRouter, nil)
159
+ srv := server.New(baseRouter, nil)
160
- if err := srv.ListenAndServe(":3000"); err != nil {
160
+ if err := srv.ListenAndServe(":3000"); err != nil {
161
- log.Fatal().Stack().Err(err).Msg("failed to listen")
161
+ log.Fatal().Stack().Err(err).Msg("failed to listen")
162
- }
162
+ }
163
163
  }
164
164
  ```
165
165