~repos /gromer
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.
24b34a7c
—
Peter John 4 years ago
add validation errors
- go.mod +2 -0
- go.sum +18 -0
- hooks_test.go +7 -5
- html_test.go +3 -2
- http.go +24 -3
go.mod
CHANGED
|
@@ -8,9 +8,11 @@ require (
|
|
|
8
8
|
github.com/bradleyjkemp/cupaloy v2.3.0+incompatible
|
|
9
9
|
github.com/fatih/color v1.13.0
|
|
10
10
|
github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf
|
|
11
|
+
github.com/go-playground/validator/v10 v10.9.0 // indirect
|
|
11
12
|
github.com/gobuffalo/velvet v0.0.0-20170320144106-d97471bf5d8f
|
|
12
13
|
github.com/google/uuid v1.3.0
|
|
13
14
|
github.com/gorilla/mux v1.8.0
|
|
15
|
+
github.com/iancoleman/strcase v0.2.0 // indirect
|
|
14
16
|
github.com/lib/pq v1.10.4
|
|
15
17
|
github.com/markbates/inflect v1.0.4
|
|
16
18
|
github.com/microcosm-cc/bluemonday v1.0.15 // indirect
|
go.sum
CHANGED
|
@@ -136,6 +136,7 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht
|
|
|
136
136
|
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
|
137
137
|
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
|
138
138
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
|
139
|
+
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
|
139
140
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
140
141
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
141
142
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
@@ -168,8 +169,14 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
|
|
|
168
169
|
github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
|
169
170
|
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
|
170
171
|
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
|
172
|
+
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
|
|
173
|
+
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
|
171
174
|
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
|
175
|
+
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
|
176
|
+
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
|
172
177
|
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
|
178
|
+
github.com/go-playground/validator/v10 v10.9.0 h1:NgTtmN58D0m8+UuxtYmGztBJB7VnPgjj221I1QHci2A=
|
|
179
|
+
github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
|
173
180
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
|
174
181
|
github.com/gobuffalo/envy v1.6.5 h1:X3is06x7v0nW2xiy2yFbbIjwHz57CD6z6MkvqULTCm8=
|
|
175
182
|
github.com/gobuffalo/envy v1.6.5/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ=
|
|
@@ -273,6 +280,8 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
|
|
|
273
280
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
|
274
281
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
|
275
282
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
|
283
|
+
github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0=
|
|
284
|
+
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
|
276
285
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
|
277
286
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
|
278
287
|
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
|
@@ -289,10 +298,14 @@ github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47e
|
|
|
289
298
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
|
290
299
|
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
|
291
300
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
|
301
|
+
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
|
292
302
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|
293
303
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|
294
304
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
305
|
+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
|
295
306
|
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
|
307
|
+
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
|
308
|
+
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
|
296
309
|
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
|
297
310
|
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
|
|
298
311
|
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
|
@@ -311,6 +324,7 @@ github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
|
|
|
311
324
|
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
|
312
325
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
|
313
326
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
|
327
|
+
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
|
314
328
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
315
329
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|
316
330
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
@@ -319,6 +333,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
|
|
319
333
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
|
320
334
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
|
321
335
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
|
336
|
+
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
|
337
|
+
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
|
322
338
|
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
|
323
339
|
github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE=
|
|
324
340
|
github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo=
|
|
@@ -395,6 +411,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
|
|
395
411
|
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
|
396
412
|
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
|
397
413
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
|
414
|
+
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
|
415
|
+
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
|
|
398
416
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
|
399
417
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
|
400
418
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
hooks_test.go
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package gromer
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
|
+
"context"
|
|
4
5
|
"testing"
|
|
5
6
|
|
|
6
7
|
. "github.com/franela/goblin"
|
|
@@ -9,13 +10,14 @@ import (
|
|
|
9
10
|
func TestHooks(t *testing.T) {
|
|
10
11
|
g := Goblin(t)
|
|
11
12
|
g.Describe("useState", func() {
|
|
12
|
-
ctx :=
|
|
13
|
+
ctx := WithState(context.Background())
|
|
14
|
+
stateCtx := getState(ctx)
|
|
13
15
|
getValue, setValue := UseState(ctx, 12)
|
|
14
16
|
|
|
15
17
|
g.It("should be initialized ", func() {
|
|
16
|
-
g.Assert(1).Equal(
|
|
18
|
+
g.Assert(1).Equal(stateCtx.index)
|
|
17
|
-
g.Assert(1).Equal(len(
|
|
19
|
+
g.Assert(1).Equal(len(stateCtx.datas))
|
|
18
|
-
g.Assert(
|
|
20
|
+
g.Assert(stateCtx.datas[0]).Equal(12)
|
|
19
21
|
})
|
|
20
22
|
|
|
21
23
|
g.It("should get value ", func() {
|
|
@@ -24,7 +26,7 @@ func TestHooks(t *testing.T) {
|
|
|
24
26
|
|
|
25
27
|
g.It("should set value", func() {
|
|
26
28
|
setValue(15)
|
|
27
|
-
g.Assert(
|
|
29
|
+
g.Assert(stateCtx.datas[0]).Equal(15)
|
|
28
30
|
g.Assert(getValue()).Equal(15)
|
|
29
31
|
})
|
|
30
32
|
})
|
html_test.go
CHANGED
|
@@ -2,6 +2,7 @@ package gromer
|
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
4
|
"bytes"
|
|
5
|
+
"context"
|
|
5
6
|
"strconv"
|
|
6
7
|
"testing"
|
|
7
8
|
|
|
@@ -27,7 +28,7 @@ func Col(uis ...interface{}) *Element {
|
|
|
27
28
|
return NewElement("div", false, append([]interface{}{Css("flex flex-col justify-center items-center")}, uis...)...)
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
func Counter(c
|
|
31
|
+
func Counter(c context.Context, start int) *Element {
|
|
31
32
|
count, setCount := UseState(c, start)
|
|
32
33
|
increment := func() {
|
|
33
34
|
setCount(count().(int) + 1)
|
|
@@ -80,7 +81,7 @@ func TestHtml(t *testing.T) {
|
|
|
80
81
|
g := Goblin(t)
|
|
81
82
|
g.Describe("Html", func() {
|
|
82
83
|
g.It("should match snapshot", func() {
|
|
83
|
-
ctx :=
|
|
84
|
+
ctx := WithState(context.Background())
|
|
84
85
|
b := bytes.NewBuffer(nil)
|
|
85
86
|
p := Html(
|
|
86
87
|
Head(
|
http.go
CHANGED
|
@@ -10,7 +10,9 @@ import (
|
|
|
10
10
|
"strings"
|
|
11
11
|
|
|
12
12
|
"github.com/fatih/color"
|
|
13
|
+
"github.com/go-playground/validator/v10"
|
|
13
14
|
"github.com/gorilla/mux"
|
|
15
|
+
"github.com/iancoleman/strcase"
|
|
14
16
|
"github.com/rs/zerolog"
|
|
15
17
|
"github.com/rs/zerolog/log"
|
|
16
18
|
)
|
|
@@ -21,11 +23,30 @@ func init() {
|
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
func RespondError(w http.ResponseWriter, status int, err error) {
|
|
24
|
-
w.WriteHeader(status)
|
|
25
26
|
w.Header().Set("Content-Type", "application/json")
|
|
27
|
+
w.WriteHeader(status) // always write status last
|
|
26
|
-
|
|
28
|
+
merror := map[string]interface{}{
|
|
27
29
|
"error": err.Error(),
|
|
28
|
-
}
|
|
30
|
+
}
|
|
31
|
+
validationErrors, ok := err.(validator.ValidationErrors)
|
|
32
|
+
if ok {
|
|
33
|
+
emap := map[string]string{}
|
|
34
|
+
for _, e := range validationErrors {
|
|
35
|
+
parts := strings.Split(e.StructNamespace(), ".")
|
|
36
|
+
lowerParts := []string{}
|
|
37
|
+
for _, p := range parts[1:] {
|
|
38
|
+
lowerParts = append(lowerParts, strcase.ToLowerCamel(p))
|
|
39
|
+
}
|
|
40
|
+
k := strings.Join(lowerParts, ".")
|
|
41
|
+
if e.Tag() == "required" {
|
|
42
|
+
emap[k] = "is required"
|
|
43
|
+
} else {
|
|
44
|
+
emap[k] = e.Error()
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
merror["error"] = emap
|
|
48
|
+
}
|
|
49
|
+
data, _ := json.Marshal(merror)
|
|
29
50
|
w.Write(data)
|
|
30
51
|
}
|
|
31
52
|
|