diff --git a/README-en.md b/README-en.md index 01bf6b0..8573a0c 100644 --- a/README-en.md +++ b/README-en.md @@ -7,9 +7,60 @@ Mir is a toolkit to develop RESTful API backend service like develop service of ![](docs/.assets/mir-arc-adapter.png) - ## Tutorials + ### Tutorials +* Generate a simple template project +```bash +% go get github.com/alimy/mir/mirc/v3@latest +% mirc new -h +create template project + +Usage: + mirc new [flags] + +Flags: + -d, --dst string genereted destination target directory (default ".") + -h, --help help for new + --mir string mir replace package name or place + -p, --pkg string project's package name (default "github.com/alimy/mir-example") + -s, --style string generated engine style eg: gin,chi,mux,hertz,echo,iris,fiber,fiber-v2,macaron,httprouter (default "gin") + +% mirc new -d example +% tree example +example +. +|-- Makefile +|-- README.md +|-- go.mod +|-- go.sum +|-- main.go +|-- mirc +| |-- auto +| | `-- api +| | |-- site.go +| | |-- v1 +| | | `-- site.go +| | `-- v2 +| | `-- site.go +| |-- main.go +| `-- routes +| |-- site.go +| |-- v1 +| | `-- site.go +| `-- v2 +| `-- site.go +`-- servants + |-- core.go + |-- servants.go + |-- site.go + |-- site_v1.go + `-- site_v2.go + +% cd example +% make generate +% make build +``` - RESTful API define: +* RESTful API define: ```go // file: mirc/routes.go @@ -42,7 +93,7 @@ type User struct { } ``` -Stub source code generatee automatic: +* Stub source code generatee automatic: ```go // file: mirc/auto/api/routes.go @@ -111,6 +162,12 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { // register routes info to router router.Handle("POST", "/login/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + req, err := b.BindLogin(c) if err != nil { r.RenderLogin(c, nil, err) @@ -119,6 +176,12 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { r.RenderLogin(c, resp, err) }) router.Handle("POST", "/logout/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + r.RenderLogout(c, s.Logout(c)) }) } @@ -157,7 +220,7 @@ func (r UnimplementedUserRender) mustEmbedUnimplementedUserRender() {} ``` -API interface implement: +* API interface implement: ```go // file: servants/user.go @@ -215,7 +278,7 @@ func renderAny(c *gin.Context, data any, err mir.Error) { } ``` -Service register: +* Service register: ```go // file: servants/servants.go @@ -234,6 +297,6 @@ func RegisterServants(e *gin.Engine) { } ``` -## Projects that used [go-mir](https://github.com/alimy/mir) +### Projects that used [go-mir](https://github.com/alimy/mir) * [examples](examples) [go-mir](https://github.com/alimy/mir)'s demo example to describe how to use [Mir](https://github.com/alimy/mir) to develop RESTful API backend service quickly. diff --git a/README.md b/README.md index 5513f7a..e4db87b 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,59 @@ Mir 是一套提供类似gRPC服务开发体验的快速开发RESTful API后端 ![](docs/.assets/mir-arc-adapter.png) ## 使用说明 - - RESTful接口定义: +* 生成样板项目 +```bash +% go get github.com/alimy/mir/mirc/v3@latest +% mirc new -h +create template project + +Usage: + mirc new [flags] + +Flags: + -d, --dst string genereted destination target directory (default ".") + -h, --help help for new + --mir string mir replace package name or place + -p, --pkg string project's package name (default "github.com/alimy/mir-example") + -s, --style string generated engine style eg: gin,chi,mux,hertz,echo,iris,fiber,fiber-v2,macaron,httprouter (default "gin") + +% mirc new -d example +% tree example +example +. +|-- Makefile +|-- README.md +|-- go.mod +|-- go.sum +|-- main.go +|-- mirc +| |-- auto +| | `-- api +| | |-- site.go +| | |-- v1 +| | | `-- site.go +| | `-- v2 +| | `-- site.go +| |-- main.go +| `-- routes +| |-- site.go +| |-- v1 +| | `-- site.go +| `-- v2 +| `-- site.go +`-- servants + |-- core.go + |-- servants.go + |-- site.go + |-- site_v1.go + `-- site_v2.go + +% cd example +% make generate +% make build +``` + + * RESTful接口定义: ```go // file: mirc/routes.go @@ -42,7 +93,7 @@ type User struct { } ``` -代码生成: +* 代码生成: ```go // file: mirc/auto/api/routes.go @@ -111,6 +162,12 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { // register routes info to router router.Handle("POST", "/login/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + req, err := b.BindLogin(c) if err != nil { r.RenderLogin(c, nil, err) @@ -119,6 +176,12 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { r.RenderLogin(c, resp, err) }) router.Handle("POST", "/logout/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + r.RenderLogout(c, s.Logout(c)) }) } @@ -157,7 +220,7 @@ func (r UnimplementedUserRender) mustEmbedUnimplementedUserRender() {} ``` -接口实现: +* 接口实现: ```go // file: servants/user.go @@ -215,7 +278,7 @@ func renderAny(c *gin.Context, data any, err mir.Error) { } ``` -服务注册: +* 服务注册: ```go // file: servants/servants.go @@ -234,7 +297,7 @@ func RegisterServants(e *gin.Engine) { } ``` -## 使用[go-mir](https://github.com/alimy/mir)的项目 +### 使用[go-mir](https://github.com/alimy/mir)的项目 * [examples](examples) [go-mir](https://github.com/alimy/mir)项目自带的demo,主要演示了如何使用[Mir](https://github.com/alimy/mir)快速进行RESTful API的后端开发. diff --git a/go.work b/go.work deleted file mode 100644 index 33fc66d..0000000 --- a/go.work +++ /dev/null @@ -1,8 +0,0 @@ -go 1.18 - -use ( - . - ./examples -) - -replace github.com/alimy/mir/v3 v3.0.0 => ./ diff --git a/go.work.sum b/go.work.sum deleted file mode 100644 index a95b913..0000000 --- a/go.work.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc= diff --git a/mirc/.gitignore b/mirc/.gitignore new file mode 100644 index 0000000..25df60e --- /dev/null +++ b/mirc/.gitignore @@ -0,0 +1,12 @@ +/mirc +/gin +/chi +/chi-v5 +/mux +/httprouter +/macaron +/echo +/iris +/fiber +/fiber-v2 +/release/* diff --git a/mirc/Makefile b/mirc/Makefile new file mode 100644 index 0000000..05e5a21 --- /dev/null +++ b/mirc/Makefile @@ -0,0 +1,78 @@ +GOFMT ?= gofmt -s -w +GOFILES := $(shell find . -name "*.go" -type f) + +LDFLAGS += -X "github.com/alimy/mir/mirc/v3/version.BuildTime=$(shell date -v+8H -u '+%Y-%m-%d %H:%M:%S %Z+8')" +LDFLAGS += -X "github.com/alimy/mir/mirc/v3/version.GitHash=$(shell git rev-parse --short=12 HEAD)" + +RELEASE_ROOT = release +RELEASE_LINUX_AMD64 = $(RELEASE_ROOT)/linux-amd64/mirc +RELEASE_DARWIN_AMD64 = $(RELEASE_ROOT)/darwin-amd64/mirc +RELEASE_DARWIN_ARM64 = $(RELEASE_ROOT)/darwin-arm64/mirc +RELEASE_WINDOWS_AMD64 = $(RELEASE_ROOT)/windows-amd64/mirc + +.PHONY: build +build: fmt + go build -ldflags '$(LDFLAGS)' -o mirc main.go + +.PHONY: release +release: linux-amd64 darwin-amd64 darwin-arm64 windows-x64 + cp ../LICENSE README.md $(RELEASE_LINUX_AMD64) + cp ../LICENSE README.md $(RELEASE_DARWIN_AMD64) + cp ../LICENSE README.md $(RELEASE_DARWIN_ARM64) + cp ../LICENSE README.md $(RELEASE_WINDOWS_AMD64) + cd $(RELEASE_LINUX_AMD64)/.. && rm -f *.zip && zip -r mirc-linux_amd64.zip mirc && cd - + cd $(RELEASE_DARWIN_AMD64)/.. && rm -f *.zip && zip -r mirc-darwin_amd64.zip mirc && cd - + cd $(RELEASE_DARWIN_ARM64)/.. && rm -f *.zip && zip -r mirc-darwin_arm64.zip mirc && cd - + cd $(RELEASE_WINDOWS_AMD64)/.. && rm -f *.zip && zip -r mirc-windows_amd64.zip mirc && cd - + +.PHONY: linux-amd64 +linux-amd64: + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '$(LDFLAGS)' -o $(RELEASE_LINUX_AMD64)/mirc main.go + +.PHONY: darwin-amd64 +darwin-amd64: + CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags '$(LDFLAGS)' -o $(RELEASE_DARWIN_AMD64)/mirc main.go + +.PHONY: darwin-arm64 +darwin-arm64: + CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags '$(LDFLAGS)' -o $(RELEASE_DARWIN_ARM64)/mirc main.go + +.PHONY: windows-x64 +windows-x64: + CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags '$(LDFLAGS)' -o $(RELEASE_WINDOWS_AMD64)/mirc main.go + +.PHONY: fmt +fmt: + $(GOFMT) $(GOFILES) + +.PHONY: check-all +check-all: check-debug-all + +STYLES = chi hertz echo fiber fiber-v2 gin httprouter iris macaron mux +.PHONY: check-debug-all +check-debug-all: + @for target in $(STYLES); do \ + echo "==========[ processing $$target ]=========="; \ + rm -rf $$target; \ + ./mirc new --mir ../../ --style $$target --dst $$target; \ + cd $$target; \ + make mod-tidy; \ + cd -; \ + echo ""; \ + done + +.PHONY: check-release-all +check-release-all: + @for target in $(STYLES); do \ + echo "==========[ processing $$target ]=========="; \ + rm -rf $$target; \ + ./mirc new --style $$target --dst $$target; \ + cd $$target; \ + make mod-tidy; \ + cd -; \ + echo ""; \ + done + +.PHONY: clean +clean: + -rm -rf $(STYLES) diff --git a/mirc/README.md b/mirc/README.md new file mode 100644 index 0000000..f8e14ae --- /dev/null +++ b/mirc/README.md @@ -0,0 +1,54 @@ +## Mirc +Mir's help toolkit + +### Usage +```bash +% go get github.com/alimy/mir/mirc/v3@latest +% mirc new -h +create template project + +Usage: + mirc new [flags] + +Flags: + -d, --dst string genereted destination target directory (default ".") + -h, --help help for new + --mir string mir replace package name or place + -p, --pkg string project's package name (default "github.com/alimy/mir-example") + -s, --style string generated engine style eg: gin,chi,mux,hertz,echo,iris,fiber,fiber-v2,macaron,httprouter (default "gin") + +% mirc new -d example +% tree example +example +. +|-- Makefile +|-- README.md +|-- go.mod +|-- go.sum +|-- main.go +|-- mirc +| |-- auto +| | `-- api +| | |-- site.go +| | |-- v1 +| | | `-- site.go +| | `-- v2 +| | `-- site.go +| |-- main.go +| `-- routes +| |-- site.go +| |-- v1 +| | `-- site.go +| `-- v2 +| `-- site.go +`-- servants + |-- core.go + |-- servants.go + |-- site.go + |-- site_v1.go + `-- site_v2.go + +% cd example +% make generate +% make build +``` diff --git a/mirc/build/go2tmpl.sh b/mirc/build/go2tmpl.sh new file mode 100755 index 0000000..3208a27 --- /dev/null +++ b/mirc/build/go2tmpl.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +GOFILES=$(find . -type f) + +for filename in $GOFILES +do + mv ${filename} ${filename}.tmpl +done \ No newline at end of file diff --git a/mirc/cmd/new.go b/mirc/cmd/new.go new file mode 100644 index 0000000..8b69f16 --- /dev/null +++ b/mirc/cmd/new.go @@ -0,0 +1,104 @@ +// Copyright 2020 Michael Li . All rights reserved. +// Use of this source code is governed by Apache License 2.0 that +// can be found in the LICENSE file. + +package cmd + +import ( + "fmt" + "log" + "os" + "path/filepath" + "strings" + + "github.com/alimy/mir/mirc/v3/templates" + "github.com/spf13/cobra" +) + +var ( + dstPath string + pkgName string + style []string + mirPkgName string + mirVersion string + engVersion string +) + +func init() { + newCmd := &cobra.Command{ + Use: "new", + Short: "create template project", + Long: "create template project", + Run: newRun, + } + + // parse flags for agentCmd + newCmd.Flags().StringVarP(&dstPath, "dst", "d", ".", "genereted destination target directory") + newCmd.Flags().StringVarP(&pkgName, "pkg", "p", "github.com/alimy/mir-example", "project's package name") + newCmd.Flags().StringSliceVarP(&style, "style", "s", []string{"gin"}, "generated engine style eg: gin,chi,mux,hertz,echo,iris,fiber,fiber-v2,macaron,httprouter") + newCmd.Flags().StringVar(&mirPkgName, "mir", "", "mir replace package name or place") + newCmd.Flags().StringVar(&mirVersion, "mir-version", "", "set mir version") + newCmd.Flags().StringVar(&engVersion, "engine-version", "", "set engine version") + + // register agentCmd as sub-command + register(newCmd) +} + +// newRun run new command +func newRun(_cmd *cobra.Command, _args []string) { + path, err := filepath.EvalSymlinks(dstPath) + if err != nil { + if os.IsNotExist(err) { + if !filepath.IsAbs(dstPath) { + cwd, err := os.Getwd() + if err != nil { + log.Fatal(err) + } + path = filepath.Join(cwd, dstPath) + } else { + path = dstPath + } + } else { + log.Fatal(err) + } + } + ctx := &templates.TmplCtx{ + PkgName: pkgName, + MirPkgName: mirPkgName, + MirVersion: mirVersion, + EngVersion: engVersion, + } + if err = genProject(ctx, path, style); err != nil { + log.Fatal(err) + } +} + +func genProject(ctx *templates.TmplCtx, dstPath string, style []string) error { + var ( + err error + filePath, dirPath string + file *os.File + ) + + t, err := templates.NewTemplate(style) + if err != nil { + return fmt.Errorf("not exist style for %s: %w", strings.Join(style, ":"), err) + } + + for _, tmpl := range t.Templates() { + filePath = filepath.Join(dstPath, tmpl.Name()) + dirPath = filepath.Dir(filePath) + if err = os.MkdirAll(dirPath, 0755); err != nil { + break + } + file, err = os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + break + } + if err = tmpl.Execute(file, ctx); err != nil { + break + } + file.Close() + } + return err +} diff --git a/mirc/cmd/root.go b/mirc/cmd/root.go new file mode 100644 index 0000000..3776f36 --- /dev/null +++ b/mirc/cmd/root.go @@ -0,0 +1,34 @@ +// Copyright 2020 Michael Li . All rights reserved. +// Use of this source code is governed by Apache License 2.0 that +// can be found in the LICENSE file. + +package cmd + +import "github.com/spf13/cobra" + +var ( + rootCmd = &cobra.Command{ + Use: "mir", + Short: "mir help toolkit", + Long: `mir help toolkit`, + } +) + +// Setup set root command name,short-describe, long-describe +// return &cobra.Command to custom other options +func Setup(use, short, long string) *cobra.Command { + rootCmd.Use = use + rootCmd.Short = short + rootCmd.Long = long + return rootCmd +} + +// register add sub-command +func register(cmd *cobra.Command) { + rootCmd.AddCommand(cmd) +} + +// Execute start application +func Execute() { + rootCmd.Execute() +} diff --git a/mirc/cmd/styles.go b/mirc/cmd/styles.go new file mode 100644 index 0000000..cd53779 --- /dev/null +++ b/mirc/cmd/styles.go @@ -0,0 +1,28 @@ +// Copyright 2020 Michael Li . All rights reserved. +// Use of this source code is governed by Apache License 2.0 that +// can be found in the LICENSE file. + +package cmd + +import ( + "fmt" + "strings" + + "github.com/alimy/mir/mirc/v3/templates" + "github.com/spf13/cobra" +) + +func init() { + stylesCmd := &cobra.Command{ + Use: "styles", + Short: "list all suported style that engine temeplate code generate", + Long: "list all suported style that engine temeplate code generate", + Run: stylesRun, + } + register(stylesCmd) +} + +// stylesRun run styles command +func stylesRun(_cmd *cobra.Command, _args []string) { + fmt.Println(strings.Join(templates.Styles(), " ")) +} diff --git a/mirc/cmd/version.go b/mirc/cmd/version.go new file mode 100644 index 0000000..97f9d38 --- /dev/null +++ b/mirc/cmd/version.go @@ -0,0 +1,31 @@ +// Copyright 2020 Michael Li . All rights reserved. +// Use of this source code is governed by Apache License 2.0 that +// can be found in the LICENSE file. + +package cmd + +import ( + "fmt" + + "github.com/alimy/mir/mirc/v3/version" + "github.com/spf13/cobra" +) + +func init() { + versionCmd := &cobra.Command{ + Use: "version", + Short: "show version information", + Long: "show version information", + Run: versionRun, + } + register(versionCmd) +} + +func versionRun(_cmd *cobra.Command, _args []string) { + if version.BuildTime == "" || version.GitHash == "" { + fmt.Printf("v%s\n", version.AppVer) + } else { + fmt.Printf("v%s\nBuildTime: %s\nGitHash: %s\n", + version.AppVer, version.BuildTime, version.GitHash) + } +} diff --git a/mirc/go.mod b/mirc/go.mod new file mode 100644 index 0000000..b4e56ee --- /dev/null +++ b/mirc/go.mod @@ -0,0 +1,9 @@ +module github.com/alimy/mir/mirc/v3 + +go 1.16 + +require ( + github.com/Masterminds/semver/v3 v3.1.1 + github.com/alimy/embedx v0.6.1 + github.com/spf13/cobra v1.1.1 +) diff --git a/mirc/go.sum b/mirc/go.sum new file mode 100644 index 0000000..4bd3ad6 --- /dev/null +++ b/mirc/go.sum @@ -0,0 +1,290 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alimy/embedx v0.6.1 h1:NrC73zd3gq18XG9tLoEJLF9TUlqMz2xC3OsSC3ApWHM= +github.com/alimy/embedx v0.6.1/go.mod h1:oEtAmXt6aGR47gKNYKtuMe/n49XN7iQAF3tr1DuEJCg= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= +github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/mirc/main.go b/mirc/main.go new file mode 100644 index 0000000..11b222a --- /dev/null +++ b/mirc/main.go @@ -0,0 +1,21 @@ +// Copyright 2020 Michael Li . All rights reserved. +// Use of this source code is governed by Apache License 2.0 that +// can be found in the LICENSE file. + +package main + +import ( + "github.com/alimy/mir/mirc/v3/cmd" +) + +func main() { + // setup root cli command of application + cmd.Setup( + "mirc", // command name + "mir help toolkit", // command short describe + "mir help tookit", // command long describe + ) + + // execute start application + cmd.Execute() +} diff --git a/mirc/templates/chi/.gitignore.tmpl b/mirc/templates/chi/.gitignore.tmpl new file mode 100644 index 0000000..96ffcd3 --- /dev/null +++ b/mirc/templates/chi/.gitignore.tmpl @@ -0,0 +1,25 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +coverage.out +count.out +test +profile.out +tmp.out + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# GoLand project files +.idea/ +*.iml + +# VS Code +.vscode diff --git a/mirc/templates/chi/Makefile.tmpl b/mirc/templates/chi/Makefile.tmpl new file mode 100644 index 0000000..9616a42 --- /dev/null +++ b/mirc/templates/chi/Makefile.tmpl @@ -0,0 +1,27 @@ +GOFMT ?= gofmt -s -w +GOFILES := $(shell find . -name "*.go" -type f) + +.PHONY: default +default: run + +.PHONY: build +build: fmt + go build -o mir-examples main.go + +.PHONY: build +run: fmt + go run main.go + +.PHONY: mod-tidy +mod-tidy: + @go mod download + @go mod tidy + +.PHONY: generate +generate: + @go generate mirc/main.go + @$(GOFMT) ./ + +.PHONY: fmt +fmt: + $(GOFMT) $(GOFILES) diff --git a/mirc/templates/chi/README.md.tmpl b/mirc/templates/chi/README.md.tmpl new file mode 100644 index 0000000..5bf9de3 --- /dev/null +++ b/mirc/templates/chi/README.md.tmpl @@ -0,0 +1,8 @@ +## mir-examples +just a simple mir's examples for explain how to use mir in your project. + +#### Usage +```bash +% make generate +% make build +``` diff --git a/mirc/templates/chi/go.mod.tmpl b/mirc/templates/chi/go.mod.tmpl new file mode 100644 index 0000000..46aba0b --- /dev/null +++ b/mirc/templates/chi/go.mod.tmpl @@ -0,0 +1,13 @@ +module {{ .PkgName }} + +go 1.18 + +require ( + github.com/alimy/mir/v3 v3.0.0 + github.com/go-chi/chi/v5 v5.0.8 +) +{{if notEmptyStr .MirPkgName }} +replace ( + github.com/alimy/mir/v3 => {{ .MirPkgName }} +) +{{end}} diff --git a/mirc/templates/chi/go.sum.tmpl b/mirc/templates/chi/go.sum.tmpl new file mode 100644 index 0000000..2ad8d91 --- /dev/null +++ b/mirc/templates/chi/go.sum.tmpl @@ -0,0 +1,2 @@ +github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= +github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= diff --git a/mirc/templates/chi/main.go.tmpl b/mirc/templates/chi/main.go.tmpl new file mode 100644 index 0000000..af029ba --- /dev/null +++ b/mirc/templates/chi/main.go.tmpl @@ -0,0 +1,21 @@ +package main + +import ( + "log" + "net/http" + + "{{ .PkgName }}/servants" + "github.com/go-chi/chi/v5" +) + +func main() { + r := chi.NewRouter() + + // register servants to chi + servants.RegisterServants(r) + + // start servant service + if err := http.ListenAndServe(":8080", r); err != nil { + log.Fatal(err) + } +} diff --git a/mirc/templates/chi/mirc/auto/api/site.go.tmpl b/mirc/templates/chi/mirc/auto/api/site.go.tmpl new file mode 100644 index 0000000..12180b2 --- /dev/null +++ b/mirc/templates/chi/mirc/auto/api/site.go.tmpl @@ -0,0 +1,283 @@ +// Code generated by go-mir. DO NOT EDIT. + +package api + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/go-chi/chi/v5" +) + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + // Chain provide middlewares for chi + Chain() chi.Middlewares + + Logout(*LogoutReq) mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogout(*http.Request) (*LogoutReq, mir.Error) + BindLogin(*http.Request) (*LoginReq, mir.Error) + BindPrevTweets(*http.Request) (*TweetsReq, mir.Error) + BindNextTweets(*http.Request) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(http.ResponseWriter, mir.Error) + RenderLogin(http.ResponseWriter, *LoginResp, mir.Error) + RenderPrevTweets(http.ResponseWriter, *TweetsResp, mir.Error) + RenderNextTweets(http.ResponseWriter, *TweetsResp, mir.Error) + RenderArticles(http.ResponseWriter, mir.Error) + RenderIndex(http.ResponseWriter, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to chi +func RegisterSiteServant(e chi.Router, s Site, b SiteBinding, r SiteRender) { + router := e + + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.MethodFunc("POST", "/user/logout/", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindLogout(hr) + if err != nil { + r.RenderLogout(rw, err) + return + } + r.RenderLogout(rw, s.Logout(req)) + }) + + router.MethodFunc("POST", "/user/login/", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindLogin(hr) + if err != nil { + r.RenderLogin(rw, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(rw, resp, err) + }) + + { + h := func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindPrevTweets(hr) + if err != nil { + r.RenderPrevTweets(rw, nil, err) + return + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(rw, resp, err) + } + router.MethodFunc("POST", "/tweets/prev", h) + router.MethodFunc("HEAD", "/tweets/prev", h) + router.MethodFunc("GET", "/tweets/prev", h) + } + + router.HandleFunc("/tweets/next", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindNextTweets(hr) + if err != nil { + r.RenderNextTweets(rw, nil, err) + return + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(rw, resp, err) + }) + + router.MethodFunc("GET", "/articles/{category}/{id:[0-9]+}", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderArticles(rw, s.Articles()) + }) + + router.MethodFunc("GET", "/index/", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderIndex(rw, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() chi.Middlewares { + return nil +} + +func (UnimplementedSiteServant) Logout(req *LogoutReq) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(http.ResponseWriter, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(w http.ResponseWriter, data *LoginResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(w http.ResponseWriter, data *TweetsResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(w http.ResponseWriter, data *TweetsResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(*http.Request, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogout(r *http.Request) (*LogoutReq, mir.Error) { + obj := new(LogoutReq) + err := b.BindAny(r, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindLogin(r *http.Request) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(r, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(r *http.Request) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(r, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(r *http.Request) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(r, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/chi/mirc/auto/api/v1/site.go.tmpl b/mirc/templates/chi/mirc/auto/api/v1/site.go.tmpl new file mode 100644 index 0000000..ea8e38b --- /dev/null +++ b/mirc/templates/chi/mirc/auto/api/v1/site.go.tmpl @@ -0,0 +1,97 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/go-chi/chi/v5" +) + +type Site interface { + // Chain provide middlewares for chi + Chain() chi.Middlewares + + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteRender interface { + RenderArticles(http.ResponseWriter, mir.Error) + RenderIndex(http.ResponseWriter, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to chi +func RegisterSiteServant(e chi.Router, s Site, r SiteRender) { + router := chi.NewRouter() + e.Mount("/v1", router) + + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + { + h := func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderArticles(rw, s.Articles()) + } + router.MethodFunc("POST", "/articles/:category/", h) + router.MethodFunc("GET", "/articles/:category/", h) + router.MethodFunc("HEAD", "/articles/:category/", h) + } + + router.MethodFunc("GET", "/index/", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderIndex(rw, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() chi.Middlewares { + return nil +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(http.ResponseWriter, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderArticles(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} diff --git a/mirc/templates/chi/mirc/auto/api/v2/site.go.tmpl b/mirc/templates/chi/mirc/auto/api/v2/site.go.tmpl new file mode 100644 index 0000000..5569d38 --- /dev/null +++ b/mirc/templates/chi/mirc/auto/api/v2/site.go.tmpl @@ -0,0 +1,256 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v2 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/go-chi/chi/v5" +) + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + Logout() mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogin(*http.Request) (*LoginReq, mir.Error) + BindPrevTweets(*http.Request) (*TweetsReq, mir.Error) + BindNextTweets(*http.Request) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(http.ResponseWriter, mir.Error) + RenderLogin(http.ResponseWriter, *LoginResp, mir.Error) + RenderPrevTweets(http.ResponseWriter, *TweetsResp, mir.Error) + RenderNextTweets(http.ResponseWriter, *TweetsResp, mir.Error) + RenderArticles(http.ResponseWriter, mir.Error) + RenderIndex(http.ResponseWriter, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to chi +func RegisterSiteServant(e chi.Router, s Site, b SiteBinding, r SiteRender) { + router := chi.NewRouter() + e.Mount("/v2", router) + + // register routes info to router + router.MethodFunc("POST", "/user/logout/", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderLogout(rw, s.Logout()) + }) + + router.MethodFunc("POST", "/user/login/", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindLogin(hr) + if err != nil { + r.RenderLogin(rw, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(rw, resp, err) + }) + + { + h := func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindPrevTweets(hr) + if err != nil { + r.RenderPrevTweets(rw, nil, err) + return + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(rw, resp, err) + } + router.MethodFunc("HEAD", "/tweets/prev", h) + router.MethodFunc("GET", "/tweets/prev", h) + router.MethodFunc("POST", "/tweets/prev", h) + } + + router.HandleFunc("/tweets/next", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindNextTweets(hr) + if err != nil { + r.RenderNextTweets(rw, nil, err) + return + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(rw, resp, err) + }) + + router.MethodFunc("GET", "/articles/:category/", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderArticles(rw, s.Articles()) + }) + + router.MethodFunc("GET", "/index/", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderIndex(rw, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Logout() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(http.ResponseWriter, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(w http.ResponseWriter, data *LoginResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(w http.ResponseWriter, data *TweetsResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(w http.ResponseWriter, data *TweetsResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(*http.Request, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogin(r *http.Request) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(r, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(r *http.Request) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(r, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(r *http.Request) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(r, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/chi/mirc/main.go.tmpl b/mirc/templates/chi/mirc/main.go.tmpl new file mode 100644 index 0000000..0430040 --- /dev/null +++ b/mirc/templates/chi/mirc/main.go.tmpl @@ -0,0 +1,26 @@ +package main + +import ( + "log" + + . "github.com/alimy/mir/v3/core" + . "github.com/alimy/mir/v3/engine" + + _ "{{ .PkgName }}/mirc/routes" + _ "{{ .PkgName }}/mirc/routes/v1" + _ "{{ .PkgName }}/mirc/routes/v2" +) + +//go:generate go run main.go +func main() { + log.Println("generate code start") + opts := Options{ + RunMode(InSerialMode), + GeneratorName(GeneratorChi), + SinkPath("auto"), + } + if err := Generate(opts); err != nil { + log.Fatal(err) + } + log.Println("generate code finish") +} diff --git a/mirc/templates/chi/mirc/routes/site.go.tmpl b/mirc/templates/chi/mirc/routes/site.go.tmpl new file mode 100644 index 0000000..711ff63 --- /dev/null +++ b/mirc/templates/chi/mirc/routes/site.go.tmpl @@ -0,0 +1,65 @@ +package routes + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site interface info +type Site struct { + Chain Chain `mir:"-"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/{category}/{id:[0-9]+}"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post, LogoutReq) `mir:"/user/logout/"` +} diff --git a/mirc/templates/chi/mirc/routes/v1/site.go.tmpl b/mirc/templates/chi/mirc/routes/v1/site.go.tmpl new file mode 100644 index 0000000..61ea076 --- /dev/null +++ b/mirc/templates/chi/mirc/routes/v1/site.go.tmpl @@ -0,0 +1,18 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +// Site site v1 interface info +type Site struct { + Chain Chain `mir:"-"` + Group Group `mir:"/v1"` + Index func(Get) `mir:"/index/"` + Articles func(Head, Get, Post) `mir:"/articles/:category/"` +} diff --git a/mirc/templates/chi/mirc/routes/v2/site.go.tmpl b/mirc/templates/chi/mirc/routes/v2/site.go.tmpl new file mode 100644 index 0000000..e9f91dd --- /dev/null +++ b/mirc/templates/chi/mirc/routes/v2/site.go.tmpl @@ -0,0 +1,60 @@ +package v2 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site v2 interface info +type Site struct { + Group Group `mir:"/v2"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/:category/"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post) `mir:"/user/logout/"` +} diff --git a/mirc/templates/chi/servants/core.go.tmpl b/mirc/templates/chi/servants/core.go.tmpl new file mode 100644 index 0000000..53379e6 --- /dev/null +++ b/mirc/templates/chi/servants/core.go.tmpl @@ -0,0 +1,17 @@ +package servants + +import ( + "errors" + "net/http" + + "github.com/alimy/mir/v3" +) + +func bindAny(r *http.Request, obj any) mir.Error { + return mir.NewError(http.StatusNotImplemented, errors.New("not implemented")) +} + +func renderAny(w http.ResponseWriter, data any, err mir.Error) { + w.WriteHeader(http.StatusNotImplemented) + w.Write([]byte("method not implemented")) +} diff --git a/mirc/templates/chi/servants/servants.go.tmpl b/mirc/templates/chi/servants/servants.go.tmpl new file mode 100644 index 0000000..96cf556 --- /dev/null +++ b/mirc/templates/chi/servants/servants.go.tmpl @@ -0,0 +1,15 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" + v1 "{{ .PkgName }}/mirc/auto/api/v1" + v2 "{{ .PkgName }}/mirc/auto/api/v2" + "github.com/go-chi/chi/v5" +) + +// RegisterServants register all the servants tor chi.Route +func RegisterServants(e chi.Router) { + api.RegisterSiteServant(e, newSiteSrv(), newSiteBinding(), newSiteRender()) + v1.RegisterSiteServant(e, newSiteV1Srv(), newSiteV1Render()) + v2.RegisterSiteServant(e, newSiteV2Srv(), newSiteV2Binding(), newSiteV2Render()) +} diff --git a/mirc/templates/chi/servants/site.go.tmpl b/mirc/templates/chi/servants/site.go.tmpl new file mode 100644 index 0000000..0912d5f --- /dev/null +++ b/mirc/templates/chi/servants/site.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" +) + +type siteSrv struct { + api.UnimplementedSiteServant +} + +type siteBinding struct { + *api.UnimplementedSiteBinding +} + +type siteRender struct { + *api.UnimplementedSiteRender +} + +func newSiteSrv() api.Site { + return &siteSrv{} +} + +func newSiteBinding() api.SiteBinding { + return &siteBinding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteRender() api.SiteRender { + return &siteRender{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/chi/servants/site_v1.go.tmpl b/mirc/templates/chi/servants/site_v1.go.tmpl new file mode 100644 index 0000000..98a0a8b --- /dev/null +++ b/mirc/templates/chi/servants/site_v1.go.tmpl @@ -0,0 +1,25 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v1" +) + +type siteV1Srv struct { + api.UnimplementedSiteServant +} + +type siteV1Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV1Srv() api.Site { + return &siteV1Srv{} +} + +func newSiteV1Render() api.SiteRender { + return &siteV1Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/chi/servants/site_v2.go.tmpl b/mirc/templates/chi/servants/site_v2.go.tmpl new file mode 100644 index 0000000..4fb76aa --- /dev/null +++ b/mirc/templates/chi/servants/site_v2.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v2" +) + +type siteV2Srv struct { + api.UnimplementedSiteServant +} + +type siteV2Binding struct { + *api.UnimplementedSiteBinding +} + +type siteV2Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV2Srv() api.Site { + return &siteV2Srv{} +} + +func newSiteV2Binding() api.SiteBinding { + return &siteV2Binding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteV2Render() api.SiteRender { + return &siteV2Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/echo/.gitignore.tmpl b/mirc/templates/echo/.gitignore.tmpl new file mode 100644 index 0000000..96ffcd3 --- /dev/null +++ b/mirc/templates/echo/.gitignore.tmpl @@ -0,0 +1,25 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +coverage.out +count.out +test +profile.out +tmp.out + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# GoLand project files +.idea/ +*.iml + +# VS Code +.vscode diff --git a/mirc/templates/echo/Makefile.tmpl b/mirc/templates/echo/Makefile.tmpl new file mode 100644 index 0000000..9616a42 --- /dev/null +++ b/mirc/templates/echo/Makefile.tmpl @@ -0,0 +1,27 @@ +GOFMT ?= gofmt -s -w +GOFILES := $(shell find . -name "*.go" -type f) + +.PHONY: default +default: run + +.PHONY: build +build: fmt + go build -o mir-examples main.go + +.PHONY: build +run: fmt + go run main.go + +.PHONY: mod-tidy +mod-tidy: + @go mod download + @go mod tidy + +.PHONY: generate +generate: + @go generate mirc/main.go + @$(GOFMT) ./ + +.PHONY: fmt +fmt: + $(GOFMT) $(GOFILES) diff --git a/mirc/templates/echo/README.md.tmpl b/mirc/templates/echo/README.md.tmpl new file mode 100644 index 0000000..5bf9de3 --- /dev/null +++ b/mirc/templates/echo/README.md.tmpl @@ -0,0 +1,8 @@ +## mir-examples +just a simple mir's examples for explain how to use mir in your project. + +#### Usage +```bash +% make generate +% make build +``` diff --git a/mirc/templates/echo/go.mod.tmpl b/mirc/templates/echo/go.mod.tmpl new file mode 100644 index 0000000..b94efd0 --- /dev/null +++ b/mirc/templates/echo/go.mod.tmpl @@ -0,0 +1,26 @@ +module {{ .PkgName }} + +go 1.18 + +require ( + github.com/alimy/mir/v3 v3.0.0 + github.com/labstack/echo/v4 v4.9.1 +) + +require ( + github.com/labstack/gommon v0.4.0 // indirect + github.com/mattn/go-colorable v0.1.11 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/stretchr/testify v1.7.1 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasttemplate v1.2.1 // indirect + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect + golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f // indirect + golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 // indirect + golang.org/x/text v0.3.7 // indirect +) +{{if notEmptyStr .MirPkgName }} +replace ( + github.com/alimy/mir/v3 => {{ .MirPkgName }} +) +{{end}} diff --git a/mirc/templates/echo/go.sum.tmpl b/mirc/templates/echo/go.sum.tmpl new file mode 100644 index 0000000..5b7462f --- /dev/null +++ b/mirc/templates/echo/go.sum.tmpl @@ -0,0 +1,36 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/labstack/echo/v4 v4.9.1 h1:GliPYSpzGKlyOhqIbG8nmHBo3i1saKWFOgh41AN3b+Y= +github.com/labstack/echo/v4 v4.9.1/go.mod h1:Pop5HLc+xoc4qhTZ1ip6C0RtP7Z+4VzRLWZZFKqbbjo= +github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= +github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= +github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/mirc/templates/echo/main.go.tmpl b/mirc/templates/echo/main.go.tmpl new file mode 100644 index 0000000..521236e --- /dev/null +++ b/mirc/templates/echo/main.go.tmpl @@ -0,0 +1,20 @@ +package main + +import ( + "log" + + "{{ .PkgName }}/servants" + "github.com/labstack/echo/v4" +) + +func main() { + e := echo.New() + + // register servants to echo + servants.RegisterServants(e) + + // start servant service + if err := e.Start(":4000"); err != nil { + log.Fatal(err) + } +} diff --git a/mirc/templates/echo/mirc/auto/api/site.go.tmpl b/mirc/templates/echo/mirc/auto/api/site.go.tmpl new file mode 100644 index 0000000..f34cd20 --- /dev/null +++ b/mirc/templates/echo/mirc/auto/api/site.go.tmpl @@ -0,0 +1,294 @@ +// Code generated by go-mir. DO NOT EDIT. + +package api + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/labstack/echo/v4" +) + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + // Chain provide handlers chain for echo + Chain() []echo.MiddlewareFunc + + Logout(*LogoutReq) mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogout(echo.Context) (*LogoutReq, mir.Error) + BindLogin(echo.Context) (*LoginReq, mir.Error) + BindPrevTweets(echo.Context) (*TweetsReq, mir.Error) + BindNextTweets(echo.Context) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(echo.Context, mir.Error) + RenderLogin(echo.Context, *LoginResp, mir.Error) + RenderPrevTweets(echo.Context, *TweetsResp, mir.Error) + RenderNextTweets(echo.Context, *TweetsResp, mir.Error) + RenderArticles(echo.Context, mir.Error) + RenderIndex(echo.Context, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to echo +func RegisterSiteServant(e *echo.Echo, s Site, b SiteBinding, r SiteRender) { + router := e + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Add("POST", "/user/logout/", func(c echo.Context) error { + ctx := c.Request().Context() + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + req, err := b.BindLogout(c) + if err != nil { + r.RenderLogout(c, err) + return err + } + r.RenderLogout(c, s.Logout(req)) + return nil + }) + + router.Add("POST", "/user/login/", func(c echo.Context) error { + ctx := c.Request().Context() + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + return err + } + resp, err := s.Login(req) + r.RenderLogin(c, resp, err) + return nil + }) + + { + h := func(c echo.Context) error { + ctx := c.Request().Context() + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + req, err := b.BindPrevTweets(c) + if err != nil { + r.RenderPrevTweets(c, nil, err) + return err + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(c, resp, err) + return nil + } + router.Add("HEAD", "/tweets/prev", h) + router.Add("GET", "/tweets/prev", h) + router.Add("POST", "/tweets/prev", h) + } + + router.Any("/tweets/next", func(c echo.Context) error { + ctx := c.Request().Context() + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + req, err := b.BindNextTweets(c) + if err != nil { + r.RenderNextTweets(c, nil, err) + return err + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(c, resp, err) + return nil + }) + + router.Add("GET", "/articles/:category/", func(c echo.Context) error { + ctx := c.Request().Context() + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + r.RenderArticles(c, s.Articles()) + return nil + }) + + router.Add("GET", "/index/", func(c echo.Context) error { + ctx := c.Request().Context() + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + r.RenderIndex(c, s.Index()) + return nil + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() []echo.MiddlewareFunc { + return nil +} + +func (UnimplementedSiteServant) Logout(req *LogoutReq) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(echo.Context, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(c echo.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(c echo.Context, data *LoginResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(c echo.Context, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(c echo.Context, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(c echo.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c echo.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(echo.Context, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogout(c echo.Context) (*LogoutReq, mir.Error) { + obj := new(LogoutReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindLogin(c echo.Context) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(c echo.Context) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(c echo.Context) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/echo/mirc/auto/api/v1/site.go.tmpl b/mirc/templates/echo/mirc/auto/api/v1/site.go.tmpl new file mode 100644 index 0000000..4081117 --- /dev/null +++ b/mirc/templates/echo/mirc/auto/api/v1/site.go.tmpl @@ -0,0 +1,99 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/labstack/echo/v4" +) + +type Site interface { + // Chain provide handlers chain for echo + Chain() []echo.MiddlewareFunc + + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteRender interface { + RenderArticles(echo.Context, mir.Error) + RenderIndex(echo.Context, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to echo +func RegisterSiteServant(e *echo.Echo, s Site, r SiteRender) { + router := e.Group("v1") + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + { + h := func(c echo.Context) error { + ctx := c.Request().Context() + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + r.RenderArticles(c, s.Articles()) + return nil + } + router.Add("POST", "/articles/:category/", h) + router.Add("GET", "/articles/:category/", h) + router.Add("HEAD", "/articles/:category/", h) + } + + router.Add("GET", "/index/", func(c echo.Context) error { + ctx := c.Request().Context() + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + r.RenderIndex(c, s.Index()) + return nil + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() []echo.MiddlewareFunc { + return nil +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(echo.Context, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderArticles(c echo.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c echo.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} diff --git a/mirc/templates/echo/mirc/auto/api/v2/site.go.tmpl b/mirc/templates/echo/mirc/auto/api/v2/site.go.tmpl new file mode 100644 index 0000000..6fa2c11 --- /dev/null +++ b/mirc/templates/echo/mirc/auto/api/v2/site.go.tmpl @@ -0,0 +1,267 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v2 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/labstack/echo/v4" +) + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + Logout() mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogin(echo.Context) (*LoginReq, mir.Error) + BindPrevTweets(echo.Context) (*TweetsReq, mir.Error) + BindNextTweets(echo.Context) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(echo.Context, mir.Error) + RenderLogin(echo.Context, *LoginResp, mir.Error) + RenderPrevTweets(echo.Context, *TweetsResp, mir.Error) + RenderNextTweets(echo.Context, *TweetsResp, mir.Error) + RenderArticles(echo.Context, mir.Error) + RenderIndex(echo.Context, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to echo +func RegisterSiteServant(e *echo.Echo, s Site, b SiteBinding, r SiteRender) { + router := e.Group("v2") + + // register routes info to router + router.Add("POST", "/user/logout/", func(c echo.Context) error { + ctx := c.Request().Context() + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + r.RenderLogout(c, s.Logout()) + return nil + }) + + router.Add("POST", "/user/login/", func(c echo.Context) error { + ctx := c.Request().Context() + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + return err + } + resp, err := s.Login(req) + r.RenderLogin(c, resp, err) + return nil + }) + + { + h := func(c echo.Context) error { + ctx := c.Request().Context() + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + req, err := b.BindPrevTweets(c) + if err != nil { + r.RenderPrevTweets(c, nil, err) + return err + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(c, resp, err) + return nil + } + router.Add("POST", "/tweets/prev", h) + router.Add("HEAD", "/tweets/prev", h) + router.Add("GET", "/tweets/prev", h) + } + + router.Any("/tweets/next", func(c echo.Context) error { + ctx := c.Request().Context() + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + req, err := b.BindNextTweets(c) + if err != nil { + r.RenderNextTweets(c, nil, err) + return err + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(c, resp, err) + return nil + }) + + router.Add("GET", "/articles/:category/", func(c echo.Context) error { + ctx := c.Request().Context() + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + r.RenderArticles(c, s.Articles()) + return nil + }) + + router.Add("GET", "/index/", func(c echo.Context) error { + ctx := c.Request().Context() + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + r.RenderIndex(c, s.Index()) + return nil + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Logout() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(echo.Context, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(c echo.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(c echo.Context, data *LoginResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(c echo.Context, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(c echo.Context, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(c echo.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c echo.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(echo.Context, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogin(c echo.Context) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(c echo.Context) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(c echo.Context) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/echo/mirc/main.go.tmpl b/mirc/templates/echo/mirc/main.go.tmpl new file mode 100644 index 0000000..9953240 --- /dev/null +++ b/mirc/templates/echo/mirc/main.go.tmpl @@ -0,0 +1,26 @@ +package main + +import ( + "log" + + . "github.com/alimy/mir/v3/core" + . "github.com/alimy/mir/v3/engine" + + _ "{{ .PkgName }}/mirc/routes" + _ "{{ .PkgName }}/mirc/routes/v1" + _ "{{ .PkgName }}/mirc/routes/v2" +) + +//go:generate go run main.go +func main() { + log.Println("generate code start") + opts := Options{ + RunMode(InSerialMode), + GeneratorName(GeneratorEcho), + SinkPath("auto"), + } + if err := Generate(opts); err != nil { + log.Fatal(err) + } + log.Println("generate code finish") +} diff --git a/mirc/templates/echo/mirc/routes/site.go.tmpl b/mirc/templates/echo/mirc/routes/site.go.tmpl new file mode 100644 index 0000000..2709138 --- /dev/null +++ b/mirc/templates/echo/mirc/routes/site.go.tmpl @@ -0,0 +1,65 @@ +package routes + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site interface info +type Site struct { + Chain Chain `mir:"-"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/:category/"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post, LogoutReq) `mir:"/user/logout/"` +} diff --git a/mirc/templates/echo/mirc/routes/v1/site.go.tmpl b/mirc/templates/echo/mirc/routes/v1/site.go.tmpl new file mode 100644 index 0000000..451c8bf --- /dev/null +++ b/mirc/templates/echo/mirc/routes/v1/site.go.tmpl @@ -0,0 +1,18 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +// Site site v1 interface info +type Site struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + Index func(Get) `mir:"/index/"` + Articles func(Head, Get, Post) `mir:"/articles/:category/"` +} diff --git a/mirc/templates/echo/mirc/routes/v2/site.go.tmpl b/mirc/templates/echo/mirc/routes/v2/site.go.tmpl new file mode 100644 index 0000000..502aeb5 --- /dev/null +++ b/mirc/templates/echo/mirc/routes/v2/site.go.tmpl @@ -0,0 +1,60 @@ +package v2 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site v2 interface info +type Site struct { + Group Group `mir:"v2"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/:category/"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post) `mir:"/user/logout/"` +} diff --git a/mirc/templates/echo/servants/core.go.tmpl b/mirc/templates/echo/servants/core.go.tmpl new file mode 100644 index 0000000..a383dd1 --- /dev/null +++ b/mirc/templates/echo/servants/core.go.tmpl @@ -0,0 +1,17 @@ +package servants + +import ( + "errors" + "net/http" + + "github.com/alimy/mir/v3" + "github.com/labstack/echo/v4" +) + +func bindAny(c echo.Context, obj any) mir.Error { + return mir.NewError(http.StatusNotImplemented, errors.New("method not implemented")) +} + +func renderAny(c echo.Context, data any, err mir.Error) { + c.String(http.StatusNotImplemented, "method not implemented") +} diff --git a/mirc/templates/echo/servants/servants.go.tmpl b/mirc/templates/echo/servants/servants.go.tmpl new file mode 100644 index 0000000..498b0e5 --- /dev/null +++ b/mirc/templates/echo/servants/servants.go.tmpl @@ -0,0 +1,15 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" + v1 "{{ .PkgName }}/mirc/auto/api/v1" + v2 "{{ .PkgName }}/mirc/auto/api/v2" + "github.com/labstack/echo/v4" +) + +// RegisterServants register all the servants to echo.Echo +func RegisterServants(e *echo.Echo) { + api.RegisterSiteServant(e, newSiteSrv(), newSiteBinding(), newSiteRender()) + v1.RegisterSiteServant(e, newSiteV1Srv(), newSiteV1Render()) + v2.RegisterSiteServant(e, newSiteV2Srv(), newSiteV2Binding(), newSiteV2Render()) +} diff --git a/mirc/templates/echo/servants/site.go.tmpl b/mirc/templates/echo/servants/site.go.tmpl new file mode 100644 index 0000000..0912d5f --- /dev/null +++ b/mirc/templates/echo/servants/site.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" +) + +type siteSrv struct { + api.UnimplementedSiteServant +} + +type siteBinding struct { + *api.UnimplementedSiteBinding +} + +type siteRender struct { + *api.UnimplementedSiteRender +} + +func newSiteSrv() api.Site { + return &siteSrv{} +} + +func newSiteBinding() api.SiteBinding { + return &siteBinding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteRender() api.SiteRender { + return &siteRender{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/echo/servants/site_v1.go.tmpl b/mirc/templates/echo/servants/site_v1.go.tmpl new file mode 100644 index 0000000..98a0a8b --- /dev/null +++ b/mirc/templates/echo/servants/site_v1.go.tmpl @@ -0,0 +1,25 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v1" +) + +type siteV1Srv struct { + api.UnimplementedSiteServant +} + +type siteV1Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV1Srv() api.Site { + return &siteV1Srv{} +} + +func newSiteV1Render() api.SiteRender { + return &siteV1Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/echo/servants/site_v2.go.tmpl b/mirc/templates/echo/servants/site_v2.go.tmpl new file mode 100644 index 0000000..4fb76aa --- /dev/null +++ b/mirc/templates/echo/servants/site_v2.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v2" +) + +type siteV2Srv struct { + api.UnimplementedSiteServant +} + +type siteV2Binding struct { + *api.UnimplementedSiteBinding +} + +type siteV2Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV2Srv() api.Site { + return &siteV2Srv{} +} + +func newSiteV2Binding() api.SiteBinding { + return &siteV2Binding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteV2Render() api.SiteRender { + return &siteV2Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/fiber-v2/.gitignore.tmpl b/mirc/templates/fiber-v2/.gitignore.tmpl new file mode 100644 index 0000000..96ffcd3 --- /dev/null +++ b/mirc/templates/fiber-v2/.gitignore.tmpl @@ -0,0 +1,25 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +coverage.out +count.out +test +profile.out +tmp.out + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# GoLand project files +.idea/ +*.iml + +# VS Code +.vscode diff --git a/mirc/templates/fiber-v2/Makefile.tmpl b/mirc/templates/fiber-v2/Makefile.tmpl new file mode 100644 index 0000000..9616a42 --- /dev/null +++ b/mirc/templates/fiber-v2/Makefile.tmpl @@ -0,0 +1,27 @@ +GOFMT ?= gofmt -s -w +GOFILES := $(shell find . -name "*.go" -type f) + +.PHONY: default +default: run + +.PHONY: build +build: fmt + go build -o mir-examples main.go + +.PHONY: build +run: fmt + go run main.go + +.PHONY: mod-tidy +mod-tidy: + @go mod download + @go mod tidy + +.PHONY: generate +generate: + @go generate mirc/main.go + @$(GOFMT) ./ + +.PHONY: fmt +fmt: + $(GOFMT) $(GOFILES) diff --git a/mirc/templates/fiber-v2/README.md.tmpl b/mirc/templates/fiber-v2/README.md.tmpl new file mode 100644 index 0000000..5bf9de3 --- /dev/null +++ b/mirc/templates/fiber-v2/README.md.tmpl @@ -0,0 +1,8 @@ +## mir-examples +just a simple mir's examples for explain how to use mir in your project. + +#### Usage +```bash +% make generate +% make build +``` diff --git a/mirc/templates/fiber-v2/go.mod.tmpl b/mirc/templates/fiber-v2/go.mod.tmpl new file mode 100644 index 0000000..2398855 --- /dev/null +++ b/mirc/templates/fiber-v2/go.mod.tmpl @@ -0,0 +1,26 @@ +module {{ .PkgName }} + +go 1.18 + +require ( + github.com/alimy/mir/v3 v3.0.0 + github.com/gofiber/fiber/v2 v2.40.1 +) + +require ( + github.com/andybalholm/brotli v1.0.4 // indirect + github.com/klauspost/compress v1.15.9 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.41.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect +) +{{if notEmptyStr .MirPkgName }} +replace ( + github.com/alimy/mir/v3 => {{ .MirPkgName }} +) +{{end}} diff --git a/mirc/templates/fiber-v2/go.sum.tmpl b/mirc/templates/fiber-v2/go.sum.tmpl new file mode 100644 index 0000000..98553d0 --- /dev/null +++ b/mirc/templates/fiber-v2/go.sum.tmpl @@ -0,0 +1,34 @@ +github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/gofiber/fiber/v2 v2.40.1 h1:pc7n9VVpGIqNsvg9IPLQhyFEMJL8gCs1kneH5D1pIl4= +github.com/gofiber/fiber/v2 v2.40.1/go.mod h1:Gko04sLksnHbzLSRBFWPFdzM9Ws9pRxvvIaohJK1dsk= +github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= +github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.41.0 h1:zeR0Z1my1wDHTRiamBCXVglQdbUwgb9uWG3k1HQz6jY= +github.com/valyala/fasthttp v1.41.0/go.mod h1:f6VbjjoI3z1NDOZOv17o6RvtRSWxC77seBFc2uWtgiY= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/mirc/templates/fiber-v2/main.go.tmpl b/mirc/templates/fiber-v2/main.go.tmpl new file mode 100644 index 0000000..338f8ea --- /dev/null +++ b/mirc/templates/fiber-v2/main.go.tmpl @@ -0,0 +1,20 @@ +package main + +import ( + "log" + + "{{ .PkgName }}/servants" + "github.com/gofiber/fiber/v2" +) + +func main() { + app := fiber.New() + + // register servants to fiber + servants.RegisterServants(app) + + // start servant service + if err := app.Listen(":3000"); err != nil { + log.Fatal(err) + } +} diff --git a/mirc/templates/fiber-v2/mirc/auto/api/site.go.tmpl b/mirc/templates/fiber-v2/mirc/auto/api/site.go.tmpl new file mode 100644 index 0000000..c378e49 --- /dev/null +++ b/mirc/templates/fiber-v2/mirc/auto/api/site.go.tmpl @@ -0,0 +1,253 @@ +// Code generated by go-mir. DO NOT EDIT. + +package api + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/middleware/logger" +) + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + // Chain provide handlers chain for fiber + Chain() []interface{} + + Logout(*LogoutReq) mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogout(*fiber.Ctx) (*LogoutReq, mir.Error) + BindLogin(*fiber.Ctx) (*LoginReq, mir.Error) + BindPrevTweets(*fiber.Ctx) (*TweetsReq, mir.Error) + BindNextTweets(*fiber.Ctx) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(*fiber.Ctx, mir.Error) + RenderLogin(*fiber.Ctx, *LoginResp, mir.Error) + RenderPrevTweets(*fiber.Ctx, *TweetsResp, mir.Error) + RenderNextTweets(*fiber.Ctx, *TweetsResp, mir.Error) + RenderArticles(*fiber.Ctx, mir.Error) + RenderIndex(*fiber.Ctx, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to fiber +func RegisterSiteServant(app *fiber.App, s Site, b SiteBinding, r SiteRender) { + router := app + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Add("POST", "/user/logout/", func(c *fiber.Ctx) error { + req, err := b.BindLogout(c) + if err != nil { + r.RenderLogout(c, err) + return err + } + r.RenderLogout(c, s.Logout(req)) + return nil + }) + + router.Add("POST", "/user/login/", func(c *fiber.Ctx) error { + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + return err + } + resp, err := s.Login(req) + r.RenderLogin(c, resp, err) + return nil + }) + + { + h := func(c *fiber.Ctx) error { + req, err := b.BindPrevTweets(c) + if err != nil { + r.RenderPrevTweets(c, nil, err) + return err + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(c, resp, err) + return nil + } + router.Add("GET", "/tweets/prev", h) + router.Add("POST", "/tweets/prev", h) + router.Add("HEAD", "/tweets/prev", h) + } + + router.All("/tweets/next", func(c *fiber.Ctx) error { + req, err := b.BindNextTweets(c) + if err != nil { + r.RenderNextTweets(c, nil, err) + return err + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(c, resp, err) + return nil + }) + + router.Add("GET", "/articles/:category/", func(c *fiber.Ctx) error { + r.RenderArticles(c, s.Articles()) + return nil + }) + + router.Add("GET", "/index/", func(c *fiber.Ctx) error { + r.RenderIndex(c, s.Index()) + return nil + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() []interface{} { + return []interface{}{logger.New()} +} + +func (UnimplementedSiteServant) Logout(req *LogoutReq) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(*fiber.Ctx, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(c *fiber.Ctx, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(c *fiber.Ctx, data *LoginResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(c *fiber.Ctx, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(c *fiber.Ctx, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(c *fiber.Ctx, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c *fiber.Ctx, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(*fiber.Ctx, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogout(c *fiber.Ctx) (*LogoutReq, mir.Error) { + obj := new(LogoutReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindLogin(c *fiber.Ctx) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(c *fiber.Ctx) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(c *fiber.Ctx) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/fiber-v2/mirc/auto/api/v1/site.go.tmpl b/mirc/templates/fiber-v2/mirc/auto/api/v1/site.go.tmpl new file mode 100644 index 0000000..61d7e45 --- /dev/null +++ b/mirc/templates/fiber-v2/mirc/auto/api/v1/site.go.tmpl @@ -0,0 +1,86 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/middleware/logger" +) + +type Site interface { + // Chain provide handlers chain for fiber + Chain() []interface{} + + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteRender interface { + RenderArticles(*fiber.Ctx, mir.Error) + RenderIndex(*fiber.Ctx, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to fiber +func RegisterSiteServant(app *fiber.App, s Site, r SiteRender) { + router := app.Group("v1") + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + { + h := func(c *fiber.Ctx) error { + r.RenderArticles(c, s.Articles()) + return nil + } + router.Add("POST", "/articles/:category/", h) + router.Add("GET", "/articles/:category/", h) + router.Add("HEAD", "/articles/:category/", h) + } + + router.Add("GET", "/index/", func(c *fiber.Ctx) error { + r.RenderIndex(c, s.Index()) + return nil + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() []interface{} { + return []interface{}{logger.New()} +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(*fiber.Ctx, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderArticles(c *fiber.Ctx, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c *fiber.Ctx, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} diff --git a/mirc/templates/fiber-v2/mirc/auto/api/v2/site.go.tmpl b/mirc/templates/fiber-v2/mirc/auto/api/v2/site.go.tmpl new file mode 100644 index 0000000..eb87909 --- /dev/null +++ b/mirc/templates/fiber-v2/mirc/auto/api/v2/site.go.tmpl @@ -0,0 +1,225 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v2 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gofiber/fiber/v2" +) + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + Logout() mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogin(*fiber.Ctx) (*LoginReq, mir.Error) + BindPrevTweets(*fiber.Ctx) (*TweetsReq, mir.Error) + BindNextTweets(*fiber.Ctx) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(*fiber.Ctx, mir.Error) + RenderLogin(*fiber.Ctx, *LoginResp, mir.Error) + RenderPrevTweets(*fiber.Ctx, *TweetsResp, mir.Error) + RenderNextTweets(*fiber.Ctx, *TweetsResp, mir.Error) + RenderArticles(*fiber.Ctx, mir.Error) + RenderIndex(*fiber.Ctx, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to fiber +func RegisterSiteServant(app *fiber.App, s Site, b SiteBinding, r SiteRender) { + router := app.Group("v2") + + // register routes info to router + router.Add("POST", "/user/logout/", func(c *fiber.Ctx) error { + r.RenderLogout(c, s.Logout()) + return nil + }) + + router.Add("POST", "/user/login/", func(c *fiber.Ctx) error { + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + return err + } + resp, err := s.Login(req) + r.RenderLogin(c, resp, err) + return nil + }) + + { + h := func(c *fiber.Ctx) error { + req, err := b.BindPrevTweets(c) + if err != nil { + r.RenderPrevTweets(c, nil, err) + return err + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(c, resp, err) + return nil + } + router.Add("HEAD", "/tweets/prev", h) + router.Add("GET", "/tweets/prev", h) + router.Add("POST", "/tweets/prev", h) + } + + router.All("/tweets/next", func(c *fiber.Ctx) error { + req, err := b.BindNextTweets(c) + if err != nil { + r.RenderNextTweets(c, nil, err) + return err + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(c, resp, err) + return nil + }) + + router.Add("GET", "/articles/:category/", func(c *fiber.Ctx) error { + r.RenderArticles(c, s.Articles()) + return nil + }) + + router.Add("GET", "/index/", func(c *fiber.Ctx) error { + r.RenderIndex(c, s.Index()) + return nil + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Logout() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(*fiber.Ctx, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(c *fiber.Ctx, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(c *fiber.Ctx, data *LoginResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(c *fiber.Ctx, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(c *fiber.Ctx, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(c *fiber.Ctx, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c *fiber.Ctx, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(*fiber.Ctx, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogin(c *fiber.Ctx) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(c *fiber.Ctx) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(c *fiber.Ctx) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/fiber-v2/mirc/main.go.tmpl b/mirc/templates/fiber-v2/mirc/main.go.tmpl new file mode 100644 index 0000000..15c14b5 --- /dev/null +++ b/mirc/templates/fiber-v2/mirc/main.go.tmpl @@ -0,0 +1,27 @@ +package main + +import ( + "log" + + . "github.com/alimy/mir/v3/core" + . "github.com/alimy/mir/v3/engine" + + _ "{{ .PkgName }}/mirc/routes" + _ "{{ .PkgName }}/mirc/routes/v1" + _ "{{ .PkgName }}/mirc/routes/v2" +) + +//go:generate go run main.go +func main() { + log.Println("generate code start") + opts := Options{ + RunMode(InSerialMode), + GeneratorName(GeneratorFiberV2), + NoneQuery(true), + SinkPath("auto"), + } + if err := Generate(opts); err != nil { + log.Fatal(err) + } + log.Println("generate code finish") +} diff --git a/mirc/templates/fiber-v2/mirc/routes/site.go.tmpl b/mirc/templates/fiber-v2/mirc/routes/site.go.tmpl new file mode 100644 index 0000000..2709138 --- /dev/null +++ b/mirc/templates/fiber-v2/mirc/routes/site.go.tmpl @@ -0,0 +1,65 @@ +package routes + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site interface info +type Site struct { + Chain Chain `mir:"-"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/:category/"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post, LogoutReq) `mir:"/user/logout/"` +} diff --git a/mirc/templates/fiber-v2/mirc/routes/v1/site.go.tmpl b/mirc/templates/fiber-v2/mirc/routes/v1/site.go.tmpl new file mode 100644 index 0000000..451c8bf --- /dev/null +++ b/mirc/templates/fiber-v2/mirc/routes/v1/site.go.tmpl @@ -0,0 +1,18 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +// Site site v1 interface info +type Site struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + Index func(Get) `mir:"/index/"` + Articles func(Head, Get, Post) `mir:"/articles/:category/"` +} diff --git a/mirc/templates/fiber-v2/mirc/routes/v2/site.go.tmpl b/mirc/templates/fiber-v2/mirc/routes/v2/site.go.tmpl new file mode 100644 index 0000000..502aeb5 --- /dev/null +++ b/mirc/templates/fiber-v2/mirc/routes/v2/site.go.tmpl @@ -0,0 +1,60 @@ +package v2 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site v2 interface info +type Site struct { + Group Group `mir:"v2"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/:category/"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post) `mir:"/user/logout/"` +} diff --git a/mirc/templates/fiber-v2/servants/core.go.tmpl b/mirc/templates/fiber-v2/servants/core.go.tmpl new file mode 100644 index 0000000..9e8f9da --- /dev/null +++ b/mirc/templates/fiber-v2/servants/core.go.tmpl @@ -0,0 +1,18 @@ +package servants + +import ( + "errors" + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gofiber/fiber/v2" +) + +func bindAny(c *fiber.Ctx, obj any) mir.Error { + return mir.NewError(http.StatusNotImplemented, errors.New("method not implemented")) +} + +func renderAny(c *fiber.Ctx, data any, err mir.Error) { + c.Status(http.StatusNotImplemented) + c.Write([]byte("method not implemented")) +} diff --git a/mirc/templates/fiber-v2/servants/servants.go.tmpl b/mirc/templates/fiber-v2/servants/servants.go.tmpl new file mode 100644 index 0000000..51d108b --- /dev/null +++ b/mirc/templates/fiber-v2/servants/servants.go.tmpl @@ -0,0 +1,15 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" + v1 "{{ .PkgName }}/mirc/auto/api/v1" + v2 "{{ .PkgName }}/mirc/auto/api/v2" + "github.com/gofiber/fiber/v2" +) + +// RegisterServants register all the servants to fiber.App +func RegisterServants(app *fiber.App) { + api.RegisterSiteServant(app, newSiteSrv(), newSiteBinding(), newSiteRender()) + v1.RegisterSiteServant(app, newSiteV1Srv(), newSiteV1Render()) + v2.RegisterSiteServant(app, newSiteV2Srv(), newSiteV2Binding(), newSiteV2Render()) +} diff --git a/mirc/templates/fiber-v2/servants/site.go.tmpl b/mirc/templates/fiber-v2/servants/site.go.tmpl new file mode 100644 index 0000000..0912d5f --- /dev/null +++ b/mirc/templates/fiber-v2/servants/site.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" +) + +type siteSrv struct { + api.UnimplementedSiteServant +} + +type siteBinding struct { + *api.UnimplementedSiteBinding +} + +type siteRender struct { + *api.UnimplementedSiteRender +} + +func newSiteSrv() api.Site { + return &siteSrv{} +} + +func newSiteBinding() api.SiteBinding { + return &siteBinding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteRender() api.SiteRender { + return &siteRender{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/fiber-v2/servants/site_v1.go.tmpl b/mirc/templates/fiber-v2/servants/site_v1.go.tmpl new file mode 100644 index 0000000..98a0a8b --- /dev/null +++ b/mirc/templates/fiber-v2/servants/site_v1.go.tmpl @@ -0,0 +1,25 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v1" +) + +type siteV1Srv struct { + api.UnimplementedSiteServant +} + +type siteV1Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV1Srv() api.Site { + return &siteV1Srv{} +} + +func newSiteV1Render() api.SiteRender { + return &siteV1Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/fiber-v2/servants/site_v2.go.tmpl b/mirc/templates/fiber-v2/servants/site_v2.go.tmpl new file mode 100644 index 0000000..4fb76aa --- /dev/null +++ b/mirc/templates/fiber-v2/servants/site_v2.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v2" +) + +type siteV2Srv struct { + api.UnimplementedSiteServant +} + +type siteV2Binding struct { + *api.UnimplementedSiteBinding +} + +type siteV2Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV2Srv() api.Site { + return &siteV2Srv{} +} + +func newSiteV2Binding() api.SiteBinding { + return &siteV2Binding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteV2Render() api.SiteRender { + return &siteV2Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/fiber/.gitignore.tmpl b/mirc/templates/fiber/.gitignore.tmpl new file mode 100644 index 0000000..96ffcd3 --- /dev/null +++ b/mirc/templates/fiber/.gitignore.tmpl @@ -0,0 +1,25 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +coverage.out +count.out +test +profile.out +tmp.out + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# GoLand project files +.idea/ +*.iml + +# VS Code +.vscode diff --git a/mirc/templates/fiber/Makefile.tmpl b/mirc/templates/fiber/Makefile.tmpl new file mode 100644 index 0000000..9616a42 --- /dev/null +++ b/mirc/templates/fiber/Makefile.tmpl @@ -0,0 +1,27 @@ +GOFMT ?= gofmt -s -w +GOFILES := $(shell find . -name "*.go" -type f) + +.PHONY: default +default: run + +.PHONY: build +build: fmt + go build -o mir-examples main.go + +.PHONY: build +run: fmt + go run main.go + +.PHONY: mod-tidy +mod-tidy: + @go mod download + @go mod tidy + +.PHONY: generate +generate: + @go generate mirc/main.go + @$(GOFMT) ./ + +.PHONY: fmt +fmt: + $(GOFMT) $(GOFILES) diff --git a/mirc/templates/fiber/README.md.tmpl b/mirc/templates/fiber/README.md.tmpl new file mode 100644 index 0000000..5bf9de3 --- /dev/null +++ b/mirc/templates/fiber/README.md.tmpl @@ -0,0 +1,8 @@ +## mir-examples +just a simple mir's examples for explain how to use mir in your project. + +#### Usage +```bash +% make generate +% make build +``` diff --git a/mirc/templates/fiber/go.mod.tmpl b/mirc/templates/fiber/go.mod.tmpl new file mode 100644 index 0000000..6962eac --- /dev/null +++ b/mirc/templates/fiber/go.mod.tmpl @@ -0,0 +1,26 @@ +module {{ .PkgName }} + +go 1.18 + +require ( + github.com/alimy/mir/v3 v3.0.0 + github.com/gofiber/fiber v1.14.6 +) + +require ( + github.com/andybalholm/brotli v1.0.0 // indirect + github.com/gofiber/utils v0.0.10 // indirect + github.com/gorilla/schema v1.1.0 // indirect + github.com/klauspost/compress v1.10.7 // indirect + github.com/mattn/go-colorable v0.1.7 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.16.0 // indirect + github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a // indirect + golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 // indirect +) +{{if notEmptyStr .MirPkgName }} +replace ( + github.com/alimy/mir/v3 => {{ .MirPkgName }} +) +{{end}} diff --git a/mirc/templates/fiber/go.sum.tmpl b/mirc/templates/fiber/go.sum.tmpl new file mode 100644 index 0000000..5de0eec --- /dev/null +++ b/mirc/templates/fiber/go.sum.tmpl @@ -0,0 +1,32 @@ +github.com/andybalholm/brotli v1.0.0 h1:7UCwP93aiSfvWpapti8g88vVVGp2qqtGyePsSuDafo4= +github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/gofiber/fiber v1.14.6 h1:QRUPvPmr8ijQuGo1MgupHBn8E+wW0IKqiOvIZPtV70o= +github.com/gofiber/fiber v1.14.6/go.mod h1:Yw2ekF1YDPreO9V6TMYjynu94xRxZBdaa8X5HhHsjCM= +github.com/gofiber/utils v0.0.10 h1:3Mr7X7JdCUo7CWf/i5sajSaDmArEDtti8bM1JUVso2U= +github.com/gofiber/utils v0.0.10/go.mod h1:9J5aHFUIjq0XfknT4+hdSMG6/jzfaAgCu4HEbWDeBlo= +github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY= +github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= +github.com/klauspost/compress v1.10.7 h1:7rix8v8GpI3ZBb0nSozFRgbtXKv+hOe+qfEpZqybrAg= +github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.16.0 h1:9zAqOYLl8Tuy3E5R6ckzGDJ1g8+pw15oQp2iL9Jl6gQ= +github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a h1:0R4NLDRDZX6JcmhJgXi5E4b8Wg84ihbmUKp/GvSPEzc= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/mirc/templates/fiber/main.go.tmpl b/mirc/templates/fiber/main.go.tmpl new file mode 100644 index 0000000..e82dc0e --- /dev/null +++ b/mirc/templates/fiber/main.go.tmpl @@ -0,0 +1,20 @@ +package main + +import ( + "log" + + "{{ .PkgName }}/servants" + "github.com/gofiber/fiber" +) + +func main() { + app := fiber.New() + + // register servants to fiber + servants.RegisterServants(app) + + // start servant service + if err := app.Listen(3000); err != nil { + log.Fatal(err) + } +} diff --git a/mirc/templates/fiber/mirc/auto/api/site.go.tmpl b/mirc/templates/fiber/mirc/auto/api/site.go.tmpl new file mode 100644 index 0000000..3df3c22 --- /dev/null +++ b/mirc/templates/fiber/mirc/auto/api/site.go.tmpl @@ -0,0 +1,247 @@ +// Code generated by go-mir. DO NOT EDIT. + +package api + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gofiber/fiber" + "github.com/gofiber/fiber/middleware" +) + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + // Chain provide handlers chain for fiber + Chain() []interface{} + + Logout(*LogoutReq) mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogout(*fiber.Ctx) (*LogoutReq, mir.Error) + BindLogin(*fiber.Ctx) (*LoginReq, mir.Error) + BindPrevTweets(*fiber.Ctx) (*TweetsReq, mir.Error) + BindNextTweets(*fiber.Ctx) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(*fiber.Ctx, mir.Error) + RenderLogin(*fiber.Ctx, *LoginResp, mir.Error) + RenderPrevTweets(*fiber.Ctx, *TweetsResp, mir.Error) + RenderNextTweets(*fiber.Ctx, *TweetsResp, mir.Error) + RenderArticles(*fiber.Ctx, mir.Error) + RenderIndex(*fiber.Ctx, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to fiber +func RegisterSiteServant(app *fiber.App, s Site, b SiteBinding, r SiteRender) { + router := app + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Add("POST", "/user/logout/", func(c *fiber.Ctx) { + req, err := b.BindLogout(c) + if err != nil { + r.RenderLogout(c, err) + return + } + r.RenderLogout(c, s.Logout(req)) + }) + + router.Add("POST", "/user/login/", func(c *fiber.Ctx) { + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(c, resp, err) + }) + + { + h := func(c *fiber.Ctx) { + req, err := b.BindPrevTweets(c) + if err != nil { + r.RenderPrevTweets(c, nil, err) + return + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(c, resp, err) + } + router.Add("HEAD", "/tweets/prev", h) + router.Add("GET", "/tweets/prev", h) + router.Add("POST", "/tweets/prev", h) + } + + router.All("/tweets/next", func(c *fiber.Ctx) { + req, err := b.BindNextTweets(c) + if err != nil { + r.RenderNextTweets(c, nil, err) + return + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(c, resp, err) + }) + + router.Add("GET", "/articles/:category/", func(c *fiber.Ctx) { + r.RenderArticles(c, s.Articles()) + }) + + router.Add("GET", "/index/", func(c *fiber.Ctx) { + r.RenderIndex(c, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() []interface{} { + return []interface{}{middleware.Logger()} +} + +func (UnimplementedSiteServant) Logout(req *LogoutReq) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(*fiber.Ctx, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(c *fiber.Ctx, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(c *fiber.Ctx, data *LoginResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(c *fiber.Ctx, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(c *fiber.Ctx, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(c *fiber.Ctx, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c *fiber.Ctx, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(*fiber.Ctx, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogout(c *fiber.Ctx) (*LogoutReq, mir.Error) { + obj := new(LogoutReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindLogin(c *fiber.Ctx) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(c *fiber.Ctx) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(c *fiber.Ctx) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/fiber/mirc/auto/api/v1/site.go.tmpl b/mirc/templates/fiber/mirc/auto/api/v1/site.go.tmpl new file mode 100644 index 0000000..1f37570 --- /dev/null +++ b/mirc/templates/fiber/mirc/auto/api/v1/site.go.tmpl @@ -0,0 +1,84 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gofiber/fiber" + "github.com/gofiber/fiber/middleware" +) + +type Site interface { + // Chain provide handlers chain for fiber + Chain() []interface{} + + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteRender interface { + RenderArticles(*fiber.Ctx, mir.Error) + RenderIndex(*fiber.Ctx, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to fiber +func RegisterSiteServant(app *fiber.App, s Site, r SiteRender) { + router := app.Group("v1") + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + { + h := func(c *fiber.Ctx) { + r.RenderArticles(c, s.Articles()) + } + router.Add("GET", "/articles/:category/", h) + router.Add("HEAD", "/articles/:category/", h) + router.Add("POST", "/articles/:category/", h) + } + + router.Add("GET", "/index/", func(c *fiber.Ctx) { + r.RenderIndex(c, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() []interface{} { + return []interface{}{middleware.Logger()} +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(*fiber.Ctx, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderArticles(c *fiber.Ctx, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c *fiber.Ctx, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} diff --git a/mirc/templates/fiber/mirc/auto/api/v2/site.go.tmpl b/mirc/templates/fiber/mirc/auto/api/v2/site.go.tmpl new file mode 100644 index 0000000..f2e30a6 --- /dev/null +++ b/mirc/templates/fiber/mirc/auto/api/v2/site.go.tmpl @@ -0,0 +1,219 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v2 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gofiber/fiber" +) + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + Logout() mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogin(*fiber.Ctx) (*LoginReq, mir.Error) + BindPrevTweets(*fiber.Ctx) (*TweetsReq, mir.Error) + BindNextTweets(*fiber.Ctx) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(*fiber.Ctx, mir.Error) + RenderLogin(*fiber.Ctx, *LoginResp, mir.Error) + RenderPrevTweets(*fiber.Ctx, *TweetsResp, mir.Error) + RenderNextTweets(*fiber.Ctx, *TweetsResp, mir.Error) + RenderArticles(*fiber.Ctx, mir.Error) + RenderIndex(*fiber.Ctx, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to fiber +func RegisterSiteServant(app *fiber.App, s Site, b SiteBinding, r SiteRender) { + router := app.Group("v2") + + // register routes info to router + router.Add("POST", "/user/logout/", func(c *fiber.Ctx) { + r.RenderLogout(c, s.Logout()) + }) + + router.Add("POST", "/user/login/", func(c *fiber.Ctx) { + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(c, resp, err) + }) + + { + h := func(c *fiber.Ctx) { + req, err := b.BindPrevTweets(c) + if err != nil { + r.RenderPrevTweets(c, nil, err) + return + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(c, resp, err) + } + router.Add("GET", "/tweets/prev", h) + router.Add("POST", "/tweets/prev", h) + router.Add("HEAD", "/tweets/prev", h) + } + + router.All("/tweets/next", func(c *fiber.Ctx) { + req, err := b.BindNextTweets(c) + if err != nil { + r.RenderNextTweets(c, nil, err) + return + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(c, resp, err) + }) + + router.Add("GET", "/articles/:category/", func(c *fiber.Ctx) { + r.RenderArticles(c, s.Articles()) + }) + + router.Add("GET", "/index/", func(c *fiber.Ctx) { + r.RenderIndex(c, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Logout() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(*fiber.Ctx, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(c *fiber.Ctx, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(c *fiber.Ctx, data *LoginResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(c *fiber.Ctx, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(c *fiber.Ctx, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(c *fiber.Ctx, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c *fiber.Ctx, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(*fiber.Ctx, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogin(c *fiber.Ctx) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(c *fiber.Ctx) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(c *fiber.Ctx) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/fiber/mirc/main.go.tmpl b/mirc/templates/fiber/mirc/main.go.tmpl new file mode 100644 index 0000000..d9a7a49 --- /dev/null +++ b/mirc/templates/fiber/mirc/main.go.tmpl @@ -0,0 +1,27 @@ +package main + +import ( + "log" + + . "github.com/alimy/mir/v3/core" + . "github.com/alimy/mir/v3/engine" + + _ "{{ .PkgName }}/mirc/routes" + _ "{{ .PkgName }}/mirc/routes/v1" + _ "{{ .PkgName }}/mirc/routes/v2" +) + +//go:generate go run main.go +func main() { + log.Println("generate code start") + opts := Options{ + RunMode(InSerialMode), + GeneratorName(GeneratorFiber), + NoneQuery(true), + SinkPath("auto"), + } + if err := Generate(opts); err != nil { + log.Fatal(err) + } + log.Println("generate code finish") +} diff --git a/mirc/templates/fiber/mirc/routes/site.go.tmpl b/mirc/templates/fiber/mirc/routes/site.go.tmpl new file mode 100644 index 0000000..2709138 --- /dev/null +++ b/mirc/templates/fiber/mirc/routes/site.go.tmpl @@ -0,0 +1,65 @@ +package routes + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site interface info +type Site struct { + Chain Chain `mir:"-"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/:category/"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post, LogoutReq) `mir:"/user/logout/"` +} diff --git a/mirc/templates/fiber/mirc/routes/v1/site.go.tmpl b/mirc/templates/fiber/mirc/routes/v1/site.go.tmpl new file mode 100644 index 0000000..451c8bf --- /dev/null +++ b/mirc/templates/fiber/mirc/routes/v1/site.go.tmpl @@ -0,0 +1,18 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +// Site site v1 interface info +type Site struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + Index func(Get) `mir:"/index/"` + Articles func(Head, Get, Post) `mir:"/articles/:category/"` +} diff --git a/mirc/templates/fiber/mirc/routes/v2/site.go.tmpl b/mirc/templates/fiber/mirc/routes/v2/site.go.tmpl new file mode 100644 index 0000000..502aeb5 --- /dev/null +++ b/mirc/templates/fiber/mirc/routes/v2/site.go.tmpl @@ -0,0 +1,60 @@ +package v2 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site v2 interface info +type Site struct { + Group Group `mir:"v2"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/:category/"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post) `mir:"/user/logout/"` +} diff --git a/mirc/templates/fiber/servants/core.go.tmpl b/mirc/templates/fiber/servants/core.go.tmpl new file mode 100644 index 0000000..3f07f79 --- /dev/null +++ b/mirc/templates/fiber/servants/core.go.tmpl @@ -0,0 +1,18 @@ +package servants + +import ( + "errors" + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gofiber/fiber" +) + +func bindAny(c *fiber.Ctx, obj any) mir.Error { + return mir.NewError(http.StatusNotImplemented, errors.New("method not implemented")) +} + +func renderAny(c *fiber.Ctx, data any, err mir.Error) { + c.Status(http.StatusNotImplemented) + c.Write([]byte("method not implemented")) +} diff --git a/mirc/templates/fiber/servants/servants.go.tmpl b/mirc/templates/fiber/servants/servants.go.tmpl new file mode 100644 index 0000000..e56ae88 --- /dev/null +++ b/mirc/templates/fiber/servants/servants.go.tmpl @@ -0,0 +1,15 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" + v1 "{{ .PkgName }}/mirc/auto/api/v1" + v2 "{{ .PkgName }}/mirc/auto/api/v2" + "github.com/gofiber/fiber" +) + +// RegisterServants register all the servants to fiber.App +func RegisterServants(app *fiber.App) { + api.RegisterSiteServant(app, newSiteSrv(), newSiteBinding(), newSiteRender()) + v1.RegisterSiteServant(app, newSiteV1Srv(), newSiteV1Render()) + v2.RegisterSiteServant(app, newSiteV2Srv(), newSiteV2Binding(), newSiteV2Render()) +} diff --git a/mirc/templates/fiber/servants/site.go.tmpl b/mirc/templates/fiber/servants/site.go.tmpl new file mode 100644 index 0000000..0912d5f --- /dev/null +++ b/mirc/templates/fiber/servants/site.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" +) + +type siteSrv struct { + api.UnimplementedSiteServant +} + +type siteBinding struct { + *api.UnimplementedSiteBinding +} + +type siteRender struct { + *api.UnimplementedSiteRender +} + +func newSiteSrv() api.Site { + return &siteSrv{} +} + +func newSiteBinding() api.SiteBinding { + return &siteBinding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteRender() api.SiteRender { + return &siteRender{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/fiber/servants/site_v1.go.tmpl b/mirc/templates/fiber/servants/site_v1.go.tmpl new file mode 100644 index 0000000..98a0a8b --- /dev/null +++ b/mirc/templates/fiber/servants/site_v1.go.tmpl @@ -0,0 +1,25 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v1" +) + +type siteV1Srv struct { + api.UnimplementedSiteServant +} + +type siteV1Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV1Srv() api.Site { + return &siteV1Srv{} +} + +func newSiteV1Render() api.SiteRender { + return &siteV1Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/fiber/servants/site_v2.go.tmpl b/mirc/templates/fiber/servants/site_v2.go.tmpl new file mode 100644 index 0000000..4fb76aa --- /dev/null +++ b/mirc/templates/fiber/servants/site_v2.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v2" +) + +type siteV2Srv struct { + api.UnimplementedSiteServant +} + +type siteV2Binding struct { + *api.UnimplementedSiteBinding +} + +type siteV2Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV2Srv() api.Site { + return &siteV2Srv{} +} + +func newSiteV2Binding() api.SiteBinding { + return &siteV2Binding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteV2Render() api.SiteRender { + return &siteV2Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/gin/.gitignore.tmpl b/mirc/templates/gin/.gitignore.tmpl new file mode 100644 index 0000000..96ffcd3 --- /dev/null +++ b/mirc/templates/gin/.gitignore.tmpl @@ -0,0 +1,25 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +coverage.out +count.out +test +profile.out +tmp.out + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# GoLand project files +.idea/ +*.iml + +# VS Code +.vscode diff --git a/mirc/templates/gin/Makefile.tmpl b/mirc/templates/gin/Makefile.tmpl new file mode 100644 index 0000000..9616a42 --- /dev/null +++ b/mirc/templates/gin/Makefile.tmpl @@ -0,0 +1,27 @@ +GOFMT ?= gofmt -s -w +GOFILES := $(shell find . -name "*.go" -type f) + +.PHONY: default +default: run + +.PHONY: build +build: fmt + go build -o mir-examples main.go + +.PHONY: build +run: fmt + go run main.go + +.PHONY: mod-tidy +mod-tidy: + @go mod download + @go mod tidy + +.PHONY: generate +generate: + @go generate mirc/main.go + @$(GOFMT) ./ + +.PHONY: fmt +fmt: + $(GOFMT) $(GOFILES) diff --git a/mirc/templates/gin/README.md.tmpl b/mirc/templates/gin/README.md.tmpl new file mode 100644 index 0000000..5bf9de3 --- /dev/null +++ b/mirc/templates/gin/README.md.tmpl @@ -0,0 +1,8 @@ +## mir-examples +just a simple mir's examples for explain how to use mir in your project. + +#### Usage +```bash +% make generate +% make build +``` diff --git a/mirc/templates/gin/go.mod.tmpl b/mirc/templates/gin/go.mod.tmpl new file mode 100644 index 0000000..19228bf --- /dev/null +++ b/mirc/templates/gin/go.mod.tmpl @@ -0,0 +1,34 @@ +module {{ .PkgName }} + +go 1.18 + +require ( + github.com/alimy/mir/v3 v3.0.0 + github.com/gin-gonic/gin v1.8.1 +) + +require ( + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-playground/locales v0.14.0 // indirect + github.com/go-playground/universal-translator v0.18.0 // indirect + github.com/go-playground/validator/v10 v10.10.0 // indirect + github.com/goccy/go-json v0.9.7 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/leodido/go-urn v1.2.1 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.0.1 // indirect + github.com/ugorji/go/codec v1.2.7 // indirect + golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect + golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect + golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 // indirect + golang.org/x/text v0.3.6 // indirect + google.golang.org/protobuf v1.28.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect +) +{{if notEmptyStr .MirPkgName }} +replace ( + github.com/alimy/mir/v3 => {{ .MirPkgName }} +) +{{end}} diff --git a/mirc/templates/gin/go.sum.tmpl b/mirc/templates/gin/go.sum.tmpl new file mode 100644 index 0000000..dd94772 --- /dev/null +++ b/mirc/templates/gin/go.sum.tmpl @@ -0,0 +1,87 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= +github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0= +github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= +github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU= +github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= +github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= +github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/mirc/templates/gin/main.go.tmpl b/mirc/templates/gin/main.go.tmpl new file mode 100644 index 0000000..1e298cb --- /dev/null +++ b/mirc/templates/gin/main.go.tmpl @@ -0,0 +1,20 @@ +package main + +import ( + "log" + + "{{ .PkgName }}/servants" + "github.com/gin-gonic/gin" +) + +func main() { + e := gin.Default() + + // register servants to gin + servants.RegisterServants(e) + + // start servant service + if err := e.Run(); err != nil { + log.Fatal(err) + } +} diff --git a/mirc/templates/gin/mirc/auto/api/site.go.tmpl b/mirc/templates/gin/mirc/auto/api/site.go.tmpl new file mode 100644 index 0000000..40f308d --- /dev/null +++ b/mirc/templates/gin/mirc/auto/api/site.go.tmpl @@ -0,0 +1,282 @@ +// Code generated by go-mir. DO NOT EDIT. + +package api + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" +) + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + // Chain provide handlers chain for gin + Chain() gin.HandlersChain + + Logout(*LogoutReq) mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogout(*gin.Context) (*LogoutReq, mir.Error) + BindLogin(*gin.Context) (*LoginReq, mir.Error) + BindPrevTweets(*gin.Context) (*TweetsReq, mir.Error) + BindNextTweets(*gin.Context) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(*gin.Context, mir.Error) + RenderLogin(*gin.Context, *LoginResp, mir.Error) + RenderPrevTweets(*gin.Context, *TweetsResp, mir.Error) + RenderNextTweets(*gin.Context, *TweetsResp, mir.Error) + RenderArticles(*gin.Context, mir.Error) + RenderIndex(*gin.Context, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to gin +func RegisterSiteServant(e *gin.Engine, s Site, b SiteBinding, r SiteRender) { + router := e + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Handle("POST", "/user/logout/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindLogout(c) + if err != nil { + r.RenderLogout(c, err) + return + } + r.RenderLogout(c, s.Logout(req)) + }) + + router.Handle("POST", "/user/login/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(c, resp, err) + }) + + { + h := func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindPrevTweets(c) + if err != nil { + r.RenderPrevTweets(c, nil, err) + return + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(c, resp, err) + } + router.Handle("HEAD", "/tweets/prev", h) + router.Handle("GET", "/tweets/prev", h) + router.Handle("POST", "/tweets/prev", h) + } + + router.Any("/tweets/next", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindNextTweets(c) + if err != nil { + r.RenderNextTweets(c, nil, err) + return + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(c, resp, err) + }) + + router.Handle("GET", "/articles/:category/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderArticles(c, s.Articles()) + }) + + router.Handle("GET", "/index/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderIndex(c, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() gin.HandlersChain { + return nil +} + +func (UnimplementedSiteServant) Logout(req *LogoutReq) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(c *gin.Context, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(c *gin.Context, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogout(c *gin.Context) (*LogoutReq, mir.Error) { + obj := new(LogoutReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(c *gin.Context) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(c *gin.Context) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/gin/mirc/auto/api/v1/site.go.tmpl b/mirc/templates/gin/mirc/auto/api/v1/site.go.tmpl new file mode 100644 index 0000000..5c71a85 --- /dev/null +++ b/mirc/templates/gin/mirc/auto/api/v1/site.go.tmpl @@ -0,0 +1,95 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" +) + +type Site interface { + // Chain provide handlers chain for gin + Chain() gin.HandlersChain + + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteRender interface { + RenderArticles(*gin.Context, mir.Error) + RenderIndex(*gin.Context, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to gin +func RegisterSiteServant(e *gin.Engine, s Site, r SiteRender) { + router := e.Group("v1") + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + { + h := func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderArticles(c, s.Articles()) + } + router.Handle("HEAD", "/articles/:category/", h) + router.Handle("POST", "/articles/:category/", h) + router.Handle("GET", "/articles/:category/", h) + } + + router.Handle("GET", "/index/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderIndex(c, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() gin.HandlersChain { + return nil +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderArticles(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} diff --git a/mirc/templates/gin/mirc/auto/api/v2/site.go.tmpl b/mirc/templates/gin/mirc/auto/api/v2/site.go.tmpl new file mode 100644 index 0000000..afbe119 --- /dev/null +++ b/mirc/templates/gin/mirc/auto/api/v2/site.go.tmpl @@ -0,0 +1,255 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v2 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" +) + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + Logout() mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogin(*gin.Context) (*LoginReq, mir.Error) + BindPrevTweets(*gin.Context) (*TweetsReq, mir.Error) + BindNextTweets(*gin.Context) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(*gin.Context, mir.Error) + RenderLogin(*gin.Context, *LoginResp, mir.Error) + RenderPrevTweets(*gin.Context, *TweetsResp, mir.Error) + RenderNextTweets(*gin.Context, *TweetsResp, mir.Error) + RenderArticles(*gin.Context, mir.Error) + RenderIndex(*gin.Context, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to gin +func RegisterSiteServant(e *gin.Engine, s Site, b SiteBinding, r SiteRender) { + router := e.Group("v2") + + // register routes info to router + router.Handle("POST", "/user/logout/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderLogout(c, s.Logout()) + }) + + router.Handle("POST", "/user/login/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(c, resp, err) + }) + + { + h := func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindPrevTweets(c) + if err != nil { + r.RenderPrevTweets(c, nil, err) + return + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(c, resp, err) + } + router.Handle("HEAD", "/tweets/prev", h) + router.Handle("GET", "/tweets/prev", h) + router.Handle("POST", "/tweets/prev", h) + } + + router.Any("/tweets/next", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindNextTweets(c) + if err != nil { + r.RenderNextTweets(c, nil, err) + return + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(c, resp, err) + }) + + router.Handle("GET", "/articles/:category/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderArticles(c, s.Articles()) + }) + + router.Handle("GET", "/index/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderIndex(c, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Logout() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(c *gin.Context, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(c *gin.Context, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(c *gin.Context) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(c *gin.Context) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/gin/mirc/main.go.tmpl b/mirc/templates/gin/mirc/main.go.tmpl new file mode 100644 index 0000000..a68c0a9 --- /dev/null +++ b/mirc/templates/gin/mirc/main.go.tmpl @@ -0,0 +1,26 @@ +package main + +import ( + "log" + + . "github.com/alimy/mir/v3/core" + . "github.com/alimy/mir/v3/engine" + + _ "{{ .PkgName }}/mirc/routes" + _ "{{ .PkgName }}/mirc/routes/v1" + _ "{{ .PkgName }}/mirc/routes/v2" +) + +//go:generate go run main.go +func main() { + log.Println("generate code start") + opts := Options{ + RunMode(InSerialMode), + GeneratorName(GeneratorGin), + SinkPath("auto"), + } + if err := Generate(opts); err != nil { + log.Fatal(err) + } + log.Println("generate code finish") +} diff --git a/mirc/templates/gin/mirc/routes/site.go.tmpl b/mirc/templates/gin/mirc/routes/site.go.tmpl new file mode 100644 index 0000000..2709138 --- /dev/null +++ b/mirc/templates/gin/mirc/routes/site.go.tmpl @@ -0,0 +1,65 @@ +package routes + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site interface info +type Site struct { + Chain Chain `mir:"-"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/:category/"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post, LogoutReq) `mir:"/user/logout/"` +} diff --git a/mirc/templates/gin/mirc/routes/v1/site.go.tmpl b/mirc/templates/gin/mirc/routes/v1/site.go.tmpl new file mode 100644 index 0000000..451c8bf --- /dev/null +++ b/mirc/templates/gin/mirc/routes/v1/site.go.tmpl @@ -0,0 +1,18 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +// Site site v1 interface info +type Site struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + Index func(Get) `mir:"/index/"` + Articles func(Head, Get, Post) `mir:"/articles/:category/"` +} diff --git a/mirc/templates/gin/mirc/routes/v2/site.go.tmpl b/mirc/templates/gin/mirc/routes/v2/site.go.tmpl new file mode 100644 index 0000000..502aeb5 --- /dev/null +++ b/mirc/templates/gin/mirc/routes/v2/site.go.tmpl @@ -0,0 +1,60 @@ +package v2 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site v2 interface info +type Site struct { + Group Group `mir:"v2"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/:category/"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post) `mir:"/user/logout/"` +} diff --git a/mirc/templates/gin/servants/core.go.tmpl b/mirc/templates/gin/servants/core.go.tmpl new file mode 100644 index 0000000..b063e1b --- /dev/null +++ b/mirc/templates/gin/servants/core.go.tmpl @@ -0,0 +1,23 @@ +package servants + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" +) + +func bindAny(c *gin.Context, obj any) mir.Error { + if err := c.ShouldBind(obj); err != nil { + mir.NewError(http.StatusBadRequest, err) + } + return nil +} + +func renderAny(c *gin.Context, data any, err mir.Error) { + if err == nil { + c.JSON(http.StatusOK, data) + } else { + c.JSON(err.StatusCode(), err.Error()) + } +} diff --git a/mirc/templates/gin/servants/servants.go.tmpl b/mirc/templates/gin/servants/servants.go.tmpl new file mode 100644 index 0000000..8c93af6 --- /dev/null +++ b/mirc/templates/gin/servants/servants.go.tmpl @@ -0,0 +1,15 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" + v1 "{{ .PkgName }}/mirc/auto/api/v1" + v2 "{{ .PkgName }}/mirc/auto/api/v2" + "github.com/gin-gonic/gin" +) + +// RegisterServants register all the servants to gin.Engine +func RegisterServants(e *gin.Engine) { + api.RegisterSiteServant(e, newSiteSrv(), newSiteBinding(), newSiteRender()) + v1.RegisterSiteServant(e, newSiteV1Srv(), newSiteV1Render()) + v2.RegisterSiteServant(e, newSiteV2Srv(), newSiteV2Binding(), newSiteV2Render()) +} diff --git a/mirc/templates/gin/servants/site.go.tmpl b/mirc/templates/gin/servants/site.go.tmpl new file mode 100644 index 0000000..0912d5f --- /dev/null +++ b/mirc/templates/gin/servants/site.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" +) + +type siteSrv struct { + api.UnimplementedSiteServant +} + +type siteBinding struct { + *api.UnimplementedSiteBinding +} + +type siteRender struct { + *api.UnimplementedSiteRender +} + +func newSiteSrv() api.Site { + return &siteSrv{} +} + +func newSiteBinding() api.SiteBinding { + return &siteBinding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteRender() api.SiteRender { + return &siteRender{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/gin/servants/site_v1.go.tmpl b/mirc/templates/gin/servants/site_v1.go.tmpl new file mode 100644 index 0000000..98a0a8b --- /dev/null +++ b/mirc/templates/gin/servants/site_v1.go.tmpl @@ -0,0 +1,25 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v1" +) + +type siteV1Srv struct { + api.UnimplementedSiteServant +} + +type siteV1Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV1Srv() api.Site { + return &siteV1Srv{} +} + +func newSiteV1Render() api.SiteRender { + return &siteV1Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/gin/servants/site_v2.go.tmpl b/mirc/templates/gin/servants/site_v2.go.tmpl new file mode 100644 index 0000000..4fb76aa --- /dev/null +++ b/mirc/templates/gin/servants/site_v2.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v2" +) + +type siteV2Srv struct { + api.UnimplementedSiteServant +} + +type siteV2Binding struct { + *api.UnimplementedSiteBinding +} + +type siteV2Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV2Srv() api.Site { + return &siteV2Srv{} +} + +func newSiteV2Binding() api.SiteBinding { + return &siteV2Binding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteV2Render() api.SiteRender { + return &siteV2Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/hertz/.gitignore.tmpl b/mirc/templates/hertz/.gitignore.tmpl new file mode 100644 index 0000000..96ffcd3 --- /dev/null +++ b/mirc/templates/hertz/.gitignore.tmpl @@ -0,0 +1,25 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +coverage.out +count.out +test +profile.out +tmp.out + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# GoLand project files +.idea/ +*.iml + +# VS Code +.vscode diff --git a/mirc/templates/hertz/Makefile.tmpl b/mirc/templates/hertz/Makefile.tmpl new file mode 100644 index 0000000..9616a42 --- /dev/null +++ b/mirc/templates/hertz/Makefile.tmpl @@ -0,0 +1,27 @@ +GOFMT ?= gofmt -s -w +GOFILES := $(shell find . -name "*.go" -type f) + +.PHONY: default +default: run + +.PHONY: build +build: fmt + go build -o mir-examples main.go + +.PHONY: build +run: fmt + go run main.go + +.PHONY: mod-tidy +mod-tidy: + @go mod download + @go mod tidy + +.PHONY: generate +generate: + @go generate mirc/main.go + @$(GOFMT) ./ + +.PHONY: fmt +fmt: + $(GOFMT) $(GOFILES) diff --git a/mirc/templates/hertz/README.md.tmpl b/mirc/templates/hertz/README.md.tmpl new file mode 100644 index 0000000..5bf9de3 --- /dev/null +++ b/mirc/templates/hertz/README.md.tmpl @@ -0,0 +1,8 @@ +## mir-examples +just a simple mir's examples for explain how to use mir in your project. + +#### Usage +```bash +% make generate +% make build +``` diff --git a/mirc/templates/hertz/go.mod.tmpl b/mirc/templates/hertz/go.mod.tmpl new file mode 100644 index 0000000..d9671ba --- /dev/null +++ b/mirc/templates/hertz/go.mod.tmpl @@ -0,0 +1,36 @@ +module {{ .PkgName }} + +go 1.18 + +require ( + github.com/alimy/mir/v3 v3.0.0 + github.com/cloudwego/hertz v0.4.2 +) + +require ( + github.com/bytedance/go-tagexpr/v2 v2.9.2 // indirect + github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7 // indirect + github.com/bytedance/sonic v1.5.0 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06 // indirect + github.com/cloudwego/netpoll v0.3.1 // indirect + github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/golang/protobuf v1.5.0 // indirect + github.com/henrylee2cn/ameda v1.4.10 // indirect + github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8 // indirect + github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/nyaruka/phonenumbers v1.0.55 // indirect + github.com/stretchr/testify v1.7.1 // indirect + github.com/tidwall/gjson v1.13.0 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect + golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect + google.golang.org/protobuf v1.28.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect +) +{{if notEmptyStr .MirPkgName }} +replace ( + github.com/alimy/mir/v3 => {{ .MirPkgName }} +) +{{end}} diff --git a/mirc/templates/hertz/go.sum.tmpl b/mirc/templates/hertz/go.sum.tmpl new file mode 100644 index 0000000..8f9147c --- /dev/null +++ b/mirc/templates/hertz/go.sum.tmpl @@ -0,0 +1,66 @@ +github.com/bytedance/go-tagexpr/v2 v2.9.2 h1:QySJaAIQgOEDQBLS3x9BxOWrnhqu5sQ+f6HaZIxD39I= +github.com/bytedance/go-tagexpr/v2 v2.9.2/go.mod h1:5qsx05dYOiUXOUgnQ7w3Oz8BYs2qtM/bJokdLb79wRM= +github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7 h1:PtwsQyQJGxf8iaPptPNaduEIu9BnrNms+pcRdHAxZaM= +github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7/go.mod h1:2ZlV9BaUH4+NXIBF0aMdKKAnHTzqH+iMU4KUjAbL23Q= +github.com/bytedance/sonic v1.5.0 h1:XWdTi8bwPgxIML+eNV1IwNuTROK6EUrQ65ey8yd6fRQ= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06 h1:1sDoSuDPWzhkdzNVxCxtIaKiAe96ESVPv8coGwc1gZ4= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/cloudwego/hertz v0.4.2 h1:Ntfs5MdPoKeFSbyStU2drM4CizOkEfYWsB9s1Q3taPY= +github.com/cloudwego/hertz v0.4.2/go.mod h1:K1U0RlU07CDeBINfHNbafH/3j9uSgIW8otbjUys3OPY= +github.com/cloudwego/netpoll v0.3.1 h1:xByoORmCLIyKZ8gS+da06WDo3j+jvmhaqS2KeKejtBk= +github.com/cloudwego/netpoll v0.3.1/go.mod h1:1T2WVuQ+MQw6h6DpE45MohSvDTKdy2DlzCx2KsnPI4E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/henrylee2cn/ameda v1.4.8/go.mod h1:liZulR8DgHxdK+MEwvZIylGnmcjzQ6N6f2PlWe7nEO4= +github.com/henrylee2cn/ameda v1.4.10 h1:JdvI2Ekq7tapdPsuhrc4CaFiqw6QXFvZIULWJgQyCAk= +github.com/henrylee2cn/ameda v1.4.10/go.mod h1:liZulR8DgHxdK+MEwvZIylGnmcjzQ6N6f2PlWe7nEO4= +github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8 h1:yE9ULgp02BhYIrO6sdV/FPe0xQM6fNHkVQW2IAymfM0= +github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8/go.mod h1:Nhe/DM3671a5udlv2AdV2ni/MZzgfv2qrPL5nIi3EGQ= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/nyaruka/phonenumbers v1.0.55 h1:bj0nTO88Y68KeUQ/n3Lo2KgK7lM1hF7L9NFuwcCl3yg= +github.com/nyaruka/phonenumbers v1.0.55/go.mod h1:sDaTZ/KPX5f8qyV9qN+hIm+4ZBARJrupC6LuhshJq1U= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.13.0 h1:3TFY9yxOQShrvmjdM76K+jc66zJeT6D3/VFFYCGQf7M= +github.com/tidwall/gjson v1.13.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20220110181412-a018aaa089fe/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/mirc/templates/hertz/main.go.tmpl b/mirc/templates/hertz/main.go.tmpl new file mode 100644 index 0000000..596cde5 --- /dev/null +++ b/mirc/templates/hertz/main.go.tmpl @@ -0,0 +1,16 @@ +package main + +import ( + "{{ .PkgName }}/servants" + "github.com/cloudwego/hertz/pkg/app/server" +) + +func main() { + h := server.Default() + + // register servants to hertz + servants.RegisterServants(h.Engine) + + // start servant service + h.Spin() +} diff --git a/mirc/templates/hertz/mirc/auto/api/site.go.tmpl b/mirc/templates/hertz/mirc/auto/api/site.go.tmpl new file mode 100644 index 0000000..d7160cf --- /dev/null +++ b/mirc/templates/hertz/mirc/auto/api/site.go.tmpl @@ -0,0 +1,284 @@ +// Code generated by go-mir. DO NOT EDIT. + +package api + +import ( + "context" + "net/http" + + "github.com/alimy/mir/v3" + "github.com/cloudwego/hertz/pkg/app" + "github.com/cloudwego/hertz/pkg/route" +) + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + // Chain provide handlers chain for hertz + Chain() []app.HandlerFunc + + Logout(*LogoutReq) mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogout(*app.RequestContext) (*LogoutReq, mir.Error) + BindLogin(*app.RequestContext) (*LoginReq, mir.Error) + BindPrevTweets(*app.RequestContext) (*TweetsReq, mir.Error) + BindNextTweets(*app.RequestContext) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(*app.RequestContext, mir.Error) + RenderLogin(*app.RequestContext, *LoginResp, mir.Error) + RenderPrevTweets(*app.RequestContext, *TweetsResp, mir.Error) + RenderNextTweets(*app.RequestContext, *TweetsResp, mir.Error) + RenderArticles(*app.RequestContext, mir.Error) + RenderIndex(*app.RequestContext, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to hertz +func RegisterSiteServant(e *route.Engine, s Site, b SiteBinding, r SiteRender) { + router := e + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Handle("POST", "/user/logout/", func(c context.Context, ctx *app.RequestContext) { + select { + case <-c.Done(): + return + default: + } + + req, err := b.BindLogout(ctx) + if err != nil { + r.RenderLogout(ctx, err) + return + } + r.RenderLogout(ctx, s.Logout(req)) + }) + + router.Handle("POST", "/user/login/", func(c context.Context, ctx *app.RequestContext) { + select { + case <-c.Done(): + return + default: + } + + req, err := b.BindLogin(ctx) + if err != nil { + r.RenderLogin(ctx, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(ctx, resp, err) + }) + + { + h := func(c context.Context, ctx *app.RequestContext) { + select { + case <-c.Done(): + return + default: + } + + req, err := b.BindPrevTweets(ctx) + if err != nil { + r.RenderPrevTweets(ctx, nil, err) + return + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(ctx, resp, err) + } + router.Handle("HEAD", "/tweets/prev", h) + router.Handle("GET", "/tweets/prev", h) + router.Handle("POST", "/tweets/prev", h) + } + + router.Any("/tweets/next", func(c context.Context, ctx *app.RequestContext) { + select { + case <-c.Done(): + return + default: + } + + req, err := b.BindNextTweets(ctx) + if err != nil { + r.RenderNextTweets(ctx, nil, err) + return + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(ctx, resp, err) + }) + + router.Handle("GET", "/articles/:category/", func(c context.Context, ctx *app.RequestContext) { + select { + case <-c.Done(): + return + default: + } + + r.RenderArticles(ctx, s.Articles()) + }) + + router.Handle("GET", "/index/", func(c context.Context, ctx *app.RequestContext) { + select { + case <-c.Done(): + return + default: + } + + r.RenderIndex(ctx, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() []app.HandlerFunc { + return nil +} + +func (UnimplementedSiteServant) Logout(req *LogoutReq) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(*app.RequestContext, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(ctx *app.RequestContext, err mir.Error) { + r.RenderAny(ctx, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(ctx *app.RequestContext, data *LoginResp, err mir.Error) { + r.RenderAny(ctx, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(ctx *app.RequestContext, data *TweetsResp, err mir.Error) { + r.RenderAny(ctx, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(ctx *app.RequestContext, data *TweetsResp, err mir.Error) { + r.RenderAny(ctx, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(ctx *app.RequestContext, err mir.Error) { + r.RenderAny(ctx, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(ctx *app.RequestContext, err mir.Error) { + r.RenderAny(ctx, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(*app.RequestContext, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogout(ctx *app.RequestContext) (*LogoutReq, mir.Error) { + obj := new(LogoutReq) + err := b.BindAny(ctx, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindLogin(ctx *app.RequestContext) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(ctx, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(ctx *app.RequestContext) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(ctx, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(ctx *app.RequestContext) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(ctx, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/hertz/mirc/auto/api/v1/site.go.tmpl b/mirc/templates/hertz/mirc/auto/api/v1/site.go.tmpl new file mode 100644 index 0000000..9a718e9 --- /dev/null +++ b/mirc/templates/hertz/mirc/auto/api/v1/site.go.tmpl @@ -0,0 +1,97 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "context" + "net/http" + + "github.com/alimy/mir/v3" + "github.com/cloudwego/hertz/pkg/app" + "github.com/cloudwego/hertz/pkg/route" +) + +type Site interface { + // Chain provide handlers chain for hertz + Chain() []app.HandlerFunc + + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteRender interface { + RenderArticles(*app.RequestContext, mir.Error) + RenderIndex(*app.RequestContext, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to hertz +func RegisterSiteServant(e *route.Engine, s Site, r SiteRender) { + router := e.Group("v1") + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + { + h := func(c context.Context, ctx *app.RequestContext) { + select { + case <-c.Done(): + return + default: + } + + r.RenderArticles(ctx, s.Articles()) + } + router.Handle("POST", "/articles/:category/", h) + router.Handle("GET", "/articles/:category/", h) + router.Handle("HEAD", "/articles/:category/", h) + } + + router.Handle("GET", "/index/", func(c context.Context, ctx *app.RequestContext) { + select { + case <-c.Done(): + return + default: + } + + r.RenderIndex(ctx, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() []app.HandlerFunc { + return nil +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(*app.RequestContext, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderArticles(ctx *app.RequestContext, err mir.Error) { + r.RenderAny(ctx, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(ctx *app.RequestContext, err mir.Error) { + r.RenderAny(ctx, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} diff --git a/mirc/templates/hertz/mirc/auto/api/v2/site.go.tmpl b/mirc/templates/hertz/mirc/auto/api/v2/site.go.tmpl new file mode 100644 index 0000000..7640481 --- /dev/null +++ b/mirc/templates/hertz/mirc/auto/api/v2/site.go.tmpl @@ -0,0 +1,257 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v2 + +import ( + "context" + "net/http" + + "github.com/alimy/mir/v3" + "github.com/cloudwego/hertz/pkg/app" + "github.com/cloudwego/hertz/pkg/route" +) + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + Logout() mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogin(*app.RequestContext) (*LoginReq, mir.Error) + BindPrevTweets(*app.RequestContext) (*TweetsReq, mir.Error) + BindNextTweets(*app.RequestContext) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(*app.RequestContext, mir.Error) + RenderLogin(*app.RequestContext, *LoginResp, mir.Error) + RenderPrevTweets(*app.RequestContext, *TweetsResp, mir.Error) + RenderNextTweets(*app.RequestContext, *TweetsResp, mir.Error) + RenderArticles(*app.RequestContext, mir.Error) + RenderIndex(*app.RequestContext, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to hertz +func RegisterSiteServant(e *route.Engine, s Site, b SiteBinding, r SiteRender) { + router := e.Group("v2") + + // register routes info to router + router.Handle("POST", "/user/logout/", func(c context.Context, ctx *app.RequestContext) { + select { + case <-c.Done(): + return + default: + } + + r.RenderLogout(ctx, s.Logout()) + }) + + router.Handle("POST", "/user/login/", func(c context.Context, ctx *app.RequestContext) { + select { + case <-c.Done(): + return + default: + } + + req, err := b.BindLogin(ctx) + if err != nil { + r.RenderLogin(ctx, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(ctx, resp, err) + }) + + { + h := func(c context.Context, ctx *app.RequestContext) { + select { + case <-c.Done(): + return + default: + } + + req, err := b.BindPrevTweets(ctx) + if err != nil { + r.RenderPrevTweets(ctx, nil, err) + return + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(ctx, resp, err) + } + router.Handle("HEAD", "/tweets/prev", h) + router.Handle("GET", "/tweets/prev", h) + router.Handle("POST", "/tweets/prev", h) + } + + router.Any("/tweets/next", func(c context.Context, ctx *app.RequestContext) { + select { + case <-c.Done(): + return + default: + } + + req, err := b.BindNextTweets(ctx) + if err != nil { + r.RenderNextTweets(ctx, nil, err) + return + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(ctx, resp, err) + }) + + router.Handle("GET", "/articles/:category/", func(c context.Context, ctx *app.RequestContext) { + select { + case <-c.Done(): + return + default: + } + + r.RenderArticles(ctx, s.Articles()) + }) + + router.Handle("GET", "/index/", func(c context.Context, ctx *app.RequestContext) { + select { + case <-c.Done(): + return + default: + } + + r.RenderIndex(ctx, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Logout() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(*app.RequestContext, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(ctx *app.RequestContext, err mir.Error) { + r.RenderAny(ctx, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(ctx *app.RequestContext, data *LoginResp, err mir.Error) { + r.RenderAny(ctx, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(ctx *app.RequestContext, data *TweetsResp, err mir.Error) { + r.RenderAny(ctx, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(ctx *app.RequestContext, data *TweetsResp, err mir.Error) { + r.RenderAny(ctx, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(ctx *app.RequestContext, err mir.Error) { + r.RenderAny(ctx, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(ctx *app.RequestContext, err mir.Error) { + r.RenderAny(ctx, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(*app.RequestContext, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogin(ctx *app.RequestContext) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(ctx, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(ctx *app.RequestContext) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(ctx, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(ctx *app.RequestContext) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(ctx, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/hertz/mirc/main.go.tmpl b/mirc/templates/hertz/mirc/main.go.tmpl new file mode 100644 index 0000000..5814560 --- /dev/null +++ b/mirc/templates/hertz/mirc/main.go.tmpl @@ -0,0 +1,26 @@ +package main + +import ( + "log" + + . "github.com/alimy/mir/v3/core" + . "github.com/alimy/mir/v3/engine" + + _ "{{ .PkgName }}/mirc/routes" + _ "{{ .PkgName }}/mirc/routes/v1" + _ "{{ .PkgName }}/mirc/routes/v2" +) + +//go:generate go run main.go +func main() { + log.Println("generate code start") + opts := Options{ + RunMode(InSerialMode), + GeneratorName(GeneratorHertz), + SinkPath("auto"), + } + if err := Generate(opts); err != nil { + log.Fatal(err) + } + log.Println("generate code finish") +} diff --git a/mirc/templates/hertz/mirc/routes/site.go.tmpl b/mirc/templates/hertz/mirc/routes/site.go.tmpl new file mode 100644 index 0000000..2709138 --- /dev/null +++ b/mirc/templates/hertz/mirc/routes/site.go.tmpl @@ -0,0 +1,65 @@ +package routes + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site interface info +type Site struct { + Chain Chain `mir:"-"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/:category/"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post, LogoutReq) `mir:"/user/logout/"` +} diff --git a/mirc/templates/hertz/mirc/routes/v1/site.go.tmpl b/mirc/templates/hertz/mirc/routes/v1/site.go.tmpl new file mode 100644 index 0000000..451c8bf --- /dev/null +++ b/mirc/templates/hertz/mirc/routes/v1/site.go.tmpl @@ -0,0 +1,18 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +// Site site v1 interface info +type Site struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + Index func(Get) `mir:"/index/"` + Articles func(Head, Get, Post) `mir:"/articles/:category/"` +} diff --git a/mirc/templates/hertz/mirc/routes/v2/site.go.tmpl b/mirc/templates/hertz/mirc/routes/v2/site.go.tmpl new file mode 100644 index 0000000..502aeb5 --- /dev/null +++ b/mirc/templates/hertz/mirc/routes/v2/site.go.tmpl @@ -0,0 +1,60 @@ +package v2 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site v2 interface info +type Site struct { + Group Group `mir:"v2"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/:category/"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post) `mir:"/user/logout/"` +} diff --git a/mirc/templates/hertz/servants/core.go.tmpl b/mirc/templates/hertz/servants/core.go.tmpl new file mode 100644 index 0000000..71442cb --- /dev/null +++ b/mirc/templates/hertz/servants/core.go.tmpl @@ -0,0 +1,22 @@ +package servants + +import ( + "errors" + "net/http" + + "github.com/alimy/mir/v3" + "github.com/cloudwego/hertz/pkg/app" + "github.com/cloudwego/hertz/pkg/protocol/consts" +) + +func bindAny(ctx *app.RequestContext, obj any) mir.Error { + return mir.NewError(http.StatusBadRequest, errors.New("method not implemented")) +} + +func renderAny(ctx *app.RequestContext, data any, err mir.Error) { + if err == nil { + ctx.JSON(consts.StatusOK, data) + } else { + ctx.JSON(err.StatusCode(), err.Error()) + } +} diff --git a/mirc/templates/hertz/servants/servants.go.tmpl b/mirc/templates/hertz/servants/servants.go.tmpl new file mode 100644 index 0000000..5458c0e --- /dev/null +++ b/mirc/templates/hertz/servants/servants.go.tmpl @@ -0,0 +1,15 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" + v1 "{{ .PkgName }}/mirc/auto/api/v1" + v2 "{{ .PkgName }}/mirc/auto/api/v2" + "github.com/cloudwego/hertz/pkg/route" +) + +// RegisterServants register all the servants to hertz +func RegisterServants(e *route.Engine) { + api.RegisterSiteServant(e, newSiteSrv(), newSiteBinding(), newSiteRender()) + v1.RegisterSiteServant(e, newSiteV1Srv(), newSiteV1Render()) + v2.RegisterSiteServant(e, newSiteV2Srv(), newSiteV2Binding(), newSiteV2Render()) +} diff --git a/mirc/templates/hertz/servants/site.go.tmpl b/mirc/templates/hertz/servants/site.go.tmpl new file mode 100644 index 0000000..0912d5f --- /dev/null +++ b/mirc/templates/hertz/servants/site.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" +) + +type siteSrv struct { + api.UnimplementedSiteServant +} + +type siteBinding struct { + *api.UnimplementedSiteBinding +} + +type siteRender struct { + *api.UnimplementedSiteRender +} + +func newSiteSrv() api.Site { + return &siteSrv{} +} + +func newSiteBinding() api.SiteBinding { + return &siteBinding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteRender() api.SiteRender { + return &siteRender{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/hertz/servants/site_v1.go.tmpl b/mirc/templates/hertz/servants/site_v1.go.tmpl new file mode 100644 index 0000000..98a0a8b --- /dev/null +++ b/mirc/templates/hertz/servants/site_v1.go.tmpl @@ -0,0 +1,25 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v1" +) + +type siteV1Srv struct { + api.UnimplementedSiteServant +} + +type siteV1Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV1Srv() api.Site { + return &siteV1Srv{} +} + +func newSiteV1Render() api.SiteRender { + return &siteV1Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/hertz/servants/site_v2.go.tmpl b/mirc/templates/hertz/servants/site_v2.go.tmpl new file mode 100644 index 0000000..4fb76aa --- /dev/null +++ b/mirc/templates/hertz/servants/site_v2.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v2" +) + +type siteV2Srv struct { + api.UnimplementedSiteServant +} + +type siteV2Binding struct { + *api.UnimplementedSiteBinding +} + +type siteV2Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV2Srv() api.Site { + return &siteV2Srv{} +} + +func newSiteV2Binding() api.SiteBinding { + return &siteV2Binding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteV2Render() api.SiteRender { + return &siteV2Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/httprouter/.gitignore.tmpl b/mirc/templates/httprouter/.gitignore.tmpl new file mode 100644 index 0000000..96ffcd3 --- /dev/null +++ b/mirc/templates/httprouter/.gitignore.tmpl @@ -0,0 +1,25 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +coverage.out +count.out +test +profile.out +tmp.out + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# GoLand project files +.idea/ +*.iml + +# VS Code +.vscode diff --git a/mirc/templates/httprouter/Makefile.tmpl b/mirc/templates/httprouter/Makefile.tmpl new file mode 100644 index 0000000..9616a42 --- /dev/null +++ b/mirc/templates/httprouter/Makefile.tmpl @@ -0,0 +1,27 @@ +GOFMT ?= gofmt -s -w +GOFILES := $(shell find . -name "*.go" -type f) + +.PHONY: default +default: run + +.PHONY: build +build: fmt + go build -o mir-examples main.go + +.PHONY: build +run: fmt + go run main.go + +.PHONY: mod-tidy +mod-tidy: + @go mod download + @go mod tidy + +.PHONY: generate +generate: + @go generate mirc/main.go + @$(GOFMT) ./ + +.PHONY: fmt +fmt: + $(GOFMT) $(GOFILES) diff --git a/mirc/templates/httprouter/README.md.tmpl b/mirc/templates/httprouter/README.md.tmpl new file mode 100644 index 0000000..5bf9de3 --- /dev/null +++ b/mirc/templates/httprouter/README.md.tmpl @@ -0,0 +1,8 @@ +## mir-examples +just a simple mir's examples for explain how to use mir in your project. + +#### Usage +```bash +% make generate +% make build +``` diff --git a/mirc/templates/httprouter/go.mod.tmpl b/mirc/templates/httprouter/go.mod.tmpl new file mode 100644 index 0000000..42e0094 --- /dev/null +++ b/mirc/templates/httprouter/go.mod.tmpl @@ -0,0 +1,13 @@ +module {{ .PkgName }} + +go 1.18 + +require ( + github.com/alimy/mir/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 +) +{{if notEmptyStr .MirPkgName }} +replace ( + github.com/alimy/mir/v3 => {{ .MirPkgName }} +) +{{end}} diff --git a/mirc/templates/httprouter/go.sum.tmpl b/mirc/templates/httprouter/go.sum.tmpl new file mode 100644 index 0000000..096c54e --- /dev/null +++ b/mirc/templates/httprouter/go.sum.tmpl @@ -0,0 +1,2 @@ +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= diff --git a/mirc/templates/httprouter/main.go.tmpl b/mirc/templates/httprouter/main.go.tmpl new file mode 100644 index 0000000..fa91ce4 --- /dev/null +++ b/mirc/templates/httprouter/main.go.tmpl @@ -0,0 +1,21 @@ +package main + +import ( + "log" + "net/http" + + "{{ .PkgName }}/servants" + "github.com/julienschmidt/httprouter" +) + +func main() { + r := httprouter.New() + + // register servants to httprouter + servants.RegisterServants(r) + + // start servant service + if err := http.ListenAndServe(":8080", r); err != nil { + log.Fatal(err) + } +} diff --git a/mirc/templates/httprouter/mirc/auto/api/site.go.tmpl b/mirc/templates/httprouter/mirc/auto/api/site.go.tmpl new file mode 100644 index 0000000..8c7359a --- /dev/null +++ b/mirc/templates/httprouter/mirc/auto/api/site.go.tmpl @@ -0,0 +1,280 @@ +// Code generated by go-mir. DO NOT EDIT. + +package api + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/julienschmidt/httprouter" +) + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + Logout(*LogoutReq) mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogout(*http.Request, httprouter.Params) (*LogoutReq, mir.Error) + BindLogin(*http.Request, httprouter.Params) (*LoginReq, mir.Error) + BindPrevTweets(*http.Request, httprouter.Params) (*TweetsReq, mir.Error) + BindNextTweets(*http.Request, httprouter.Params) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(http.ResponseWriter, mir.Error) + RenderLogin(http.ResponseWriter, *LoginResp, mir.Error) + RenderPrevTweets(http.ResponseWriter, *TweetsResp, mir.Error) + RenderNextTweets(http.ResponseWriter, *TweetsResp, mir.Error) + RenderArticles(http.ResponseWriter, mir.Error) + RenderIndex(http.ResponseWriter, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to httprouter +func RegisterSiteServant(router *httprouter.Router, s Site, b SiteBinding, r SiteRender) { + router.Handle("POST", "/user/logout/", func(rw http.ResponseWriter, hr *http.Request, p httprouter.Params) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindLogout(hr, p) + if err != nil { + r.RenderLogout(rw, err) + return + } + r.RenderLogout(rw, s.Logout(req)) + }) + + router.Handle("POST", "/user/login/", func(rw http.ResponseWriter, hr *http.Request, p httprouter.Params) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindLogin(hr, p) + if err != nil { + r.RenderLogin(rw, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(rw, resp, err) + }) + + { + h := func(rw http.ResponseWriter, hr *http.Request, p httprouter.Params) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindPrevTweets(hr, p) + if err != nil { + r.RenderPrevTweets(rw, nil, err) + return + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(rw, resp, err) + } + router.Handle("POST", "/tweets/prev", h) + router.Handle("HEAD", "/tweets/prev", h) + router.Handle("GET", "/tweets/prev", h) + } + + { + h := func(rw http.ResponseWriter, hr *http.Request, p httprouter.Params) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindNextTweets(hr, p) + if err != nil { + r.RenderNextTweets(rw, nil, err) + return + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(rw, resp, err) + } + router.Handle("GET", "/tweets/next", h) + router.Handle("OPTIONS", "/tweets/next", h) + router.Handle("TRACE", "/tweets/next", h) + router.Handle("HEAD", "/tweets/next", h) + router.Handle("POST", "/tweets/next", h) + router.Handle("PUT", "/tweets/next", h) + router.Handle("PATCH", "/tweets/next", h) + router.Handle("DELETE", "/tweets/next", h) + router.Handle("CONNECT", "/tweets/next", h) + } + + router.Handle("GET", "/articles/:category/", func(rw http.ResponseWriter, hr *http.Request, p httprouter.Params) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderArticles(rw, s.Articles()) + }) + + router.Handle("GET", "/index/", func(rw http.ResponseWriter, hr *http.Request, p httprouter.Params) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderIndex(rw, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Logout(req *LogoutReq) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(http.ResponseWriter, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(w http.ResponseWriter, data *LoginResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(w http.ResponseWriter, data *TweetsResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(w http.ResponseWriter, data *TweetsResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(*http.Request, httprouter.Params, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogout(r *http.Request, p httprouter.Params) (*LogoutReq, mir.Error) { + obj := new(LogoutReq) + err := b.BindAny(r, p, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindLogin(r *http.Request, p httprouter.Params) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(r, p, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(r *http.Request, p httprouter.Params) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(r, p, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(r *http.Request, p httprouter.Params) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(r, p, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/httprouter/mirc/auto/api/v1/site.go.tmpl b/mirc/templates/httprouter/mirc/auto/api/v1/site.go.tmpl new file mode 100644 index 0000000..352c639 --- /dev/null +++ b/mirc/templates/httprouter/mirc/auto/api/v1/site.go.tmpl @@ -0,0 +1,82 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/julienschmidt/httprouter" +) + +type Site interface { + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteRender interface { + RenderArticles(http.ResponseWriter, mir.Error) + RenderIndex(http.ResponseWriter, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to httprouter +func RegisterSiteServant(router *httprouter.Router, s Site, r SiteRender) { + { + h := func(rw http.ResponseWriter, hr *http.Request, p httprouter.Params) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderArticles(rw, s.Articles()) + } + router.Handle("POST", "/v1/articles/:category/", h) + router.Handle("GET", "/v1/articles/:category/", h) + router.Handle("HEAD", "/v1/articles/:category/", h) + } + + router.Handle("GET", "/v1/index/", func(rw http.ResponseWriter, hr *http.Request, p httprouter.Params) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderIndex(rw, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(http.ResponseWriter, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderArticles(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} diff --git a/mirc/templates/httprouter/mirc/auto/api/v2/site.go.tmpl b/mirc/templates/httprouter/mirc/auto/api/v2/site.go.tmpl new file mode 100644 index 0000000..cc0f7ac --- /dev/null +++ b/mirc/templates/httprouter/mirc/auto/api/v2/site.go.tmpl @@ -0,0 +1,263 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v2 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/julienschmidt/httprouter" +) + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + Logout() mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogin(*http.Request, httprouter.Params) (*LoginReq, mir.Error) + BindPrevTweets(*http.Request, httprouter.Params) (*TweetsReq, mir.Error) + BindNextTweets(*http.Request, httprouter.Params) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(http.ResponseWriter, mir.Error) + RenderLogin(http.ResponseWriter, *LoginResp, mir.Error) + RenderPrevTweets(http.ResponseWriter, *TweetsResp, mir.Error) + RenderNextTweets(http.ResponseWriter, *TweetsResp, mir.Error) + RenderArticles(http.ResponseWriter, mir.Error) + RenderIndex(http.ResponseWriter, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to httprouter +func RegisterSiteServant(router *httprouter.Router, s Site, b SiteBinding, r SiteRender) { + router.Handle("POST", "/v2/user/logout/", func(rw http.ResponseWriter, hr *http.Request, p httprouter.Params) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderLogout(rw, s.Logout()) + }) + + router.Handle("POST", "/v2/user/login/", func(rw http.ResponseWriter, hr *http.Request, p httprouter.Params) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindLogin(hr, p) + if err != nil { + r.RenderLogin(rw, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(rw, resp, err) + }) + + { + h := func(rw http.ResponseWriter, hr *http.Request, p httprouter.Params) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindPrevTweets(hr, p) + if err != nil { + r.RenderPrevTweets(rw, nil, err) + return + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(rw, resp, err) + } + router.Handle("POST", "/v2/tweets/prev", h) + router.Handle("HEAD", "/v2/tweets/prev", h) + router.Handle("GET", "/v2/tweets/prev", h) + } + + { + h := func(rw http.ResponseWriter, hr *http.Request, p httprouter.Params) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindNextTweets(hr, p) + if err != nil { + r.RenderNextTweets(rw, nil, err) + return + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(rw, resp, err) + } + router.Handle("CONNECT", "/v2/tweets/next", h) + router.Handle("GET", "/v2/tweets/next", h) + router.Handle("POST", "/v2/tweets/next", h) + router.Handle("PUT", "/v2/tweets/next", h) + router.Handle("OPTIONS", "/v2/tweets/next", h) + router.Handle("TRACE", "/v2/tweets/next", h) + router.Handle("HEAD", "/v2/tweets/next", h) + router.Handle("PATCH", "/v2/tweets/next", h) + router.Handle("DELETE", "/v2/tweets/next", h) + } + + router.Handle("GET", "/v2/articles/:category/", func(rw http.ResponseWriter, hr *http.Request, p httprouter.Params) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderArticles(rw, s.Articles()) + }) + + router.Handle("GET", "/v2/index/", func(rw http.ResponseWriter, hr *http.Request, p httprouter.Params) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderIndex(rw, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Logout() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(http.ResponseWriter, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(w http.ResponseWriter, data *LoginResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(w http.ResponseWriter, data *TweetsResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(w http.ResponseWriter, data *TweetsResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(*http.Request, httprouter.Params, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogin(r *http.Request, p httprouter.Params) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(r, p, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(r *http.Request, p httprouter.Params) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(r, p, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(r *http.Request, p httprouter.Params) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(r, p, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/httprouter/mirc/main.go.tmpl b/mirc/templates/httprouter/mirc/main.go.tmpl new file mode 100644 index 0000000..4baacea --- /dev/null +++ b/mirc/templates/httprouter/mirc/main.go.tmpl @@ -0,0 +1,26 @@ +package main + +import ( + "log" + + . "github.com/alimy/mir/v3/core" + . "github.com/alimy/mir/v3/engine" + + _ "{{ .PkgName }}/mirc/routes" + _ "{{ .PkgName }}/mirc/routes/v1" + _ "{{ .PkgName }}/mirc/routes/v2" +) + +//go:generate go run main.go +func main() { + log.Println("generate code start") + opts := Options{ + RunMode(InSerialMode), + GeneratorName(GeneratorHttpRouter), + SinkPath("auto"), + } + if err := Generate(opts); err != nil { + log.Fatal(err) + } + log.Println("generate code finish") +} diff --git a/mirc/templates/httprouter/mirc/routes/site.go.tmpl b/mirc/templates/httprouter/mirc/routes/site.go.tmpl new file mode 100644 index 0000000..2709138 --- /dev/null +++ b/mirc/templates/httprouter/mirc/routes/site.go.tmpl @@ -0,0 +1,65 @@ +package routes + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site interface info +type Site struct { + Chain Chain `mir:"-"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/:category/"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post, LogoutReq) `mir:"/user/logout/"` +} diff --git a/mirc/templates/httprouter/mirc/routes/v1/site.go.tmpl b/mirc/templates/httprouter/mirc/routes/v1/site.go.tmpl new file mode 100644 index 0000000..451c8bf --- /dev/null +++ b/mirc/templates/httprouter/mirc/routes/v1/site.go.tmpl @@ -0,0 +1,18 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +// Site site v1 interface info +type Site struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + Index func(Get) `mir:"/index/"` + Articles func(Head, Get, Post) `mir:"/articles/:category/"` +} diff --git a/mirc/templates/httprouter/mirc/routes/v2/site.go.tmpl b/mirc/templates/httprouter/mirc/routes/v2/site.go.tmpl new file mode 100644 index 0000000..502aeb5 --- /dev/null +++ b/mirc/templates/httprouter/mirc/routes/v2/site.go.tmpl @@ -0,0 +1,60 @@ +package v2 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site v2 interface info +type Site struct { + Group Group `mir:"v2"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/:category/"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post) `mir:"/user/logout/"` +} diff --git a/mirc/templates/httprouter/servants/core.go.tmpl b/mirc/templates/httprouter/servants/core.go.tmpl new file mode 100644 index 0000000..9b35bdd --- /dev/null +++ b/mirc/templates/httprouter/servants/core.go.tmpl @@ -0,0 +1,18 @@ +package servants + +import ( + "errors" + "net/http" + + "github.com/alimy/mir/v3" + "github.com/julienschmidt/httprouter" +) + +func bindAny(r *http.Request, p httprouter.Params, obj any) mir.Error { + return mir.NewError(http.StatusBadRequest, errors.New("method not implemented")) +} + +func renderAny(w http.ResponseWriter, data any, err mir.Error) { + w.WriteHeader(http.StatusNotImplemented) + w.Write([]byte("method not implemented")) +} diff --git a/mirc/templates/httprouter/servants/servants.go.tmpl b/mirc/templates/httprouter/servants/servants.go.tmpl new file mode 100644 index 0000000..ca8a01b --- /dev/null +++ b/mirc/templates/httprouter/servants/servants.go.tmpl @@ -0,0 +1,15 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" + v1 "{{ .PkgName }}/mirc/auto/api/v1" + v2 "{{ .PkgName }}/mirc/auto/api/v2" + "github.com/julienschmidt/httprouter" +) + +// RegisterServants register all the servants to httprouter.Router +func RegisterServants(e *httprouter.Router) { + api.RegisterSiteServant(e, newSiteSrv(), newSiteBinding(), newSiteRender()) + v1.RegisterSiteServant(e, newSiteV1Srv(), newSiteV1Render()) + v2.RegisterSiteServant(e, newSiteV2Srv(), newSiteV2Binding(), newSiteV2Render()) +} diff --git a/mirc/templates/httprouter/servants/site.go.tmpl b/mirc/templates/httprouter/servants/site.go.tmpl new file mode 100644 index 0000000..0912d5f --- /dev/null +++ b/mirc/templates/httprouter/servants/site.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" +) + +type siteSrv struct { + api.UnimplementedSiteServant +} + +type siteBinding struct { + *api.UnimplementedSiteBinding +} + +type siteRender struct { + *api.UnimplementedSiteRender +} + +func newSiteSrv() api.Site { + return &siteSrv{} +} + +func newSiteBinding() api.SiteBinding { + return &siteBinding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteRender() api.SiteRender { + return &siteRender{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/httprouter/servants/site_v1.go.tmpl b/mirc/templates/httprouter/servants/site_v1.go.tmpl new file mode 100644 index 0000000..98a0a8b --- /dev/null +++ b/mirc/templates/httprouter/servants/site_v1.go.tmpl @@ -0,0 +1,25 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v1" +) + +type siteV1Srv struct { + api.UnimplementedSiteServant +} + +type siteV1Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV1Srv() api.Site { + return &siteV1Srv{} +} + +func newSiteV1Render() api.SiteRender { + return &siteV1Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/httprouter/servants/site_v2.go.tmpl b/mirc/templates/httprouter/servants/site_v2.go.tmpl new file mode 100644 index 0000000..4fb76aa --- /dev/null +++ b/mirc/templates/httprouter/servants/site_v2.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v2" +) + +type siteV2Srv struct { + api.UnimplementedSiteServant +} + +type siteV2Binding struct { + *api.UnimplementedSiteBinding +} + +type siteV2Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV2Srv() api.Site { + return &siteV2Srv{} +} + +func newSiteV2Binding() api.SiteBinding { + return &siteV2Binding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteV2Render() api.SiteRender { + return &siteV2Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/iris/.gitignore.tmpl b/mirc/templates/iris/.gitignore.tmpl new file mode 100644 index 0000000..96ffcd3 --- /dev/null +++ b/mirc/templates/iris/.gitignore.tmpl @@ -0,0 +1,25 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +coverage.out +count.out +test +profile.out +tmp.out + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# GoLand project files +.idea/ +*.iml + +# VS Code +.vscode diff --git a/mirc/templates/iris/Makefile.tmpl b/mirc/templates/iris/Makefile.tmpl new file mode 100644 index 0000000..9616a42 --- /dev/null +++ b/mirc/templates/iris/Makefile.tmpl @@ -0,0 +1,27 @@ +GOFMT ?= gofmt -s -w +GOFILES := $(shell find . -name "*.go" -type f) + +.PHONY: default +default: run + +.PHONY: build +build: fmt + go build -o mir-examples main.go + +.PHONY: build +run: fmt + go run main.go + +.PHONY: mod-tidy +mod-tidy: + @go mod download + @go mod tidy + +.PHONY: generate +generate: + @go generate mirc/main.go + @$(GOFMT) ./ + +.PHONY: fmt +fmt: + $(GOFMT) $(GOFILES) diff --git a/mirc/templates/iris/README.md.tmpl b/mirc/templates/iris/README.md.tmpl new file mode 100644 index 0000000..5bf9de3 --- /dev/null +++ b/mirc/templates/iris/README.md.tmpl @@ -0,0 +1,8 @@ +## mir-examples +just a simple mir's examples for explain how to use mir in your project. + +#### Usage +```bash +% make generate +% make build +``` diff --git a/mirc/templates/iris/go.mod.tmpl b/mirc/templates/iris/go.mod.tmpl new file mode 100644 index 0000000..790d293 --- /dev/null +++ b/mirc/templates/iris/go.mod.tmpl @@ -0,0 +1,60 @@ +module {{ .PkgName }} + +go 1.18 + +require ( + github.com/alimy/mir/v3 v3.0.0 + github.com/kataras/iris/v12 v12.1.8 +) + +require ( + github.com/BurntSushi/toml v0.3.1 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v3 v3.0.0 // indirect + github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398 // indirect + github.com/ajg/form v1.5.1 // indirect + github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible // indirect + github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/imkira/go-interpol v1.1.0 // indirect + github.com/iris-contrib/blackfriday v2.0.0+incompatible // indirect + github.com/iris-contrib/jade v1.1.3 // indirect + github.com/iris-contrib/pongo2 v0.0.1 // indirect + github.com/iris-contrib/schema v0.0.1 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/kataras/golog v0.0.10 // indirect + github.com/kataras/pio v0.0.2 // indirect + github.com/kataras/sitemap v0.0.5 // indirect + github.com/klauspost/compress v1.15.9 // indirect + github.com/kr/pretty v0.3.0 // indirect + github.com/microcosm-cc/bluemonday v1.0.2 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/moul/http2curl v1.0.0 // indirect + github.com/rogpeppe/go-internal v1.8.0 // indirect + github.com/ryanuber/columnize v2.1.0+incompatible // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sergi/go-diff v1.2.0 // indirect + github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect + github.com/smartystreets/goconvey v1.7.2 // indirect + github.com/stretchr/testify v1.7.1 // indirect + github.com/valyala/fasthttp v1.43.0 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect + github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect + github.com/yudai/gojsondiff v1.0.0 // indirect + github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect + golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect + golang.org/x/net v0.0.0-20220906165146-f3363e06e74c // indirect + golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect + golang.org/x/text v0.3.7 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/ini.v1 v1.51.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect +) +{{if notEmptyStr .MirPkgName }} +replace ( + github.com/alimy/mir/v3 => {{ .MirPkgName }} +) +{{end}} diff --git a/mirc/templates/iris/go.sum.tmpl b/mirc/templates/iris/go.sum.tmpl new file mode 100644 index 0000000..63b24aa --- /dev/null +++ b/mirc/templates/iris/go.sum.tmpl @@ -0,0 +1,216 @@ +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v3 v3.0.0 h1:1PwO5w5VCtlUUl+KTOBsTGZlhjWkcybsGaAau52tOy8= +github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398 h1:WDC6ySpJzbxGWFh4aMxFFC28wwGp5pEuoTtvA4q/qQ4= +github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible h1:Ppm0npCCsmuR9oQaBtRuZcmILVE74aXE+AmrJj8L2ns= +github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o= +github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= +github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/gavv/httpexpect v2.0.0+incompatible h1:1X9kcRshkSKEjNJJxX9Y9mQ5BRfbxU5kORdjhlA1yX8= +github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI= +github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/iris-contrib/blackfriday v2.0.0+incompatible h1:o5sHQHHm0ToHUlAJSTjW9UWicjJSDDauOOQ2AHuIVp4= +github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= +github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= +github.com/iris-contrib/jade v1.1.3 h1:p7J/50I0cjo0wq/VWVCDFd8taPJbuFC+bq23SniRFX0= +github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= +github.com/iris-contrib/pongo2 v0.0.1 h1:zGP7pW51oi5eQZMIlGA3I+FHY9/HOQWDB+572yin0to= +github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= +github.com/iris-contrib/schema v0.0.1 h1:10g/WnoRR+U+XXHWKBHeNy/+tZmM2kcAVGLOsz+yaDA= +github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kataras/golog v0.0.10 h1:vRDRUmwacco/pmBAm8geLn8rHEdc+9Z4NAr5Sh7TG/4= +github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= +github.com/kataras/iris/v12 v12.1.8 h1:O3gJasjm7ZxpxwTH8tApZsvf274scSGQAUpNe47c37U= +github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= +github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= +github.com/kataras/pio v0.0.2 h1:6NAi+uPJ/Zuid6mrAKlgpbI11/zK/lV4B2rxWaJN98Y= +github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= +github.com/kataras/sitemap v0.0.5 h1:4HCONX5RLgVy6G4RkYOV3vKNcma9p236LdGOipJsaFE= +github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= +github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= +github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= +github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/microcosm-cc/bluemonday v1.0.2 h1:5lPfLTTAvAbtS0VqT+94yOtFnGfUWYyx0+iToC3Os3s= +github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs= +github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/ryanuber/columnize v2.1.0+incompatible h1:j1Wcmh8OrK4Q7GXY+V7SVSY8nUWQxHW5TkBe7YUl+2s= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= +github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= +github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg= +github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.43.0 h1:Gy4sb32C98fbzVWZlTM1oTMdLWGyvxR03VhM6cBIU4g= +github.com/valyala/fasthttp v1.43.0/go.mod h1:f6VbjjoI3z1NDOZOv17o6RvtRSWxC77seBFc2uWtgiY= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220906165146-f3363e06e74c h1:yKufUcDwucU5urd+50/Opbt4AYpqthk7wHpHok8f1lo= +golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.51.1 h1:GyboHr4UqMiLUybYjd22ZjQIKEJEpgtLXtuGbR21Oho= +gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/mirc/templates/iris/main.go.tmpl b/mirc/templates/iris/main.go.tmpl new file mode 100644 index 0000000..cddfac3 --- /dev/null +++ b/mirc/templates/iris/main.go.tmpl @@ -0,0 +1,20 @@ +package main + +import ( + "log" + + "{{ .PkgName }}/servants" + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + + // register servants to iris + servants.RegisterServants(app) + + // start servant service + if err := app.Run(iris.Addr(":8013")); err != nil { + log.Fatal(err) + } +} diff --git a/mirc/templates/iris/mirc/auto/api/site.go.tmpl b/mirc/templates/iris/mirc/auto/api/site.go.tmpl new file mode 100644 index 0000000..8532fbf --- /dev/null +++ b/mirc/templates/iris/mirc/auto/api/site.go.tmpl @@ -0,0 +1,283 @@ +// Code generated by go-mir. DO NOT EDIT. + +package api + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/context" +) + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + // Chain provide handlers chain for iris + Chain() context.Handlers + + Logout(*LogoutReq) mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogout(context.Context) (*LogoutReq, mir.Error) + BindLogin(context.Context) (*LoginReq, mir.Error) + BindPrevTweets(context.Context) (*TweetsReq, mir.Error) + BindNextTweets(context.Context) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(context.Context, mir.Error) + RenderLogin(context.Context, *LoginResp, mir.Error) + RenderPrevTweets(context.Context, *TweetsResp, mir.Error) + RenderNextTweets(context.Context, *TweetsResp, mir.Error) + RenderArticles(context.Context, mir.Error) + RenderIndex(context.Context, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to iris +func RegisterSiteServant(app *iris.Application, s Site, b SiteBinding, r SiteRender) { + router := app + // use chain for party + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Handle("POST", "/user/logout/", func(c context.Context) { + select { + case <-c.Request().Context().Done(): + return + default: + } + + req, err := b.BindLogout(c) + if err != nil { + r.RenderLogout(c, err) + return + } + r.RenderLogout(c, s.Logout(req)) + }) + + router.Handle("POST", "/user/login/", func(c context.Context) { + select { + case <-c.Request().Context().Done(): + return + default: + } + + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(c, resp, err) + }) + + { + h := func(c context.Context) { + select { + case <-c.Request().Context().Done(): + return + default: + } + + req, err := b.BindPrevTweets(c) + if err != nil { + r.RenderPrevTweets(c, nil, err) + return + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(c, resp, err) + } + router.Handle("HEAD", "/tweets/prev", h) + router.Handle("GET", "/tweets/prev", h) + router.Handle("POST", "/tweets/prev", h) + } + + router.Any("/tweets/next", func(c context.Context) { + select { + case <-c.Request().Context().Done(): + return + default: + } + + req, err := b.BindNextTweets(c) + if err != nil { + r.RenderNextTweets(c, nil, err) + return + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(c, resp, err) + }) + + router.Handle("GET", "/articles/{category:string}", func(c context.Context) { + select { + case <-c.Request().Context().Done(): + return + default: + } + + r.RenderArticles(c, s.Articles()) + }) + + router.Handle("GET", "/index/", func(c context.Context) { + select { + case <-c.Request().Context().Done(): + return + default: + } + + r.RenderIndex(c, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() context.Handlers { + return nil +} + +func (UnimplementedSiteServant) Logout(req *LogoutReq) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(context.Context, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(c context.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(c context.Context, data *LoginResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(c context.Context, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(c context.Context, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(c context.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c context.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(context.Context, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogout(c context.Context) (*LogoutReq, mir.Error) { + obj := new(LogoutReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindLogin(c context.Context) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(c context.Context) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(c context.Context) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/iris/mirc/auto/api/v1/site.go.tmpl b/mirc/templates/iris/mirc/auto/api/v1/site.go.tmpl new file mode 100644 index 0000000..11994ee --- /dev/null +++ b/mirc/templates/iris/mirc/auto/api/v1/site.go.tmpl @@ -0,0 +1,96 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/context" +) + +type Site interface { + // Chain provide handlers chain for iris + Chain() context.Handlers + + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteRender interface { + RenderArticles(context.Context, mir.Error) + RenderIndex(context.Context, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to iris +func RegisterSiteServant(app *iris.Application, s Site, r SiteRender) { + router := app.Party("v1") + // use chain for party + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + { + h := func(c context.Context) { + select { + case <-c.Request().Context().Done(): + return + default: + } + + r.RenderArticles(c, s.Articles()) + } + router.Handle("HEAD", "/articles/{category:string}", h) + router.Handle("POST", "/articles/{category:string}", h) + router.Handle("GET", "/articles/{category:string}", h) + } + + router.Handle("GET", "/index/", func(c context.Context) { + select { + case <-c.Request().Context().Done(): + return + default: + } + + r.RenderIndex(c, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() context.Handlers { + return nil +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(context.Context, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderArticles(c context.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c context.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} diff --git a/mirc/templates/iris/mirc/auto/api/v2/site.go.tmpl b/mirc/templates/iris/mirc/auto/api/v2/site.go.tmpl new file mode 100644 index 0000000..0c964d0 --- /dev/null +++ b/mirc/templates/iris/mirc/auto/api/v2/site.go.tmpl @@ -0,0 +1,256 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v2 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/context" +) + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + Logout() mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogin(context.Context) (*LoginReq, mir.Error) + BindPrevTweets(context.Context) (*TweetsReq, mir.Error) + BindNextTweets(context.Context) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(context.Context, mir.Error) + RenderLogin(context.Context, *LoginResp, mir.Error) + RenderPrevTweets(context.Context, *TweetsResp, mir.Error) + RenderNextTweets(context.Context, *TweetsResp, mir.Error) + RenderArticles(context.Context, mir.Error) + RenderIndex(context.Context, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to iris +func RegisterSiteServant(app *iris.Application, s Site, b SiteBinding, r SiteRender) { + router := app.Party("v2") + + // register routes info to router + router.Handle("POST", "/user/logout/", func(c context.Context) { + select { + case <-c.Request().Context().Done(): + return + default: + } + + r.RenderLogout(c, s.Logout()) + }) + + router.Handle("POST", "/user/login/", func(c context.Context) { + select { + case <-c.Request().Context().Done(): + return + default: + } + + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(c, resp, err) + }) + + { + h := func(c context.Context) { + select { + case <-c.Request().Context().Done(): + return + default: + } + + req, err := b.BindPrevTweets(c) + if err != nil { + r.RenderPrevTweets(c, nil, err) + return + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(c, resp, err) + } + router.Handle("HEAD", "/tweets/prev", h) + router.Handle("GET", "/tweets/prev", h) + router.Handle("POST", "/tweets/prev", h) + } + + router.Any("/tweets/next", func(c context.Context) { + select { + case <-c.Request().Context().Done(): + return + default: + } + + req, err := b.BindNextTweets(c) + if err != nil { + r.RenderNextTweets(c, nil, err) + return + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(c, resp, err) + }) + + router.Handle("GET", "/articles/{category:string}", func(c context.Context) { + select { + case <-c.Request().Context().Done(): + return + default: + } + + r.RenderArticles(c, s.Articles()) + }) + + router.Handle("GET", "/index/", func(c context.Context) { + select { + case <-c.Request().Context().Done(): + return + default: + } + + r.RenderIndex(c, s.Index()) + }) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Logout() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(context.Context, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(c context.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(c context.Context, data *LoginResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(c context.Context, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(c context.Context, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(c context.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c context.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(context.Context, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogin(c context.Context) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(c context.Context) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(c context.Context) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/iris/mirc/main.go.tmpl b/mirc/templates/iris/mirc/main.go.tmpl new file mode 100644 index 0000000..7b04a75 --- /dev/null +++ b/mirc/templates/iris/mirc/main.go.tmpl @@ -0,0 +1,26 @@ +package main + +import ( + "log" + + . "github.com/alimy/mir/v3/core" + . "github.com/alimy/mir/v3/engine" + + _ "{{ .PkgName }}/mirc/routes" + _ "{{ .PkgName }}/mirc/routes/v1" + _ "{{ .PkgName }}/mirc/routes/v2" +) + +//go:generate go run main.go +func main() { + log.Println("generate code start") + opts := Options{ + RunMode(InSerialMode), + GeneratorName(GeneratorIris), + SinkPath("auto"), + } + if err := Generate(opts); err != nil { + log.Fatal(err) + } + log.Println("generate code finish") +} diff --git a/mirc/templates/iris/mirc/routes/site.go.tmpl b/mirc/templates/iris/mirc/routes/site.go.tmpl new file mode 100644 index 0000000..41dfe4b --- /dev/null +++ b/mirc/templates/iris/mirc/routes/site.go.tmpl @@ -0,0 +1,65 @@ +package routes + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site interface info +type Site struct { + Chain Chain `mir:"-"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/{category:string}"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post, LogoutReq) `mir:"/user/logout/"` +} diff --git a/mirc/templates/iris/mirc/routes/v1/site.go.tmpl b/mirc/templates/iris/mirc/routes/v1/site.go.tmpl new file mode 100644 index 0000000..a7e992b --- /dev/null +++ b/mirc/templates/iris/mirc/routes/v1/site.go.tmpl @@ -0,0 +1,18 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +// Site site v1 interface info +type Site struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + Index func(Get) `mir:"/index/"` + Articles func(Head, Get, Post) `mir:"/articles/{category:string}"` +} diff --git a/mirc/templates/iris/mirc/routes/v2/site.go.tmpl b/mirc/templates/iris/mirc/routes/v2/site.go.tmpl new file mode 100644 index 0000000..f36ef2e --- /dev/null +++ b/mirc/templates/iris/mirc/routes/v2/site.go.tmpl @@ -0,0 +1,60 @@ +package v2 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site v2 interface info +type Site struct { + Group Group `mir:"v2"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/{category:string}"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post) `mir:"/user/logout/"` +} diff --git a/mirc/templates/iris/servants/core.go.tmpl b/mirc/templates/iris/servants/core.go.tmpl new file mode 100644 index 0000000..fbeb3ef --- /dev/null +++ b/mirc/templates/iris/servants/core.go.tmpl @@ -0,0 +1,18 @@ +package servants + +import ( + "errors" + "net/http" + + "github.com/alimy/mir/v3" + "github.com/kataras/iris/v12/context" +) + +func bindAny(c context.Context, obj any) mir.Error { + return mir.NewError(http.StatusNotImplemented, errors.New("method not implemented")) +} + +func renderAny(c context.Context, data any, err mir.Error) { + c.StatusCode(http.StatusNotImplemented) + c.WriteString("method not implemented") +} diff --git a/mirc/templates/iris/servants/servants.go.tmpl b/mirc/templates/iris/servants/servants.go.tmpl new file mode 100644 index 0000000..d98dc7e --- /dev/null +++ b/mirc/templates/iris/servants/servants.go.tmpl @@ -0,0 +1,15 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" + v1 "{{ .PkgName }}/mirc/auto/api/v1" + v2 "{{ .PkgName }}/mirc/auto/api/v2" + "github.com/kataras/iris/v12" +) + +// RegisterServants register all the servants to iris.Application +func RegisterServants(app *iris.Application) { + api.RegisterSiteServant(app, newSiteSrv(), newSiteBinding(), newSiteRender()) + v1.RegisterSiteServant(app, newSiteV1Srv(), newSiteV1Render()) + v2.RegisterSiteServant(app, newSiteV2Srv(), newSiteV2Binding(), newSiteV2Render()) +} diff --git a/mirc/templates/iris/servants/site.go.tmpl b/mirc/templates/iris/servants/site.go.tmpl new file mode 100644 index 0000000..0912d5f --- /dev/null +++ b/mirc/templates/iris/servants/site.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" +) + +type siteSrv struct { + api.UnimplementedSiteServant +} + +type siteBinding struct { + *api.UnimplementedSiteBinding +} + +type siteRender struct { + *api.UnimplementedSiteRender +} + +func newSiteSrv() api.Site { + return &siteSrv{} +} + +func newSiteBinding() api.SiteBinding { + return &siteBinding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteRender() api.SiteRender { + return &siteRender{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/iris/servants/site_v1.go.tmpl b/mirc/templates/iris/servants/site_v1.go.tmpl new file mode 100644 index 0000000..98a0a8b --- /dev/null +++ b/mirc/templates/iris/servants/site_v1.go.tmpl @@ -0,0 +1,25 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v1" +) + +type siteV1Srv struct { + api.UnimplementedSiteServant +} + +type siteV1Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV1Srv() api.Site { + return &siteV1Srv{} +} + +func newSiteV1Render() api.SiteRender { + return &siteV1Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/iris/servants/site_v2.go.tmpl b/mirc/templates/iris/servants/site_v2.go.tmpl new file mode 100644 index 0000000..4fb76aa --- /dev/null +++ b/mirc/templates/iris/servants/site_v2.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v2" +) + +type siteV2Srv struct { + api.UnimplementedSiteServant +} + +type siteV2Binding struct { + *api.UnimplementedSiteBinding +} + +type siteV2Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV2Srv() api.Site { + return &siteV2Srv{} +} + +func newSiteV2Binding() api.SiteBinding { + return &siteV2Binding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteV2Render() api.SiteRender { + return &siteV2Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/macaron/.gitignore.tmpl b/mirc/templates/macaron/.gitignore.tmpl new file mode 100644 index 0000000..96ffcd3 --- /dev/null +++ b/mirc/templates/macaron/.gitignore.tmpl @@ -0,0 +1,25 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +coverage.out +count.out +test +profile.out +tmp.out + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# GoLand project files +.idea/ +*.iml + +# VS Code +.vscode diff --git a/mirc/templates/macaron/Makefile.tmpl b/mirc/templates/macaron/Makefile.tmpl new file mode 100644 index 0000000..9616a42 --- /dev/null +++ b/mirc/templates/macaron/Makefile.tmpl @@ -0,0 +1,27 @@ +GOFMT ?= gofmt -s -w +GOFILES := $(shell find . -name "*.go" -type f) + +.PHONY: default +default: run + +.PHONY: build +build: fmt + go build -o mir-examples main.go + +.PHONY: build +run: fmt + go run main.go + +.PHONY: mod-tidy +mod-tidy: + @go mod download + @go mod tidy + +.PHONY: generate +generate: + @go generate mirc/main.go + @$(GOFMT) ./ + +.PHONY: fmt +fmt: + $(GOFMT) $(GOFILES) diff --git a/mirc/templates/macaron/README.md.tmpl b/mirc/templates/macaron/README.md.tmpl new file mode 100644 index 0000000..5bf9de3 --- /dev/null +++ b/mirc/templates/macaron/README.md.tmpl @@ -0,0 +1,8 @@ +## mir-examples +just a simple mir's examples for explain how to use mir in your project. + +#### Usage +```bash +% make generate +% make build +``` diff --git a/mirc/templates/macaron/go.mod.tmpl b/mirc/templates/macaron/go.mod.tmpl new file mode 100644 index 0000000..16e320c --- /dev/null +++ b/mirc/templates/macaron/go.mod.tmpl @@ -0,0 +1,20 @@ +module {{ .PkgName }} + +go 1.18 + +require ( + github.com/alimy/mir/v3 v3.0.0 + gopkg.in/macaron.v1 v1.4.0 +) + +require ( + github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191 // indirect + github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e // indirect + golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect + gopkg.in/ini.v1 v1.46.0 // indirect +) +{{if notEmptyStr .MirPkgName }} +replace ( + github.com/alimy/mir/v3 => {{ .MirPkgName }} +) +{{end}} diff --git a/mirc/templates/macaron/go.sum.tmpl b/mirc/templates/macaron/go.sum.tmpl new file mode 100644 index 0000000..130271f --- /dev/null +++ b/mirc/templates/macaron/go.sum.tmpl @@ -0,0 +1,32 @@ +github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191 h1:NjHlg70DuOkcAMqgt0+XA+NHwtu66MkTVVgR4fFWbcI= +github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191/go.mod h1:VFI2o2q9kYsC4o7VP1HrEVosiZZTd+MVT3YZx4gqvJw= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4= +github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= +github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= +github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= +github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8= +github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e h1:GSGeB9EAKY2spCABz6xOX5DbxZEXolK+nBSvmsQwRjM= +github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +gopkg.in/ini.v1 v1.46.0 h1:VeDZbLYGaupuvIrsYCEOe/L/2Pcs5n7hdO1ZTjporag= +gopkg.in/ini.v1 v1.46.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/macaron.v1 v1.4.0 h1:RJHC09fAnQ8tuGUiZNjG0uyL1BWSdSWd9SpufIcEArQ= +gopkg.in/macaron.v1 v1.4.0/go.mod h1:uMZCFccv9yr5TipIalVOyAyZQuOH3OkmXvgcWwhJuP4= diff --git a/mirc/templates/macaron/main.go.tmpl b/mirc/templates/macaron/main.go.tmpl new file mode 100644 index 0000000..8b5b39f --- /dev/null +++ b/mirc/templates/macaron/main.go.tmpl @@ -0,0 +1,16 @@ +package main + +import ( + "{{ .PkgName }}/servants" + "gopkg.in/macaron.v1" +) + +func main() { + m := macaron.New() + + // register servants to macaron + servants.RegisterServants(m) + + // start servant service(:4000) + m.Run() +} diff --git a/mirc/templates/macaron/mirc/auto/api/site.go.tmpl b/mirc/templates/macaron/mirc/auto/api/site.go.tmpl new file mode 100644 index 0000000..7e359ef --- /dev/null +++ b/mirc/templates/macaron/mirc/auto/api/site.go.tmpl @@ -0,0 +1,246 @@ +// Code generated by go-mir. DO NOT EDIT. + +package api + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "gopkg.in/macaron.v1" +) + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + // Chain provide handlers chain for macaron + Chain() []macaron.Handler + + Logout(*LogoutReq) mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogout(*macaron.Context) (*LogoutReq, mir.Error) + BindLogin(*macaron.Context) (*LoginReq, mir.Error) + BindPrevTweets(*macaron.Context) (*TweetsReq, mir.Error) + BindNextTweets(*macaron.Context) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(*macaron.Context, mir.Error) + RenderLogin(*macaron.Context, *LoginResp, mir.Error) + RenderPrevTweets(*macaron.Context, *TweetsResp, mir.Error) + RenderNextTweets(*macaron.Context, *TweetsResp, mir.Error) + RenderArticles(*macaron.Context, mir.Error) + RenderIndex(*macaron.Context, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to macaron +func RegisterSiteServant(m *macaron.Macaron, s Site, b SiteBinding, r SiteRender) { + // use chain for router + middlewares := s.Chain() + for _, middleware := range middlewares { + m.Use(middleware) + } + + m.Handle("POST", "/user/logout/", []macaron.Handler{func(c *macaron.Context) { + req, err := b.BindLogout(c) + if err != nil { + r.RenderLogout(c, err) + return + } + r.RenderLogout(c, s.Logout(req)) + }}) + + m.Handle("POST", "/user/login/", []macaron.Handler{func(c *macaron.Context) { + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(c, resp, err) + }}) + + { + h := func(c *macaron.Context) { + req, err := b.BindPrevTweets(c) + if err != nil { + r.RenderPrevTweets(c, nil, err) + return + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(c, resp, err) + } + m.Handle("GET", "/tweets/prev", []macaron.Handler{h}) + m.Handle("POST", "/tweets/prev", []macaron.Handler{h}) + m.Handle("HEAD", "/tweets/prev", []macaron.Handler{h}) + } + + m.Any("/tweets/next", func(c *macaron.Context) { + req, err := b.BindNextTweets(c) + if err != nil { + r.RenderNextTweets(c, nil, err) + return + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(c, resp, err) + }) + + m.Handle("GET", "/articles/:category/", []macaron.Handler{func(c *macaron.Context) { + r.RenderArticles(c, s.Articles()) + }}) + + m.Handle("GET", "/index/", []macaron.Handler{func(c *macaron.Context) { + r.RenderIndex(c, s.Index()) + }}) + +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() []macaron.Handler { + return nil +} + +func (UnimplementedSiteServant) Logout(req *LogoutReq) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(*macaron.Context, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(c *macaron.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(c *macaron.Context, data *LoginResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(c *macaron.Context, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(c *macaron.Context, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(c *macaron.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c *macaron.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(*macaron.Context, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogout(c *macaron.Context) (*LogoutReq, mir.Error) { + obj := new(LogoutReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindLogin(c *macaron.Context) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(c *macaron.Context) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(c *macaron.Context) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/macaron/mirc/auto/api/v1/site.go.tmpl b/mirc/templates/macaron/mirc/auto/api/v1/site.go.tmpl new file mode 100644 index 0000000..7a4c51a --- /dev/null +++ b/mirc/templates/macaron/mirc/auto/api/v1/site.go.tmpl @@ -0,0 +1,80 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "gopkg.in/macaron.v1" +) + +type Site interface { + // Chain provide handlers chain for macaron + Chain() []macaron.Handler + + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteRender interface { + RenderArticles(*macaron.Context, mir.Error) + RenderIndex(*macaron.Context, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to macaron +func RegisterSiteServant(m *macaron.Macaron, s Site, r SiteRender) { + // use chain for router + middlewares := s.Chain() + m.Group("v1", func() { + { + h := func(c *macaron.Context) { + r.RenderArticles(c, s.Articles()) + } + m.Handle("POST", "/articles/:category/", []macaron.Handler{h}) + m.Handle("GET", "/articles/:category/", []macaron.Handler{h}) + m.Handle("HEAD", "/articles/:category/", []macaron.Handler{h}) + } + m.Handle("GET", "/index/", []macaron.Handler{func(c *macaron.Context) { + r.RenderIndex(c, s.Index()) + }}) + + }, middlewares...) +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() []macaron.Handler { + return nil +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(*macaron.Context, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderArticles(c *macaron.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c *macaron.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} diff --git a/mirc/templates/macaron/mirc/auto/api/v2/site.go.tmpl b/mirc/templates/macaron/mirc/auto/api/v2/site.go.tmpl new file mode 100644 index 0000000..5eb4685 --- /dev/null +++ b/mirc/templates/macaron/mirc/auto/api/v2/site.go.tmpl @@ -0,0 +1,217 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v2 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "gopkg.in/macaron.v1" +) + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + Logout() mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogin(*macaron.Context) (*LoginReq, mir.Error) + BindPrevTweets(*macaron.Context) (*TweetsReq, mir.Error) + BindNextTweets(*macaron.Context) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(*macaron.Context, mir.Error) + RenderLogin(*macaron.Context, *LoginResp, mir.Error) + RenderPrevTweets(*macaron.Context, *TweetsResp, mir.Error) + RenderNextTweets(*macaron.Context, *TweetsResp, mir.Error) + RenderArticles(*macaron.Context, mir.Error) + RenderIndex(*macaron.Context, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to macaron +func RegisterSiteServant(m *macaron.Macaron, s Site, b SiteBinding, r SiteRender) { + m.Group("v2", func() { + m.Handle("POST", "/user/logout/", []macaron.Handler{func(c *macaron.Context) { + r.RenderLogout(c, s.Logout()) + }}) + + m.Handle("POST", "/user/login/", []macaron.Handler{func(c *macaron.Context) { + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(c, resp, err) + }}) + + { + h := func(c *macaron.Context) { + req, err := b.BindPrevTweets(c) + if err != nil { + r.RenderPrevTweets(c, nil, err) + return + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(c, resp, err) + } + m.Handle("HEAD", "/tweets/prev", []macaron.Handler{h}) + m.Handle("GET", "/tweets/prev", []macaron.Handler{h}) + m.Handle("POST", "/tweets/prev", []macaron.Handler{h}) + } + m.Any("/tweets/next", func(c *macaron.Context) { + req, err := b.BindNextTweets(c) + if err != nil { + r.RenderNextTweets(c, nil, err) + return + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(c, resp, err) + }) + + m.Handle("GET", "/articles/:category/", []macaron.Handler{func(c *macaron.Context) { + r.RenderArticles(c, s.Articles()) + }}) + + m.Handle("GET", "/index/", []macaron.Handler{func(c *macaron.Context) { + r.RenderIndex(c, s.Index()) + }}) + + }) +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Logout() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(*macaron.Context, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(c *macaron.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(c *macaron.Context, data *LoginResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(c *macaron.Context, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(c *macaron.Context, data *TweetsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(c *macaron.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(c *macaron.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(*macaron.Context, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogin(c *macaron.Context) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(c *macaron.Context) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(c *macaron.Context) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/macaron/mirc/main.go.tmpl b/mirc/templates/macaron/mirc/main.go.tmpl new file mode 100644 index 0000000..38357a2 --- /dev/null +++ b/mirc/templates/macaron/mirc/main.go.tmpl @@ -0,0 +1,26 @@ +package main + +import ( + "log" + + . "github.com/alimy/mir/v3/core" + . "github.com/alimy/mir/v3/engine" + + _ "{{ .PkgName }}/mirc/routes" + _ "{{ .PkgName }}/mirc/routes/v1" + _ "{{ .PkgName }}/mirc/routes/v2" +) + +//go:generate go run main.go +func main() { + log.Println("generate code start") + opts := Options{ + RunMode(InSerialMode), + GeneratorName(GeneratorMacaron), + SinkPath("auto"), + } + if err := Generate(opts); err != nil { + log.Fatal(err) + } + log.Println("generate code finish") +} diff --git a/mirc/templates/macaron/mirc/routes/site.go.tmpl b/mirc/templates/macaron/mirc/routes/site.go.tmpl new file mode 100644 index 0000000..2709138 --- /dev/null +++ b/mirc/templates/macaron/mirc/routes/site.go.tmpl @@ -0,0 +1,65 @@ +package routes + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site interface info +type Site struct { + Chain Chain `mir:"-"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/:category/"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post, LogoutReq) `mir:"/user/logout/"` +} diff --git a/mirc/templates/macaron/mirc/routes/v1/site.go.tmpl b/mirc/templates/macaron/mirc/routes/v1/site.go.tmpl new file mode 100644 index 0000000..451c8bf --- /dev/null +++ b/mirc/templates/macaron/mirc/routes/v1/site.go.tmpl @@ -0,0 +1,18 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +// Site site v1 interface info +type Site struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + Index func(Get) `mir:"/index/"` + Articles func(Head, Get, Post) `mir:"/articles/:category/"` +} diff --git a/mirc/templates/macaron/mirc/routes/v2/site.go.tmpl b/mirc/templates/macaron/mirc/routes/v2/site.go.tmpl new file mode 100644 index 0000000..502aeb5 --- /dev/null +++ b/mirc/templates/macaron/mirc/routes/v2/site.go.tmpl @@ -0,0 +1,60 @@ +package v2 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site v2 interface info +type Site struct { + Group Group `mir:"v2"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/:category/"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post) `mir:"/user/logout/"` +} diff --git a/mirc/templates/macaron/servants/core.go.tmpl b/mirc/templates/macaron/servants/core.go.tmpl new file mode 100644 index 0000000..1b0ab05 --- /dev/null +++ b/mirc/templates/macaron/servants/core.go.tmpl @@ -0,0 +1,18 @@ +package servants + +import ( + "errors" + "net/http" + + "github.com/alimy/mir/v3" + "gopkg.in/macaron.v1" +) + +func bindAny(c *macaron.Context, obj any) mir.Error { + return mir.NewError(http.StatusNotImplemented, errors.New("method not implemented")) +} + +func renderAny(c *macaron.Context, data any, err mir.Error) { + c.Resp.WriteHeader(http.StatusNotImplemented) + c.Resp.Write([]byte("method not implemented")) +} diff --git a/mirc/templates/macaron/servants/servants.go.tmpl b/mirc/templates/macaron/servants/servants.go.tmpl new file mode 100644 index 0000000..5eaf8f3 --- /dev/null +++ b/mirc/templates/macaron/servants/servants.go.tmpl @@ -0,0 +1,15 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" + v1 "{{ .PkgName }}/mirc/auto/api/v1" + v2 "{{ .PkgName }}/mirc/auto/api/v2" + "gopkg.in/macaron.v1" +) + +// RegisterServants register all the servants to macaron.Macaron +func RegisterServants(e *macaron.Macaron) { + api.RegisterSiteServant(e, newSiteSrv(), newSiteBinding(), newSiteRender()) + v1.RegisterSiteServant(e, newSiteV1Srv(), newSiteV1Render()) + v2.RegisterSiteServant(e, newSiteV2Srv(), newSiteV2Binding(), newSiteV2Render()) +} diff --git a/mirc/templates/macaron/servants/site.go.tmpl b/mirc/templates/macaron/servants/site.go.tmpl new file mode 100644 index 0000000..0912d5f --- /dev/null +++ b/mirc/templates/macaron/servants/site.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" +) + +type siteSrv struct { + api.UnimplementedSiteServant +} + +type siteBinding struct { + *api.UnimplementedSiteBinding +} + +type siteRender struct { + *api.UnimplementedSiteRender +} + +func newSiteSrv() api.Site { + return &siteSrv{} +} + +func newSiteBinding() api.SiteBinding { + return &siteBinding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteRender() api.SiteRender { + return &siteRender{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/macaron/servants/site_v1.go.tmpl b/mirc/templates/macaron/servants/site_v1.go.tmpl new file mode 100644 index 0000000..98a0a8b --- /dev/null +++ b/mirc/templates/macaron/servants/site_v1.go.tmpl @@ -0,0 +1,25 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v1" +) + +type siteV1Srv struct { + api.UnimplementedSiteServant +} + +type siteV1Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV1Srv() api.Site { + return &siteV1Srv{} +} + +func newSiteV1Render() api.SiteRender { + return &siteV1Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/macaron/servants/site_v2.go.tmpl b/mirc/templates/macaron/servants/site_v2.go.tmpl new file mode 100644 index 0000000..4fb76aa --- /dev/null +++ b/mirc/templates/macaron/servants/site_v2.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v2" +) + +type siteV2Srv struct { + api.UnimplementedSiteServant +} + +type siteV2Binding struct { + *api.UnimplementedSiteBinding +} + +type siteV2Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV2Srv() api.Site { + return &siteV2Srv{} +} + +func newSiteV2Binding() api.SiteBinding { + return &siteV2Binding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteV2Render() api.SiteRender { + return &siteV2Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/mux/.gitignore.tmpl b/mirc/templates/mux/.gitignore.tmpl new file mode 100644 index 0000000..96ffcd3 --- /dev/null +++ b/mirc/templates/mux/.gitignore.tmpl @@ -0,0 +1,25 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +coverage.out +count.out +test +profile.out +tmp.out + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# GoLand project files +.idea/ +*.iml + +# VS Code +.vscode diff --git a/mirc/templates/mux/Makefile.tmpl b/mirc/templates/mux/Makefile.tmpl new file mode 100644 index 0000000..9616a42 --- /dev/null +++ b/mirc/templates/mux/Makefile.tmpl @@ -0,0 +1,27 @@ +GOFMT ?= gofmt -s -w +GOFILES := $(shell find . -name "*.go" -type f) + +.PHONY: default +default: run + +.PHONY: build +build: fmt + go build -o mir-examples main.go + +.PHONY: build +run: fmt + go run main.go + +.PHONY: mod-tidy +mod-tidy: + @go mod download + @go mod tidy + +.PHONY: generate +generate: + @go generate mirc/main.go + @$(GOFMT) ./ + +.PHONY: fmt +fmt: + $(GOFMT) $(GOFILES) diff --git a/mirc/templates/mux/README.md.tmpl b/mirc/templates/mux/README.md.tmpl new file mode 100644 index 0000000..5bf9de3 --- /dev/null +++ b/mirc/templates/mux/README.md.tmpl @@ -0,0 +1,8 @@ +## mir-examples +just a simple mir's examples for explain how to use mir in your project. + +#### Usage +```bash +% make generate +% make build +``` diff --git a/mirc/templates/mux/go.mod.tmpl b/mirc/templates/mux/go.mod.tmpl new file mode 100644 index 0000000..1d61c21 --- /dev/null +++ b/mirc/templates/mux/go.mod.tmpl @@ -0,0 +1,13 @@ +module {{ .PkgName }} + +go 1.18 + +require ( + github.com/alimy/mir/v3 v3.0.0 + github.com/gorilla/mux v1.8.0 +) +{{if notEmptyStr .MirPkgName }} +replace ( + github.com/alimy/mir/v3 => {{ .MirPkgName }} +) +{{end}} diff --git a/mirc/templates/mux/go.sum.tmpl b/mirc/templates/mux/go.sum.tmpl new file mode 100644 index 0000000..5350288 --- /dev/null +++ b/mirc/templates/mux/go.sum.tmpl @@ -0,0 +1,2 @@ +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= diff --git a/mirc/templates/mux/main.go.tmpl b/mirc/templates/mux/main.go.tmpl new file mode 100644 index 0000000..2f34a93 --- /dev/null +++ b/mirc/templates/mux/main.go.tmpl @@ -0,0 +1,21 @@ +package main + +import ( + "log" + "net/http" + + "{{ .PkgName }}/servants" + "github.com/gorilla/mux" +) + +func main() { + r := mux.NewRouter() + + // register servants to chi + servants.RegisterServants(r) + + // start servant service + if err := http.ListenAndServe(":8080", r); err != nil { + log.Fatal(err) + } +} diff --git a/mirc/templates/mux/mirc/auto/api/site.go.tmpl b/mirc/templates/mux/mirc/auto/api/site.go.tmpl new file mode 100644 index 0000000..6fc40f0 --- /dev/null +++ b/mirc/templates/mux/mirc/auto/api/site.go.tmpl @@ -0,0 +1,280 @@ +// Code generated by go-mir. DO NOT EDIT. + +package api + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gorilla/mux" +) + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + // Chain provide middlewares for mux + Chain() []mux.MiddlewareFunc + + Logout(*LogoutReq) mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogout(*http.Request) (*LogoutReq, mir.Error) + BindLogin(*http.Request) (*LoginReq, mir.Error) + BindPrevTweets(*http.Request) (*TweetsReq, mir.Error) + BindNextTweets(*http.Request) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(http.ResponseWriter, mir.Error) + RenderLogin(http.ResponseWriter, *LoginResp, mir.Error) + RenderPrevTweets(http.ResponseWriter, *TweetsResp, mir.Error) + RenderNextTweets(http.ResponseWriter, *TweetsResp, mir.Error) + RenderArticles(http.ResponseWriter, mir.Error) + RenderIndex(http.ResponseWriter, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to mux +func RegisterSiteServant(e *mux.Router, s Site, b SiteBinding, r SiteRender) { + router := e + + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + + router.HandleFunc("/user/logout/", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindLogout(hr) + if err != nil { + r.RenderLogout(rw, err) + return + } + r.RenderLogout(rw, s.Logout(req)) + }).Methods("POST") + + router.HandleFunc("/user/login/", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindLogin(hr) + if err != nil { + r.RenderLogin(rw, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(rw, resp, err) + }).Methods("POST") + + router.HandleFunc("/tweets/prev", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindPrevTweets(hr) + if err != nil { + r.RenderPrevTweets(rw, nil, err) + return + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(rw, resp, err) + }).Methods("HEAD", "GET", "POST") + + router.HandleFunc("/tweets/next", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindNextTweets(hr) + if err != nil { + r.RenderNextTweets(rw, nil, err) + return + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(rw, resp, err) + }).Methods("POST", "DELETE", "OPTIONS", "TRACE", "GET", "HEAD", "CONNECT", "PUT", "PATCH") + + router.HandleFunc("/articles/{category}/{id:[0-9]+}", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderArticles(rw, s.Articles()) + }).Methods("GET"). + Host("{subdomain}.example.com"). + Queries("filter", "{filter}", "foo", "bar", "id", "{id:[0-9]+}") + + router.HandleFunc("/index/", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderIndex(rw, s.Index()) + }).Methods("GET") +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() []mux.MiddlewareFunc { + return nil +} + +func (UnimplementedSiteServant) Logout(req *LogoutReq) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(http.ResponseWriter, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(w http.ResponseWriter, data *LoginResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(w http.ResponseWriter, data *TweetsResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(w http.ResponseWriter, data *TweetsResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(*http.Request, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogout(r *http.Request) (*LogoutReq, mir.Error) { + obj := new(LogoutReq) + err := b.BindAny(r, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindLogin(r *http.Request) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(r, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(r *http.Request) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(r, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(r *http.Request) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(r, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/mux/mirc/auto/api/v1/site.go.tmpl b/mirc/templates/mux/mirc/auto/api/v1/site.go.tmpl new file mode 100644 index 0000000..c88537d --- /dev/null +++ b/mirc/templates/mux/mirc/auto/api/v1/site.go.tmpl @@ -0,0 +1,92 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gorilla/mux" +) + +type Site interface { + // Chain provide middlewares for mux + Chain() []mux.MiddlewareFunc + + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteRender interface { + RenderArticles(http.ResponseWriter, mir.Error) + RenderIndex(http.ResponseWriter, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to mux +func RegisterSiteServant(e *mux.Router, s Site, r SiteRender) { + router := e.PathPrefix("v1").Subrouter() + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + + router.HandleFunc("/articles/{category}/{id:[0-9]+}", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderArticles(rw, s.Articles()) + }).Methods("POST", "GET", "HEAD"). + Host("{subdomain}.example.com"). + Queries("filter", "{filter}", "foo", "bar", "id", "{id:[0-9]+}") + + router.HandleFunc("/index/", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderIndex(rw, s.Index()) + }).Methods("GET") +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Chain() []mux.MiddlewareFunc { + return nil +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(http.ResponseWriter, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderArticles(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} diff --git a/mirc/templates/mux/mirc/auto/api/v2/site.go.tmpl b/mirc/templates/mux/mirc/auto/api/v2/site.go.tmpl new file mode 100644 index 0000000..09afa7b --- /dev/null +++ b/mirc/templates/mux/mirc/auto/api/v2/site.go.tmpl @@ -0,0 +1,252 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v2 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gorilla/mux" +) + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +type Site interface { + Logout() mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + PrevTweets(*TweetsReq) (*TweetsResp, mir.Error) + NextTweets(*TweetsReq) (*TweetsResp, mir.Error) + Articles() mir.Error + Index() mir.Error + + mustEmbedUnimplementedSiteServant() +} + +type SiteBinding interface { + BindLogin(*http.Request) (*LoginReq, mir.Error) + BindPrevTweets(*http.Request) (*TweetsReq, mir.Error) + BindNextTweets(*http.Request) (*TweetsReq, mir.Error) + + mustEmbedUnimplementedSiteBinding() +} + +type SiteRender interface { + RenderLogout(http.ResponseWriter, mir.Error) + RenderLogin(http.ResponseWriter, *LoginResp, mir.Error) + RenderPrevTweets(http.ResponseWriter, *TweetsResp, mir.Error) + RenderNextTweets(http.ResponseWriter, *TweetsResp, mir.Error) + RenderArticles(http.ResponseWriter, mir.Error) + RenderIndex(http.ResponseWriter, mir.Error) + + mustEmbedUnimplementedSiteRender() +} + +// RegisterSiteServant register Site servant to mux +func RegisterSiteServant(e *mux.Router, s Site, b SiteBinding, r SiteRender) { + router := e.PathPrefix("v2").Subrouter() + + // register routes info to router + + router.HandleFunc("/user/logout/", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderLogout(rw, s.Logout()) + }).Methods("POST") + + router.HandleFunc("/user/login/", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindLogin(hr) + if err != nil { + r.RenderLogin(rw, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(rw, resp, err) + }).Methods("POST") + + router.HandleFunc("/tweets/prev", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindPrevTweets(hr) + if err != nil { + r.RenderPrevTweets(rw, nil, err) + return + } + resp, err := s.PrevTweets(req) + r.RenderPrevTweets(rw, resp, err) + }).Methods("HEAD", "GET", "POST") + + router.HandleFunc("/tweets/next", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + req, err := b.BindNextTweets(hr) + if err != nil { + r.RenderNextTweets(rw, nil, err) + return + } + resp, err := s.NextTweets(req) + r.RenderNextTweets(rw, resp, err) + }).Methods("PATCH", "DELETE", "CONNECT", "OPTIONS", "TRACE", "GET", "HEAD", "POST", "PUT") + + router.HandleFunc("/articles/{category}/{id:[0-9]+}", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderArticles(rw, s.Articles()) + }).Methods("GET"). + Host("{subdomain}.example.com"). + Queries("filter", "{filter}", "foo", "bar", "id", "{id:[0-9]+}") + + router.HandleFunc("/index/", func(rw http.ResponseWriter, hr *http.Request) { + select { + case <-hr.Context().Done(): + return + default: + } + + r.RenderIndex(rw, s.Index()) + }).Methods("GET") +} + +// UnimplementedSiteServant can be embedded to have forward compatible implementations. +type UnimplementedSiteServant struct { +} + +func (UnimplementedSiteServant) Logout() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Login(req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) PrevTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) NextTweets(req *TweetsReq) (*TweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Articles() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) Index() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedSiteServant) mustEmbedUnimplementedSiteServant() {} + +// UnimplementedSiteRender can be embedded to have forward compatible implementations. +type UnimplementedSiteRender struct { + RenderAny func(http.ResponseWriter, any, mir.Error) +} + +func (r *UnimplementedSiteRender) RenderLogout(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) RenderLogin(w http.ResponseWriter, data *LoginResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderPrevTweets(w http.ResponseWriter, data *TweetsResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderNextTweets(w http.ResponseWriter, data *TweetsResp, err mir.Error) { + r.RenderAny(w, data, err) +} + +func (r *UnimplementedSiteRender) RenderArticles(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) RenderIndex(w http.ResponseWriter, err mir.Error) { + r.RenderAny(w, nil, err) +} + +func (r *UnimplementedSiteRender) mustEmbedUnimplementedSiteRender() {} + +// UnimplementedSiteBinding can be embedded to have forward compatible implementations. +type UnimplementedSiteBinding struct { + BindAny func(*http.Request, any) mir.Error +} + +func (b *UnimplementedSiteBinding) BindLogin(r *http.Request) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(r, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindPrevTweets(r *http.Request) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(r, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) BindNextTweets(r *http.Request) (*TweetsReq, mir.Error) { + obj := new(TweetsReq) + err := b.BindAny(r, obj) + return obj, err +} + +func (b *UnimplementedSiteBinding) mustEmbedUnimplementedSiteBinding() {} diff --git a/mirc/templates/mux/mirc/main.go.tmpl b/mirc/templates/mux/mirc/main.go.tmpl new file mode 100644 index 0000000..f458dab --- /dev/null +++ b/mirc/templates/mux/mirc/main.go.tmpl @@ -0,0 +1,26 @@ +package main + +import ( + "log" + + . "github.com/alimy/mir/v3/core" + . "github.com/alimy/mir/v3/engine" + + _ "{{ .PkgName }}/mirc/routes" + _ "{{ .PkgName }}/mirc/routes/v1" + _ "{{ .PkgName }}/mirc/routes/v2" +) + +//go:generate go run main.go +func main() { + log.Println("generate code start") + opts := Options{ + RunMode(InSerialMode), + GeneratorName(GeneratorMux), + SinkPath("auto"), + } + if err := Generate(opts); err != nil { + log.Fatal(err) + } + log.Println("generate code finish") +} diff --git a/mirc/templates/mux/mirc/routes/site.go.tmpl b/mirc/templates/mux/mirc/routes/site.go.tmpl new file mode 100644 index 0000000..72107ba --- /dev/null +++ b/mirc/templates/mux/mirc/routes/site.go.tmpl @@ -0,0 +1,65 @@ +package routes + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LogoutReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site interface info +type Site struct { + Chain Chain `mir:"-"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"//{subdomain}.example.com/articles/{category}/{id:[0-9]+}?filter={filter}&foo=bar&id={id:[0-9]+}"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post, LogoutReq) `mir:"/user/logout/"` +} diff --git a/mirc/templates/mux/mirc/routes/v1/site.go.tmpl b/mirc/templates/mux/mirc/routes/v1/site.go.tmpl new file mode 100644 index 0000000..14c3aea --- /dev/null +++ b/mirc/templates/mux/mirc/routes/v1/site.go.tmpl @@ -0,0 +1,18 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +// Site site v1 interface info +type Site struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + Index func(Get) `mir:"/index/"` + Articles func(Head, Get, Post) `mir:"//{subdomain}.example.com/articles/{category}/{id:[0-9]+}?filter={filter}&foo=bar&id={id:[0-9]+}"` +} diff --git a/mirc/templates/mux/mirc/routes/v2/site.go.tmpl b/mirc/templates/mux/mirc/routes/v2/site.go.tmpl new file mode 100644 index 0000000..36425d5 --- /dev/null +++ b/mirc/templates/mux/mirc/routes/v2/site.go.tmpl @@ -0,0 +1,60 @@ +package v2 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(Site)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type TweetsReq struct { + Date string `json:"date"` +} + +type TweetsResp struct { + Tweets []Tweet `json:"tweets"` + Total uint32 `json:"total"` +} + +type Tweet struct { + Type string `json:"type"` + Content string `json:"content"` +} + +// Site site v2 interface info +type Site struct { + Group Group `mir:"v2"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"//{subdomain}.example.com/articles/{category}/{id:[0-9]+}?filter={filter}&foo=bar&id={id:[0-9]+}"` + NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next"` + PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post) `mir:"/user/logout/"` +} diff --git a/mirc/templates/mux/servants/core.go.tmpl b/mirc/templates/mux/servants/core.go.tmpl new file mode 100644 index 0000000..3fdd9ae --- /dev/null +++ b/mirc/templates/mux/servants/core.go.tmpl @@ -0,0 +1,17 @@ +package servants + +import ( + "errors" + "net/http" + + "github.com/alimy/mir/v3" +) + +func bindAny(r *http.Request, obj any) mir.Error { + return mir.NewError(http.StatusNotImplemented, errors.New("method not implemented")) +} + +func renderAny(w http.ResponseWriter, data any, err mir.Error) { + w.WriteHeader(http.StatusNotImplemented) + w.Write([]byte("method not implemented")) +} diff --git a/mirc/templates/mux/servants/servants.go.tmpl b/mirc/templates/mux/servants/servants.go.tmpl new file mode 100644 index 0000000..85d216d --- /dev/null +++ b/mirc/templates/mux/servants/servants.go.tmpl @@ -0,0 +1,15 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" + v1 "{{ .PkgName }}/mirc/auto/api/v1" + v2 "{{ .PkgName }}/mirc/auto/api/v2" + "github.com/gorilla/mux" +) + +// RegisterServants register all the servants to mux.Router +func RegisterServants(e *mux.Router) { + api.RegisterSiteServant(e, newSiteSrv(), newSiteBinding(), newSiteRender()) + v1.RegisterSiteServant(e, newSiteV1Srv(), newSiteV1Render()) + v2.RegisterSiteServant(e, newSiteV2Srv(), newSiteV2Binding(), newSiteV2Render()) +} diff --git a/mirc/templates/mux/servants/site.go.tmpl b/mirc/templates/mux/servants/site.go.tmpl new file mode 100644 index 0000000..0912d5f --- /dev/null +++ b/mirc/templates/mux/servants/site.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + "{{ .PkgName }}/mirc/auto/api" +) + +type siteSrv struct { + api.UnimplementedSiteServant +} + +type siteBinding struct { + *api.UnimplementedSiteBinding +} + +type siteRender struct { + *api.UnimplementedSiteRender +} + +func newSiteSrv() api.Site { + return &siteSrv{} +} + +func newSiteBinding() api.SiteBinding { + return &siteBinding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteRender() api.SiteRender { + return &siteRender{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/mux/servants/site_v1.go.tmpl b/mirc/templates/mux/servants/site_v1.go.tmpl new file mode 100644 index 0000000..98a0a8b --- /dev/null +++ b/mirc/templates/mux/servants/site_v1.go.tmpl @@ -0,0 +1,25 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v1" +) + +type siteV1Srv struct { + api.UnimplementedSiteServant +} + +type siteV1Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV1Srv() api.Site { + return &siteV1Srv{} +} + +func newSiteV1Render() api.SiteRender { + return &siteV1Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/mux/servants/site_v2.go.tmpl b/mirc/templates/mux/servants/site_v2.go.tmpl new file mode 100644 index 0000000..4fb76aa --- /dev/null +++ b/mirc/templates/mux/servants/site_v2.go.tmpl @@ -0,0 +1,37 @@ +package servants + +import ( + api "{{ .PkgName }}/mirc/auto/api/v2" +) + +type siteV2Srv struct { + api.UnimplementedSiteServant +} + +type siteV2Binding struct { + *api.UnimplementedSiteBinding +} + +type siteV2Render struct { + *api.UnimplementedSiteRender +} + +func newSiteV2Srv() api.Site { + return &siteV2Srv{} +} + +func newSiteV2Binding() api.SiteBinding { + return &siteV2Binding{ + UnimplementedSiteBinding: &api.UnimplementedSiteBinding{ + BindAny: bindAny, + }, + } +} + +func newSiteV2Render() api.SiteRender { + return &siteV2Render{ + UnimplementedSiteRender: &api.UnimplementedSiteRender{ + RenderAny: renderAny, + }, + } +} diff --git a/mirc/templates/templates.go b/mirc/templates/templates.go new file mode 100644 index 0000000..53c2dcf --- /dev/null +++ b/mirc/templates/templates.go @@ -0,0 +1,192 @@ +package templates + +import ( + "embed" + "fmt" + "io/fs" + "path" + "sort" + "strings" + "text/template" + + "github.com/alimy/embedx" +) + +var ( + //go:embed chi + //go:embed chi/.gitignore.tmpl + //go:embed echo + //go:embed echo/.gitignore.tmpl + //go:embed fiber + //go:embed fiber/.gitignore.tmpl + //go:embed fiber-v2 + //go:embed fiber-v2/.gitignore.tmpl + //go:embed gin + //go:embed gin/.gitignore.tmpl + //go:embed hertz + //go:embed hertz/.gitignore.tmpl + //go:embed httprouter + //go:embed httprouter/.gitignore.tmpl + //go:embed iris + //go:embed iris/.gitignore.tmpl + //go:embed macaron + //go:embed macaron/.gitignore.tmpl + //go:embed mux + //go:embed mux/.gitignore.tmpl + content embed.FS + + // styles map of style slice to style + styles = make(map[string]*tmplInfo) +) + +// TmplCtx template context for generate project +type TmplCtx struct { + PkgName string + MirPkgName string + MirVersion string + EngVersion string +} + +// ts style slice alice type +type ts []string + +type tmplInfo struct { + target string + files []string +} + +func init() { + for _, s := range []struct { + styles ts + info *tmplInfo + }{ + {ts{"gin"}, &tmplInfo{ + target: "gin", + files: levelStar(5), + }}, + {ts{"hertz"}, &tmplInfo{ + target: "hertz", + files: levelStar(5), + }}, + {ts{"chi"}, &tmplInfo{ + target: "chi", + files: levelStar(5), + }}, + {ts{"echo"}, &tmplInfo{ + target: "echo", + files: levelStar(5), + }}, + {ts{"fiber"}, &tmplInfo{ + target: "fiber", + files: levelStar(5), + }}, + {ts{"fiber-v2"}, &tmplInfo{ + target: "fiber-v2", + files: levelStar(5), + }}, + {ts{"fiber", "v2"}, &tmplInfo{ + target: "fiber-v2", + files: levelStar(5), + }}, + {ts{"httprouter"}, &tmplInfo{ + target: "httprouter", + files: levelStar(5), + }}, + {ts{"iris"}, &tmplInfo{ + target: "iris", + files: levelStar(5), + }}, + {ts{"macaron"}, &tmplInfo{ + target: "macaron", + files: levelStar(5), + }}, + {ts{"mux"}, &tmplInfo{ + target: "mux", + files: levelStar(5), + }}, + } { + styles[s.styles.String()] = s.info + } +} + +// VersionOfMir return mir's version +func (c *TmplCtx) VersionOfMir(defVer string) string { + if c.MirVersion != "" { + return c.MirVersion + } + return defVer +} + +// VersionOfEngine return engine's version +func (c *TmplCtx) VersionOfEngine(defVer string) string { + if c.EngVersion != "" { + return c.EngVersion + } + return defVer +} + +func (t *tmplInfo) globFiles(fsys fs.FS) ([]string, error) { + fps := make([]string, 0) + for _, p := range t.files { + list, err := fs.Glob(fsys, p) + if err != nil { + return nil, err + } + fps = append(fps, list...) + } + return fps, nil +} + +func (s ts) String() string { + sort.Strings(s) + return strings.Join(s, ":") +} + +func levelStar(l uint8) []string { + patterns := make([]string, 0, l) + for i := uint8(0); i < l; i++ { + ms := strings.Builder{} + for j := i; j > 0; j-- { + ms.WriteString("*/") + } + ms.WriteString("*.tmpl") + patterns = append(patterns, ms.String()) + } + return patterns +} + +func Styles() []string { + styleNames := make([]string, 0, len(styles)) + for name := range styles { + styleNames = append(styleNames, name) + } + return styleNames +} + +func NewTemplate(style []string) (*template.Template, error) { + sort.Strings(style) + info, exist := styles[strings.Join(style, ":")] + if !exist { + return nil, fmt.Errorf("not exist style(%s) template project", style) + } + embedFS, err := fs.Sub(content, info.target) + if err != nil { + return nil, err + } + embedx.RegisterNamer(embedx.NamerFunc(func(filename string) string { + ext := path.Ext(filename) + return filename[:len(filename)-len(ext)] + })) + files, err := info.globFiles(embedFS) + if err != nil { + return nil, err + } + tmpl := template.New("mirc").Funcs(template.FuncMap{ + "notEmptyStr": notEmptyStr, + }) + return embedx.ParseWith(tmpl, embedFS, files...) +} + +func notEmptyStr(s string) bool { + return s != "" +} diff --git a/mirc/version/version.go b/mirc/version/version.go new file mode 100644 index 0000000..0504f67 --- /dev/null +++ b/mirc/version/version.go @@ -0,0 +1,30 @@ +// Copyright 2020 Michael Li . All rights reserved. +// Use of this source code is governed by Apache License 2.0 that +// can be found in the LICENSE file. + +package version + +import ( + "fmt" + + "github.com/Masterminds/semver/v3" +) + +var ( + // GitHash Value will be set during build + GitHash = "" + + // BuildTime Value will be set during build + BuildTime = "" + + // AppVer version of Mirc + AppVer = semver.MustParse("v3.0.0") +) + +func ShowInfo() string { + if BuildTime == "" || GitHash == "" { + return fmt.Sprintf("v%s\n", AppVer) + } else { + return fmt.Sprintf("v%s\nBuildTime: %s\nGitHash: %s\n", AppVer, BuildTime, GitHash) + } +}