├── .fapfile ├── lib ├── types │ └── packages.go └── templates │ ├── initreadme │ ├── qtpl │ │ ├── readme.qtpl │ │ └── readme.qtpl.go │ └── generate.go │ ├── web │ ├── qtpl │ │ ├── getRouteChain.qtpl │ │ ├── homeHandler.qtpl │ │ ├── fasthttp_router.qtpl │ │ ├── getRouteChain.qtpl.go │ │ ├── homeHandler.qtpl.go │ │ └── fasthttp_router.qtpl.go │ └── generate.go │ ├── webrdb │ ├── qtpl │ │ ├── getRouteChain.qtpl │ │ ├── main.qtpl │ │ ├── homeHandler.qtpl │ │ ├── getRouteChain.qtpl.go │ │ ├── homeHandler.qtpl.go │ │ └── main.qtpl.go │ └── generate.go │ └── static │ └── generate.go ├── .gitignore ├── web ├── types.go ├── methods.go ├── listen.go └── registerChain.go ├── main.go ├── README.md ├── cmd ├── deploy.go ├── init.go ├── release.go ├── build.go ├── root.go └── from.go └── LICENSE /.fapfile: -------------------------------------------------------------------------------- 1 | quicktemplate: false 2 | -------------------------------------------------------------------------------- /lib/types/packages.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type ( 4 | // PackageStructure defines a structure 5 | // as a map with key == relative file path 6 | // and value == file body as a string 7 | PackageStructure map[string]string 8 | ) 9 | -------------------------------------------------------------------------------- /lib/templates/initreadme/qtpl/readme.qtpl: -------------------------------------------------------------------------------- 1 | {% func Readme(name, template string) %}#{%s name %} [![made with fap](https://img.shields.io/badge/made%20with-fap-brightgreen.svg)](https://github.com/kirillDanshin/fap) 2 | 3 | Made with [fap](https://github.com/kirillDanshin/fap) using {%s template %} 4 | {% endfunc %} 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | -------------------------------------------------------------------------------- /lib/templates/initreadme/generate.go: -------------------------------------------------------------------------------- 1 | package initreadme 2 | 3 | import ( 4 | "github.com/kirillDanshin/fap/lib/templates/initreadme/qtpl" 5 | "github.com/kirillDanshin/fap/lib/types" 6 | ) 7 | 8 | // Generate returns PackageStruct with README.md 9 | func Generate(name, template string) (types.PackageStructure, error) { 10 | return types.PackageStructure{ 11 | "README.md": qtpl.Readme(name, template), 12 | }, nil 13 | } 14 | -------------------------------------------------------------------------------- /lib/templates/web/qtpl/getRouteChain.qtpl: -------------------------------------------------------------------------------- 1 | {% func GetRouteChain(packageName string) %}{% if packageName == "main" %}package main{% else %}package {%s packageName %}{% endif %} 2 | 3 | import ( 4 | "github.com/kirillDanshin/fap/web" 5 | ) 6 | 7 | func getRouteChain() web.HandlersChain{ 8 | return web.HandlersChain{ 9 | web.MethodGET: web.MethodChain{ 10 | "/:name": homeHandler, 11 | }, 12 | } 13 | } 14 | 15 | {% endfunc %} 16 | -------------------------------------------------------------------------------- /lib/templates/webrdb/qtpl/getRouteChain.qtpl: -------------------------------------------------------------------------------- 1 | {% func GetRouteChain(packageName string) %}{% if packageName == "main" %}package main{% else %}package {%s packageName %}{% endif %} 2 | 3 | import ( 4 | "github.com/kirillDanshin/fap/web" 5 | ) 6 | 7 | func getRouteChain() web.HandlersChain{ 8 | return web.HandlersChain{ 9 | web.MethodGET: web.MethodChain{ 10 | "/": homeHandler, 11 | "/:name": homeHandler, 12 | }, 13 | } 14 | } 15 | 16 | {% endfunc %} 17 | -------------------------------------------------------------------------------- /lib/templates/web/qtpl/homeHandler.qtpl: -------------------------------------------------------------------------------- 1 | {% func HomeHandler(packageName string) %}{% if packageName == "main" %}package main{% else %}package {%s packageName %}{% endif %} 2 | 3 | import ( 4 | "github.com/valyala/fasthttp" 5 | ) 6 | 7 | var ( 8 | homeGreetsTpl = []byte("Hi, ") 9 | homeGreetsNameParam = "name" 10 | homeGreetsDefaultName = []byte("Guest") 11 | ) 12 | 13 | func homeHandler(ctx *fasthttp.RequestCtx) { 14 | ctx.Write(homeGreetsTpl) 15 | if name := ctx.UserValue(homeGreetsNameParam); name != nil && len(name.(string)) > 0 { 16 | ctx.WriteString(name.(string)) 17 | } else { 18 | ctx.Write(homeGreetsDefaultName) 19 | } 20 | } 21 | {% endfunc %} 22 | -------------------------------------------------------------------------------- /web/types.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "github.com/buaazp/fasthttprouter" 5 | "github.com/valyala/fasthttp" 6 | ) 7 | 8 | // method type is defined in methods.go 9 | 10 | type ( 11 | // HandlersChain describes a map that stores 12 | // method chain info. 13 | HandlersChain map[method]MethodChain 14 | 15 | // MethodChain describes a map that stores handlers 16 | // for a path 17 | MethodChain map[string]func(*fasthttp.RequestCtx) 18 | 19 | // Instance describes a server instance 20 | Instance struct { 21 | address string 22 | Router *fasthttprouter.Router 23 | } 24 | ) 25 | 26 | // New web instance 27 | func New(addr string) *Instance { 28 | return &Instance{ 29 | address: addr, 30 | Router: fasthttprouter.New(), 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Kirill Danshin 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import "github.com/kirillDanshin/fap/cmd" 18 | 19 | func main() { 20 | cmd.Execute() 21 | } 22 | -------------------------------------------------------------------------------- /lib/templates/web/generate.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "github.com/kirillDanshin/fap/lib/templates/web/qtpl" 5 | "github.com/kirillDanshin/fap/lib/types" 6 | "github.com/kirillDanshin/myutils" 7 | ) 8 | 9 | // Generate returns a map with generated 10 | // package structure 11 | func Generate(packageName string) (types.PackageStructure, error) { 12 | if packageName == "" { 13 | packageName = "main" 14 | } 15 | path := "main.go" 16 | if packageName != "main" { 17 | path = myutils.Concat(packageName, "/web.go") 18 | } 19 | structure := types.PackageStructure{ 20 | "homeHandler.go": qtpl.HomeHandler(packageName), 21 | "getRouteChain.go": qtpl.GetRouteChain(packageName), 22 | path: qtpl.FastHTTPRouter(packageName), 23 | } 24 | return structure, nil 25 | } 26 | -------------------------------------------------------------------------------- /lib/templates/webrdb/generate.go: -------------------------------------------------------------------------------- 1 | package webrdb 2 | 3 | import ( 4 | "github.com/kirillDanshin/fap/lib/templates/webrdb/qtpl" 5 | "github.com/kirillDanshin/fap/lib/types" 6 | "github.com/kirillDanshin/myutils" 7 | ) 8 | 9 | // Generate returns a map with generated 10 | // package structure 11 | func Generate(packageName string) (types.PackageStructure, error) { 12 | if packageName == "" { 13 | packageName = "main" 14 | } 15 | path := "main.go" 16 | if packageName != "main" { 17 | path = myutils.Concat(packageName, "/web.go") 18 | } 19 | structure := types.PackageStructure{ 20 | "homeHandler.go": qtpl.HomeHandler(packageName), 21 | path: qtpl.FastHTTPRouter(packageName), 22 | "getRouteChain.go": qtpl.GetRouteChain(packageName), 23 | } 24 | return structure, nil 25 | } 26 | -------------------------------------------------------------------------------- /lib/templates/static/generate.go: -------------------------------------------------------------------------------- 1 | package static 2 | 3 | import "github.com/kirillDanshin/fap/lib/types" 4 | 5 | const template = `package main 6 | 7 | import ( 8 | "flag" 9 | "log" 10 | 11 | "github.com/valyala/fasthttp" 12 | ) 13 | 14 | var ( 15 | addr = flag.String("addr", ":8080", "address to listen") 16 | dir = flag.String("dir", "./static", "directory to serve") 17 | ) 18 | 19 | func main() { 20 | flag.Parse() 21 | log.Printf("Serving %s on %s\n", *dir, *addr) 22 | fasthttp.ListenAndServe(*addr, fasthttp.FSHandler(*dir, 0)) 23 | }` 24 | 25 | // Generate returns a map with generated 26 | // package structure 27 | func Generate(packageName string) (types.PackageStructure, error) { 28 | structure := types.PackageStructure{ 29 | "main.go": template, 30 | } 31 | return structure, nil 32 | } 33 | -------------------------------------------------------------------------------- /lib/templates/web/qtpl/fasthttp_router.qtpl: -------------------------------------------------------------------------------- 1 | {% func FastHTTPRouter(packageName string) %}{% if packageName == "main" %}package main{% else %}package {%s packageName %}{% endif %} 2 | 3 | import ({% if packageName == "main" %} 4 | "flag" 5 | {% endif %} 6 | "github.com/kirillDanshin/dlog" 7 | "github.com/kirillDanshin/fap/web" 8 | "github.com/kirillDanshin/myutils" 9 | ) 10 | {% if packageName == "main" %} 11 | var ( 12 | address = flag.String("address", "127.0.0.1:3270", "address to bind") 13 | ){% endif %} 14 | 15 | {% if packageName == "main" %}func main() { 16 | flag.Parse() 17 | addr := *address 18 | {% else %}func Run(addr string) {{% endif %} 19 | dlog.F("Registering handlers") 20 | 21 | w := web.New(addr) 22 | 23 | w.RegisterChain(getRouteChain()) 24 | 25 | dlog.F("Listening on %s", addr) 26 | myutils.LogFatalError(w.ListenAndServeGZip()) 27 | } 28 | {% endfunc %} 29 | -------------------------------------------------------------------------------- /web/methods.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | // method is a private type to safe RegisterChain args from invalid methods 4 | type method string 5 | 6 | const ( 7 | // MethodDELETE is for RegisterChain func, it handles DELETE methods 8 | MethodDELETE method = "DELETE" 9 | 10 | // MethodGET is for RegisterChain func, it handles GET methods 11 | MethodGET method = "GET" 12 | 13 | // MethodHEAD is for RegisterChain func, it handles HEAD methods 14 | MethodHEAD method = "HEAD" 15 | 16 | // MethodOPTIONS is for RegisterChain func, it handles OPTIONS methods 17 | MethodOPTIONS method = "OPTIONS" 18 | 19 | // MethodPATCH is for RegisterChain func, it handles PATCH methods 20 | MethodPATCH method = "PATCH" 21 | 22 | // MethodPOST is for RegisterChain func, it handles POST methods 23 | MethodPOST method = "POST" 24 | 25 | // MethodPUT is for RegisterChain func, it handles PUT methods 26 | MethodPUT method = "PUT" 27 | ) 28 | -------------------------------------------------------------------------------- /web/listen.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/valyala/fasthttp" 7 | ) 8 | 9 | // ListenAndServe on instance address 10 | func (i *Instance) ListenAndServe() error { 11 | return fasthttp.ListenAndServe(i.address, i.Router.Handler) 12 | } 13 | 14 | // ListenAndServeGZip on instance address with default compress middleware 15 | func (i *Instance) ListenAndServeGZip() error { 16 | return fasthttp.ListenAndServe(i.address, fasthttp.CompressHandler(i.Router.Handler)) 17 | } 18 | 19 | // ListenAndServeGZipLevel on instance address with selected compress level 20 | // NOTE: level should be greater or equal to 0 and lower or equal to 9 21 | func (i *Instance) ListenAndServeGZipLevel(level int) error { 22 | if level > 9 || level < 0 { 23 | return errors.New("Invalid gzip level") 24 | } 25 | return fasthttp.ListenAndServe(i.address, fasthttp.CompressHandlerLevel(i.Router.Handler, level)) 26 | } 27 | -------------------------------------------------------------------------------- /web/registerChain.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | // RegisterChain adds path handlers for specified method 4 | func (i *Instance) RegisterChain(handlersChain HandlersChain) { 5 | for m, mHandlers := range handlersChain { 6 | switch m { 7 | case MethodPOST: 8 | for path, handler := range mHandlers { 9 | i.Router.POST(path, handler) 10 | } 11 | case MethodDELETE: 12 | for path, handler := range mHandlers { 13 | i.Router.DELETE(path, handler) 14 | } 15 | case MethodGET: 16 | for path, handler := range mHandlers { 17 | i.Router.GET(path, handler) 18 | } 19 | case MethodHEAD: 20 | for path, handler := range mHandlers { 21 | i.Router.HEAD(path, handler) 22 | } 23 | case MethodOPTIONS: 24 | for path, handler := range mHandlers { 25 | i.Router.OPTIONS(path, handler) 26 | } 27 | case MethodPATCH: 28 | for path, handler := range mHandlers { 29 | i.Router.PATCH(path, handler) 30 | } 31 | case MethodPUT: 32 | for path, handler := range mHandlers { 33 | i.Router.PUT(path, handler) 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fap [![CLA assistant](https://cla-assistant.io/readme/badge/kirillDanshin/fap)](https://cla-assistant.io/kirillDanshin/fap) [![ReviewNinja](https://app.review.ninja/62991967/badge)](https://app.review.ninja/kirillDanshin/fap) 2 | 3 | Go fap 4 | 5 | ## **WARNING!** EARLY BETA! 6 | 7 | Please send pull requests and send bugs if you catch one. 8 | 9 | Feauture requests are welcome! 10 | 11 | # Install 12 | 13 | `go get -u github.com/kirillDanshin/fap` 14 | 15 | # Use 16 | 17 | ## Init from web template 18 | 19 | Create a project directory, `cd` there and run 20 | 21 | `fap init from web` 22 | 23 | It'll initialize git repository with readme, .gitignore and code from web template. 24 | 25 | ### Build 26 | 27 | `fap build` 28 | 29 | Builds your package with qtc templates and runs `go install` 30 | 31 | ### Debug build 32 | 33 | `fap build -d` 34 | 35 | Builds your package with qtc templates and runs `go install -tags "debug"` 36 | 37 | ### Release 38 | 39 | `fap release "Some message"` 40 | 41 | Adds all changes to git, commit them with "Some message" and pushes it to origin/master 42 | 43 | # TODO 44 | 45 | - [x] `fap init` 46 | - [x] `fap build` builds qtc templates and runs go install 47 | - [x] `fap release` (alias for `git add .; git commit; git push`) 48 | - [ ] fap/web helper package 49 | - [ ] fapfile support 50 | - [ ] fap template API 51 | - [ ] `fap deploy` 52 | - [ ] `fap test` 53 | -------------------------------------------------------------------------------- /cmd/deploy.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Kirill Danshin 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cmd 16 | 17 | import ( 18 | "fmt" 19 | 20 | "github.com/spf13/cobra" 21 | ) 22 | 23 | // deployCmd represents the deploy command 24 | var deployCmd = &cobra.Command{ 25 | Use: "deploy", 26 | Short: "Unsupported yet", 27 | Run: func(cmd *cobra.Command, args []string) { 28 | // TODO: Work your own magic here 29 | fmt.Println("deploy called") 30 | }, 31 | } 32 | 33 | func init() { 34 | RootCmd.AddCommand(deployCmd) 35 | 36 | // Here you will define your flags and configuration settings. 37 | 38 | // Cobra supports Persistent Flags which will work for this command 39 | // and all subcommands, e.g.: 40 | // deployCmd.PersistentFlags().String("foo", "", "A help for foo") 41 | 42 | // Cobra supports local flags which will only run when this command 43 | // is called directly, e.g.: 44 | // deployCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 45 | 46 | } 47 | -------------------------------------------------------------------------------- /lib/templates/webrdb/qtpl/main.qtpl: -------------------------------------------------------------------------------- 1 | {% func FastHTTPRouter(packageName string) %}{% if packageName == "main" %}package main{% else %}package {%s packageName %}{% endif %} 2 | 3 | import ({% if packageName == "main" %} 4 | "flag" 5 | 6 | {% endif %} "github.com/kirillDanshin/dlog" 7 | "github.com/kirillDanshin/fap/web" 8 | "github.com/kirillDanshin/myutils" 9 | 10 | r "gopkg.in/dancannon/gorethink.v2" 11 | ) 12 | var ({% if packageName == "main" %} 13 | address = flag.String("address", "127.0.0.1:3270", "address to bind") 14 | rdbAddr = flag.String("rdbAddr", "127.0.0.1:28015", "rethinkdb address for connection") 15 | rDBName = flag.String("rDB", "fap", "rethinkdb database name") 16 | {% endif %} 17 | rdb *r.Session 18 | ) 19 | {% if packageName == "main" %}func main() { 20 | flag.Parse() 21 | addr := *address 22 | rdbAddress := *rdbAddr 23 | rDB := *rDBName 24 | {% else %}func Run(addr, rdbAddress, rDB string) {{% endif %} 25 | var err error 26 | 27 | dlog.F("Connecting to RethinkDB") 28 | rdb, err = r.Connect(r.ConnectOpts{ 29 | Address: rdbAddress, 30 | Database: rDB, 31 | }) 32 | myutils.LogFatalError(err) 33 | 34 | r.DBCreate(rDB).Run(rdb) 35 | 36 | tl := []string{} 37 | req, err := r.TableList().Run(rdb) 38 | r.TableCreate("stats").Run(rdb) 39 | myutils.LogFatalError(err) 40 | 41 | dlog.D(req.All(&tl)) 42 | dlog.D(tl) 43 | 44 | w := web.New(addr) 45 | 46 | dlog.F("Registering handlers") 47 | 48 | w.RegisterChain(getRouteChain()) 49 | 50 | dlog.F("Listening on %s", addr) 51 | myutils.LogFatalError(w.ListenAndServeGZip()) 52 | } 53 | {% endfunc %} 54 | -------------------------------------------------------------------------------- /lib/templates/webrdb/qtpl/homeHandler.qtpl: -------------------------------------------------------------------------------- 1 | {% func HomeHandler(packageName string) %}{% if packageName == "main" %}package main{% else %}package {%s packageName %}{% endif %} 2 | 3 | import ( 4 | "fmt" 5 | "github.com/valyala/fasthttp" 6 | r "gopkg.in/dancannon/gorethink.v2" 7 | ) 8 | 9 | var ( 10 | homeGreetsTpl = []byte("Hi, ") 11 | homeGreetsNameParam = "name" 12 | homeGreetsDefaultName = []byte("Guest") 13 | homeCounterTpl = []byte("This page was viewed: ") 14 | homeCounterEnd = []byte(" times") 15 | ) 16 | 17 | func homeHandler(ctx *fasthttp.RequestCtx) { 18 | ctx.Write(homeGreetsTpl) 19 | if name := ctx.UserValue(homeGreetsNameParam); name != nil && len(name.(string)) > 0 { 20 | ctx.WriteString(name.(string)) 21 | } else { 22 | ctx.Write(homeGreetsDefaultName) 23 | } 24 | filter := map[string]interface{}{ 25 | "uri": string(ctx.URI().Path()), 26 | } 27 | var ( 28 | tmp []interface{} 29 | count = float64(0) 30 | ) 31 | f, _ := r.Table("stats").Filter(filter).Run(rdb) 32 | f.All(&tmp) 33 | f.Close() 34 | if len(tmp) > 0 { 35 | r.Table("stats").Filter(filter).Update(map[string]interface{}{ 36 | "views": r.Row.Field("views").Add(1).Default(0), 37 | }).RunWrite(rdb) 38 | v, _ := r.Table("stats").Filter(filter).Run(rdb) 39 | c := map[string]interface{}{} 40 | v.Peek(&c) 41 | count = c["views"].(float64) 42 | v.Close() 43 | } else { 44 | filter["views"] = 1 45 | r.Table("stats").Insert(filter).RunWrite(rdb) 46 | count = 1 47 | } 48 | fmt.Fprintln(ctx) 49 | ctx.Write(homeCounterTpl) 50 | fmt.Fprint(ctx, count) 51 | ctx.Write(homeCounterEnd) 52 | } 53 | {% endfunc %} 54 | -------------------------------------------------------------------------------- /cmd/init.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Kirill Danshin 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cmd 16 | 17 | import ( 18 | "fmt" 19 | "os" 20 | 21 | "github.com/spf13/cobra" 22 | ) 23 | 24 | // initCmd represents the init command 25 | var initCmd = &cobra.Command{ 26 | Use: "init", 27 | Aliases: []string{"i"}, 28 | Short: "Initialize a package", 29 | Long: `Initialize a package from some template. For example: 30 | fap init from fasthttp_router`, 31 | Run: func(cmd *cobra.Command, args []string) { 32 | fmt.Println("Choose a base template") 33 | os.Exit(1) 34 | }, 35 | } 36 | 37 | func init() { 38 | RootCmd.AddCommand(initCmd) 39 | 40 | // Here you will define your flags and configuration settings. 41 | 42 | // Cobra supports Persistent Flags which will work for this command 43 | // and all subcommands, e.g.: 44 | // initCmd.PersistentFlags().String("foo", "", "A help for foo") 45 | 46 | // Cobra supports local flags which will only run when this command 47 | // is called directly, e.g.: 48 | // initCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 49 | 50 | } 51 | -------------------------------------------------------------------------------- /cmd/release.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Kirill Danshin 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cmd 16 | 17 | import ( 18 | "log" 19 | "os" 20 | "os/exec" 21 | 22 | "github.com/spf13/cobra" 23 | ) 24 | 25 | // releaseCmd represents the release command 26 | var releaseCmd = &cobra.Command{ 27 | Use: "release", 28 | Short: "Adds all changes to git, commits it and pushes to origin/master", 29 | Run: func(cmd *cobra.Command, args []string) { 30 | if len(args) != 1 { 31 | log.Printf("args: %#+v\n", args) 32 | log.Println("Enter the release message") 33 | } 34 | log.Println("Adding changes to git") 35 | if o, err := exec.Command("git", "add", ".").CombinedOutput(); err != nil { 36 | log.Printf("git add . error: %s", o) 37 | os.Exit(1) 38 | } 39 | log.Printf(`Commiting them with "%s" message`, args[0]) 40 | if o, err := exec.Command("git", "commit", "-m", args[0]).CombinedOutput(); err != nil { 41 | log.Printf("git commit error: %s", o) 42 | os.Exit(1) 43 | } 44 | log.Println("Pushing it") 45 | if o, err := exec.Command("git", "push", "origin", "master").CombinedOutput(); err != nil { 46 | log.Printf("git push origin master error: %s", o) 47 | os.Exit(1) 48 | } 49 | log.Println("Done!") 50 | }, 51 | } 52 | 53 | func init() { 54 | RootCmd.AddCommand(releaseCmd) 55 | } 56 | -------------------------------------------------------------------------------- /cmd/build.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Kirill Danshin 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cmd 16 | 17 | import ( 18 | "log" 19 | "os/exec" 20 | 21 | "github.com/spf13/cobra" 22 | ) 23 | 24 | // buildCmd represents the build command 25 | var buildCmd = &cobra.Command{ 26 | Use: "build", 27 | Short: "fap build your application", 28 | Run: func(cmd *cobra.Command, args []string) { 29 | if cmd.Flag("quicktemplate").Value.String() == "true" { 30 | qtcBuild := exec.Command("qtc", "./...") 31 | if o, err := qtcBuild.CombinedOutput(); err != nil { 32 | log.Printf("qtc build error: %s\n\n%s", o, err) 33 | } else { 34 | log.Printf("qtc build done") 35 | } 36 | } 37 | var goInstall *exec.Cmd 38 | if cmd.Flag("debug").Value.String() == "true" { 39 | log.Println("Using debug mode") 40 | goInstall = exec.Command("go", "install", `-tags="debug"`) 41 | } else { 42 | goInstall = exec.Command("go", "install") 43 | } 44 | if o, err := goInstall.CombinedOutput(); err != nil { 45 | log.Printf("go install error: %s\n\n%s", o, err) 46 | } else { 47 | log.Printf("go install done") 48 | } 49 | }, 50 | } 51 | 52 | func init() { 53 | RootCmd.AddCommand(buildCmd) 54 | 55 | // Here you will define your flags and configuration settings. 56 | 57 | // Cobra supports Persistent Flags which will work for this command 58 | // and all subcommands, e.g.: 59 | buildCmd.PersistentFlags().BoolP("quicktemplate", "q", true, "Enable qtc compiling") 60 | 61 | // Cobra supports local flags which will only run when this command 62 | // is called directly, e.g.: 63 | buildCmd.Flags().BoolP("debug", "d", false, "Enable debug mode") 64 | 65 | } 66 | -------------------------------------------------------------------------------- /lib/templates/initreadme/qtpl/readme.qtpl.go: -------------------------------------------------------------------------------- 1 | // This file is automatically generated by qtc from "readme.qtpl". 2 | // See https://github.com/valyala/quicktemplate for details. 3 | 4 | //line lib/templates/initreadme/qtpl/readme.qtpl:1 5 | package qtpl 6 | 7 | //line lib/templates/initreadme/qtpl/readme.qtpl:1 8 | import ( 9 | qtio422016 "io" 10 | 11 | qt422016 "github.com/valyala/quicktemplate" 12 | ) 13 | 14 | //line lib/templates/initreadme/qtpl/readme.qtpl:1 15 | var ( 16 | _ = qtio422016.Copy 17 | _ = qt422016.AcquireByteBuffer 18 | ) 19 | 20 | //line lib/templates/initreadme/qtpl/readme.qtpl:1 21 | func StreamReadme(qw422016 *qt422016.Writer, name, template string) { 22 | //line lib/templates/initreadme/qtpl/readme.qtpl:1 23 | qw422016.N().S(`#`) 24 | //line lib/templates/initreadme/qtpl/readme.qtpl:1 25 | qw422016.E().S(name) 26 | //line lib/templates/initreadme/qtpl/readme.qtpl:1 27 | qw422016.N().S(` [![made with fap](https://img.shields.io/badge/made%20with-fap-brightgreen.svg)](https://github.com/kirillDanshin/fap) 28 | 29 | Made with [fap](https://github.com/kirillDanshin/fap) using `) 30 | //line lib/templates/initreadme/qtpl/readme.qtpl:3 31 | qw422016.E().S(template) 32 | //line lib/templates/initreadme/qtpl/readme.qtpl:3 33 | qw422016.N().S(` 34 | `) 35 | //line lib/templates/initreadme/qtpl/readme.qtpl:4 36 | } 37 | 38 | //line lib/templates/initreadme/qtpl/readme.qtpl:4 39 | func WriteReadme(qq422016 qtio422016.Writer, name, template string) { 40 | //line lib/templates/initreadme/qtpl/readme.qtpl:4 41 | qw422016 := qt422016.AcquireWriter(qq422016) 42 | //line lib/templates/initreadme/qtpl/readme.qtpl:4 43 | StreamReadme(qw422016, name, template) 44 | //line lib/templates/initreadme/qtpl/readme.qtpl:4 45 | qt422016.ReleaseWriter(qw422016) 46 | //line lib/templates/initreadme/qtpl/readme.qtpl:4 47 | } 48 | 49 | //line lib/templates/initreadme/qtpl/readme.qtpl:4 50 | func Readme(name, template string) string { 51 | //line lib/templates/initreadme/qtpl/readme.qtpl:4 52 | qb422016 := qt422016.AcquireByteBuffer() 53 | //line lib/templates/initreadme/qtpl/readme.qtpl:4 54 | WriteReadme(qb422016, name, template) 55 | //line lib/templates/initreadme/qtpl/readme.qtpl:4 56 | qs422016 := string(qb422016.B) 57 | //line lib/templates/initreadme/qtpl/readme.qtpl:4 58 | qt422016.ReleaseByteBuffer(qb422016) 59 | //line lib/templates/initreadme/qtpl/readme.qtpl:4 60 | return qs422016 61 | //line lib/templates/initreadme/qtpl/readme.qtpl:4 62 | } 63 | -------------------------------------------------------------------------------- /lib/templates/web/qtpl/getRouteChain.qtpl.go: -------------------------------------------------------------------------------- 1 | // This file is automatically generated by qtc from "getRouteChain.qtpl". 2 | // See https://github.com/valyala/quicktemplate for details. 3 | 4 | //line lib/templates/web/qtpl/getRouteChain.qtpl:1 5 | package qtpl 6 | 7 | //line lib/templates/web/qtpl/getRouteChain.qtpl:1 8 | import ( 9 | qtio422016 "io" 10 | 11 | qt422016 "github.com/valyala/quicktemplate" 12 | ) 13 | 14 | //line lib/templates/web/qtpl/getRouteChain.qtpl:1 15 | var ( 16 | _ = qtio422016.Copy 17 | _ = qt422016.AcquireByteBuffer 18 | ) 19 | 20 | //line lib/templates/web/qtpl/getRouteChain.qtpl:1 21 | func StreamGetRouteChain(qw422016 *qt422016.Writer, packageName string) { 22 | //line lib/templates/web/qtpl/getRouteChain.qtpl:1 23 | if packageName == "main" { 24 | //line lib/templates/web/qtpl/getRouteChain.qtpl:1 25 | qw422016.N().S(`package main`) 26 | //line lib/templates/web/qtpl/getRouteChain.qtpl:1 27 | } else { 28 | //line lib/templates/web/qtpl/getRouteChain.qtpl:1 29 | qw422016.N().S(`package `) 30 | //line lib/templates/web/qtpl/getRouteChain.qtpl:1 31 | qw422016.E().S(packageName) 32 | //line lib/templates/web/qtpl/getRouteChain.qtpl:1 33 | } 34 | //line lib/templates/web/qtpl/getRouteChain.qtpl:1 35 | qw422016.N().S(` 36 | 37 | import ( 38 | "github.com/kirillDanshin/fap/web" 39 | ) 40 | 41 | func getRouteChain() web.HandlersChain{ 42 | return web.HandlersChain{ 43 | web.MethodGET: web.MethodChain{ 44 | "/:name": homeHandler, 45 | }, 46 | } 47 | } 48 | 49 | `) 50 | //line lib/templates/web/qtpl/getRouteChain.qtpl:15 51 | } 52 | 53 | //line lib/templates/web/qtpl/getRouteChain.qtpl:15 54 | func WriteGetRouteChain(qq422016 qtio422016.Writer, packageName string) { 55 | //line lib/templates/web/qtpl/getRouteChain.qtpl:15 56 | qw422016 := qt422016.AcquireWriter(qq422016) 57 | //line lib/templates/web/qtpl/getRouteChain.qtpl:15 58 | StreamGetRouteChain(qw422016, packageName) 59 | //line lib/templates/web/qtpl/getRouteChain.qtpl:15 60 | qt422016.ReleaseWriter(qw422016) 61 | //line lib/templates/web/qtpl/getRouteChain.qtpl:15 62 | } 63 | 64 | //line lib/templates/web/qtpl/getRouteChain.qtpl:15 65 | func GetRouteChain(packageName string) string { 66 | //line lib/templates/web/qtpl/getRouteChain.qtpl:15 67 | qb422016 := qt422016.AcquireByteBuffer() 68 | //line lib/templates/web/qtpl/getRouteChain.qtpl:15 69 | WriteGetRouteChain(qb422016, packageName) 70 | //line lib/templates/web/qtpl/getRouteChain.qtpl:15 71 | qs422016 := string(qb422016.B) 72 | //line lib/templates/web/qtpl/getRouteChain.qtpl:15 73 | qt422016.ReleaseByteBuffer(qb422016) 74 | //line lib/templates/web/qtpl/getRouteChain.qtpl:15 75 | return qs422016 76 | //line lib/templates/web/qtpl/getRouteChain.qtpl:15 77 | } 78 | -------------------------------------------------------------------------------- /lib/templates/webrdb/qtpl/getRouteChain.qtpl.go: -------------------------------------------------------------------------------- 1 | // This file is automatically generated by qtc from "getRouteChain.qtpl". 2 | // See https://github.com/valyala/quicktemplate for details. 3 | 4 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:1 5 | package qtpl 6 | 7 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:1 8 | import ( 9 | qtio422016 "io" 10 | 11 | qt422016 "github.com/valyala/quicktemplate" 12 | ) 13 | 14 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:1 15 | var ( 16 | _ = qtio422016.Copy 17 | _ = qt422016.AcquireByteBuffer 18 | ) 19 | 20 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:1 21 | func StreamGetRouteChain(qw422016 *qt422016.Writer, packageName string) { 22 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:1 23 | if packageName == "main" { 24 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:1 25 | qw422016.N().S(`package main`) 26 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:1 27 | } else { 28 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:1 29 | qw422016.N().S(`package `) 30 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:1 31 | qw422016.E().S(packageName) 32 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:1 33 | } 34 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:1 35 | qw422016.N().S(` 36 | 37 | import ( 38 | "github.com/kirillDanshin/fap/web" 39 | ) 40 | 41 | func getRouteChain() web.HandlersChain{ 42 | return web.HandlersChain{ 43 | web.MethodGET: web.MethodChain{ 44 | "/": homeHandler, 45 | "/:name": homeHandler, 46 | }, 47 | } 48 | } 49 | 50 | `) 51 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:16 52 | } 53 | 54 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:16 55 | func WriteGetRouteChain(qq422016 qtio422016.Writer, packageName string) { 56 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:16 57 | qw422016 := qt422016.AcquireWriter(qq422016) 58 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:16 59 | StreamGetRouteChain(qw422016, packageName) 60 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:16 61 | qt422016.ReleaseWriter(qw422016) 62 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:16 63 | } 64 | 65 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:16 66 | func GetRouteChain(packageName string) string { 67 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:16 68 | qb422016 := qt422016.AcquireByteBuffer() 69 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:16 70 | WriteGetRouteChain(qb422016, packageName) 71 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:16 72 | qs422016 := string(qb422016.B) 73 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:16 74 | qt422016.ReleaseByteBuffer(qb422016) 75 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:16 76 | return qs422016 77 | //line lib/templates/webrdb/qtpl/getRouteChain.qtpl:16 78 | } 79 | -------------------------------------------------------------------------------- /lib/templates/web/qtpl/homeHandler.qtpl.go: -------------------------------------------------------------------------------- 1 | // This file is automatically generated by qtc from "homeHandler.qtpl". 2 | // See https://github.com/valyala/quicktemplate for details. 3 | 4 | //line lib/templates/web/qtpl/homeHandler.qtpl:1 5 | package qtpl 6 | 7 | //line lib/templates/web/qtpl/homeHandler.qtpl:1 8 | import ( 9 | qtio422016 "io" 10 | 11 | qt422016 "github.com/valyala/quicktemplate" 12 | ) 13 | 14 | //line lib/templates/web/qtpl/homeHandler.qtpl:1 15 | var ( 16 | _ = qtio422016.Copy 17 | _ = qt422016.AcquireByteBuffer 18 | ) 19 | 20 | //line lib/templates/web/qtpl/homeHandler.qtpl:1 21 | func StreamHomeHandler(qw422016 *qt422016.Writer, packageName string) { 22 | //line lib/templates/web/qtpl/homeHandler.qtpl:1 23 | if packageName == "main" { 24 | //line lib/templates/web/qtpl/homeHandler.qtpl:1 25 | qw422016.N().S(`package main`) 26 | //line lib/templates/web/qtpl/homeHandler.qtpl:1 27 | } else { 28 | //line lib/templates/web/qtpl/homeHandler.qtpl:1 29 | qw422016.N().S(`package `) 30 | //line lib/templates/web/qtpl/homeHandler.qtpl:1 31 | qw422016.E().S(packageName) 32 | //line lib/templates/web/qtpl/homeHandler.qtpl:1 33 | } 34 | //line lib/templates/web/qtpl/homeHandler.qtpl:1 35 | qw422016.N().S(` 36 | 37 | import ( 38 | "github.com/valyala/fasthttp" 39 | ) 40 | 41 | var ( 42 | homeGreetsTpl = []byte("Hi, ") 43 | homeGreetsNameParam = "name" 44 | homeGreetsDefaultName = []byte("Guest") 45 | ) 46 | 47 | func homeHandler(ctx *fasthttp.RequestCtx) { 48 | ctx.Write(homeGreetsTpl) 49 | if name := ctx.UserValue(homeGreetsNameParam); name != nil && len(name.(string)) > 0 { 50 | ctx.WriteString(name.(string)) 51 | } else { 52 | ctx.Write(homeGreetsDefaultName) 53 | } 54 | } 55 | `) 56 | //line lib/templates/web/qtpl/homeHandler.qtpl:21 57 | } 58 | 59 | //line lib/templates/web/qtpl/homeHandler.qtpl:21 60 | func WriteHomeHandler(qq422016 qtio422016.Writer, packageName string) { 61 | //line lib/templates/web/qtpl/homeHandler.qtpl:21 62 | qw422016 := qt422016.AcquireWriter(qq422016) 63 | //line lib/templates/web/qtpl/homeHandler.qtpl:21 64 | StreamHomeHandler(qw422016, packageName) 65 | //line lib/templates/web/qtpl/homeHandler.qtpl:21 66 | qt422016.ReleaseWriter(qw422016) 67 | //line lib/templates/web/qtpl/homeHandler.qtpl:21 68 | } 69 | 70 | //line lib/templates/web/qtpl/homeHandler.qtpl:21 71 | func HomeHandler(packageName string) string { 72 | //line lib/templates/web/qtpl/homeHandler.qtpl:21 73 | qb422016 := qt422016.AcquireByteBuffer() 74 | //line lib/templates/web/qtpl/homeHandler.qtpl:21 75 | WriteHomeHandler(qb422016, packageName) 76 | //line lib/templates/web/qtpl/homeHandler.qtpl:21 77 | qs422016 := string(qb422016.B) 78 | //line lib/templates/web/qtpl/homeHandler.qtpl:21 79 | qt422016.ReleaseByteBuffer(qb422016) 80 | //line lib/templates/web/qtpl/homeHandler.qtpl:21 81 | return qs422016 82 | //line lib/templates/web/qtpl/homeHandler.qtpl:21 83 | } 84 | -------------------------------------------------------------------------------- /cmd/root.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Kirill Danshin 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cmd 16 | 17 | import ( 18 | "fmt" 19 | "os" 20 | 21 | "github.com/spf13/cobra" 22 | "github.com/spf13/viper" 23 | ) 24 | 25 | var cfgFile string 26 | 27 | // RootCmd represents the base command when called without any subcommands 28 | var RootCmd = &cobra.Command{ 29 | Use: "fap", 30 | Short: "fap fap fap", 31 | Long: `fap allows you to generate package from boilerplates, build it and soon 32 | will help you to release, test and deploy it within a one simple command.`, 33 | // Uncomment the following line if your bare application 34 | // has an action associated with it: 35 | // Run: func(cmd *cobra.Command, args []string) { }, 36 | } 37 | 38 | // Execute adds all child commands to the root command sets flags appropriately. 39 | // This is called by main.main(). It only needs to happen once to the rootCmd. 40 | func Execute() { 41 | if err := RootCmd.Execute(); err != nil { 42 | fmt.Println(err) 43 | os.Exit(-1) 44 | } 45 | } 46 | 47 | func init() { 48 | cobra.OnInitialize(initConfig) 49 | 50 | // Here you will define your flags and configuration settings. 51 | // Cobra supports Persistent Flags, which, if defined here, 52 | // will be global for your application. 53 | 54 | // RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.fap.yaml)") 55 | RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is ./.fapfile or /etc/fap/.fapfile)") 56 | // Cobra also supports local flags, which will only run 57 | // when this action is called directly. 58 | // RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 59 | } 60 | 61 | // initConfig reads in config file and ENV variables if set. 62 | func initConfig() { 63 | if cfgFile != "" { // enable ability to specify config file via flag 64 | viper.SetConfigFile(cfgFile) 65 | } 66 | 67 | viper.SetConfigName(".fapfile") // name of config file (without extension) 68 | // viper.AddConfigPath("$HOME") // adding home directory as first search path 69 | viper.AddConfigPath(".") // adding project directory as first search path 70 | viper.AddConfigPath("/etc/fap") // adding /etc/fap directory as second search path 71 | viper.AutomaticEnv() // read in environment variables that match 72 | 73 | // If a config file is found, read it in. 74 | if err := viper.ReadInConfig(); err == nil { 75 | fmt.Println("Using config file:", viper.ConfigFileUsed()) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /cmd/from.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Kirill Danshin 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cmd 16 | 17 | import ( 18 | "log" 19 | "os" 20 | "os/exec" 21 | "path" 22 | 23 | "github.com/imdario/mergo" 24 | "github.com/kirillDanshin/fap/lib/templates/initreadme" 25 | "github.com/kirillDanshin/fap/lib/templates/static" 26 | "github.com/kirillDanshin/fap/lib/templates/web" 27 | "github.com/kirillDanshin/fap/lib/templates/webrdb" 28 | "github.com/kirillDanshin/fap/lib/types" 29 | "github.com/kirillDanshin/myutils" 30 | "github.com/spf13/afero" 31 | "github.com/spf13/cobra" 32 | ) 33 | 34 | // fromCmd represents the from command 35 | var fromCmd = &cobra.Command{ 36 | Use: "from", 37 | Short: "Generate from selected template", 38 | Run: func(cmd *cobra.Command, args []string) { 39 | if len(args) == 0 { 40 | println("Choose a template") 41 | os.Exit(1) 42 | } 43 | var packageStruct types.PackageStructure 44 | switch args[0] { 45 | case "web": 46 | packageStruct, _ = web.Generate("main") 47 | case "webrdb": 48 | packageStruct, _ = webrdb.Generate("main") 49 | case "static": 50 | packageStruct, _ = static.Generate("main") 51 | default: 52 | println("Unknown a template") 53 | os.Exit(1) 54 | } 55 | fs := afero.Afero{Fs: afero.NewOsFs()} 56 | if cmd.Flag("git").Value.String() == "true" { 57 | exec.Command("git", "init").Run() 58 | wd, err := os.Getwd() 59 | myutils.LogFatalError(err) 60 | readme, err := initreadme.Generate(path.Base(wd), "fasthttprouter") 61 | myutils.LogFatalError(err) 62 | mergo.Merge(&packageStruct, readme) 63 | } 64 | for filePath, content := range packageStruct { 65 | exists, _ := fs.Exists(filePath) 66 | if exists && cmd.Flag("overwrite").Value.String() == "true" { 67 | log.Println("Overwriting", filePath) 68 | } 69 | if exists && cmd.Flag("overwrite").Value.String() == "true" || !exists { 70 | dir, _ := path.Split(filePath) 71 | if len(dir) != 0 { 72 | os.MkdirAll(dir, 0755) 73 | } 74 | fs.WriteFile(filePath, []byte(content), 0755) 75 | } 76 | } 77 | if cmd.Flag("git").Value.String() == "true" { 78 | exec.Command("git", "add", ".").Run() 79 | exec.Command("git", "commit", "-m", "init with fap").Run() 80 | } 81 | }, 82 | } 83 | 84 | func init() { 85 | initCmd.AddCommand(fromCmd) 86 | 87 | // Here you will define your flags and configuration settings. 88 | 89 | // Cobra supports Persistent Flags which will work for this command 90 | // and all subcommands, e.g.: 91 | // fromCmd.PersistentFlags().String("foo", "", "A help for foo") 92 | 93 | // Cobra supports local flags which will only run when this command 94 | // is called directly, e.g.: 95 | fromCmd.Flags().BoolP("git", "g", true, "init git repo") 96 | fromCmd.Flags().BoolP("overwrite", "o", false, "overwrite files") 97 | 98 | } 99 | -------------------------------------------------------------------------------- /lib/templates/webrdb/qtpl/homeHandler.qtpl.go: -------------------------------------------------------------------------------- 1 | // This file is automatically generated by qtc from "homeHandler.qtpl". 2 | // See https://github.com/valyala/quicktemplate for details. 3 | 4 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:1 5 | package qtpl 6 | 7 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:1 8 | import ( 9 | qtio422016 "io" 10 | 11 | qt422016 "github.com/valyala/quicktemplate" 12 | ) 13 | 14 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:1 15 | var ( 16 | _ = qtio422016.Copy 17 | _ = qt422016.AcquireByteBuffer 18 | ) 19 | 20 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:1 21 | func StreamHomeHandler(qw422016 *qt422016.Writer, packageName string) { 22 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:1 23 | if packageName == "main" { 24 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:1 25 | qw422016.N().S(`package main`) 26 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:1 27 | } else { 28 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:1 29 | qw422016.N().S(`package `) 30 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:1 31 | qw422016.E().S(packageName) 32 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:1 33 | } 34 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:1 35 | qw422016.N().S(` 36 | 37 | import ( 38 | "fmt" 39 | "github.com/valyala/fasthttp" 40 | r "gopkg.in/dancannon/gorethink.v2" 41 | ) 42 | 43 | var ( 44 | homeGreetsTpl = []byte("Hi, ") 45 | homeGreetsNameParam = "name" 46 | homeGreetsDefaultName = []byte("Guest") 47 | homeCounterTpl = []byte("This page was viewed: ") 48 | homeCounterEnd = []byte(" times") 49 | ) 50 | 51 | func homeHandler(ctx *fasthttp.RequestCtx) { 52 | ctx.Write(homeGreetsTpl) 53 | if name := ctx.UserValue(homeGreetsNameParam); name != nil && len(name.(string)) > 0 { 54 | ctx.WriteString(name.(string)) 55 | } else { 56 | ctx.Write(homeGreetsDefaultName) 57 | } 58 | filter := map[string]interface{}{ 59 | "uri": string(ctx.URI().Path()), 60 | } 61 | var ( 62 | tmp []interface{} 63 | count = float64(0) 64 | ) 65 | f, _ := r.Table("stats").Filter(filter).Run(rdb) 66 | f.All(&tmp) 67 | f.Close() 68 | if len(tmp) > 0 { 69 | r.Table("stats").Filter(filter).Update(map[string]interface{}{ 70 | "views": r.Row.Field("views").Add(1).Default(0), 71 | }).RunWrite(rdb) 72 | v, _ := r.Table("stats").Filter(filter).Run(rdb) 73 | c := map[string]interface{}{} 74 | v.Peek(&c) 75 | count = c["views"].(float64) 76 | v.Close() 77 | } else { 78 | filter["views"] = 1 79 | r.Table("stats").Insert(filter).RunWrite(rdb) 80 | count = 1 81 | } 82 | fmt.Fprintln(ctx) 83 | ctx.Write(homeCounterTpl) 84 | fmt.Fprint(ctx, count) 85 | ctx.Write(homeCounterEnd) 86 | } 87 | `) 88 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:53 89 | } 90 | 91 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:53 92 | func WriteHomeHandler(qq422016 qtio422016.Writer, packageName string) { 93 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:53 94 | qw422016 := qt422016.AcquireWriter(qq422016) 95 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:53 96 | StreamHomeHandler(qw422016, packageName) 97 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:53 98 | qt422016.ReleaseWriter(qw422016) 99 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:53 100 | } 101 | 102 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:53 103 | func HomeHandler(packageName string) string { 104 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:53 105 | qb422016 := qt422016.AcquireByteBuffer() 106 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:53 107 | WriteHomeHandler(qb422016, packageName) 108 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:53 109 | qs422016 := string(qb422016.B) 110 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:53 111 | qt422016.ReleaseByteBuffer(qb422016) 112 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:53 113 | return qs422016 114 | //line lib/templates/webrdb/qtpl/homeHandler.qtpl:53 115 | } 116 | -------------------------------------------------------------------------------- /lib/templates/web/qtpl/fasthttp_router.qtpl.go: -------------------------------------------------------------------------------- 1 | // This file is automatically generated by qtc from "fasthttp_router.qtpl". 2 | // See https://github.com/valyala/quicktemplate for details. 3 | 4 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:1 5 | package qtpl 6 | 7 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:1 8 | import ( 9 | qtio422016 "io" 10 | 11 | qt422016 "github.com/valyala/quicktemplate" 12 | ) 13 | 14 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:1 15 | var ( 16 | _ = qtio422016.Copy 17 | _ = qt422016.AcquireByteBuffer 18 | ) 19 | 20 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:1 21 | func StreamFastHTTPRouter(qw422016 *qt422016.Writer, packageName string) { 22 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:1 23 | if packageName == "main" { 24 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:1 25 | qw422016.N().S(`package main`) 26 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:1 27 | } else { 28 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:1 29 | qw422016.N().S(`package `) 30 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:1 31 | qw422016.E().S(packageName) 32 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:1 33 | } 34 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:1 35 | qw422016.N().S(` 36 | 37 | import (`) 38 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:3 39 | if packageName == "main" { 40 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:3 41 | qw422016.N().S(` 42 | "flag" 43 | `) 44 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:5 45 | } 46 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:5 47 | qw422016.N().S(` 48 | "github.com/kirillDanshin/dlog" 49 | "github.com/kirillDanshin/fap/web" 50 | "github.com/kirillDanshin/myutils" 51 | ) 52 | `) 53 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:10 54 | if packageName == "main" { 55 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:10 56 | qw422016.N().S(` 57 | var ( 58 | address = flag.String("address", "127.0.0.1:3270", "address to bind") 59 | )`) 60 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:13 61 | } 62 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:13 63 | qw422016.N().S(` 64 | 65 | `) 66 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:15 67 | if packageName == "main" { 68 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:15 69 | qw422016.N().S(`func main() { 70 | flag.Parse() 71 | addr := *address 72 | `) 73 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:18 74 | } else { 75 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:18 76 | qw422016.N().S(`func Run(addr string) {`) 77 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:18 78 | } 79 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:18 80 | qw422016.N().S(` 81 | dlog.F("Registering handlers") 82 | 83 | w := web.New(addr) 84 | 85 | w.RegisterChain(getRouteChain()) 86 | 87 | dlog.F("Listening on %s", addr) 88 | myutils.LogFatalError(w.ListenAndServeGZip()) 89 | } 90 | `) 91 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:28 92 | } 93 | 94 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:28 95 | func WriteFastHTTPRouter(qq422016 qtio422016.Writer, packageName string) { 96 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:28 97 | qw422016 := qt422016.AcquireWriter(qq422016) 98 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:28 99 | StreamFastHTTPRouter(qw422016, packageName) 100 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:28 101 | qt422016.ReleaseWriter(qw422016) 102 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:28 103 | } 104 | 105 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:28 106 | func FastHTTPRouter(packageName string) string { 107 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:28 108 | qb422016 := qt422016.AcquireByteBuffer() 109 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:28 110 | WriteFastHTTPRouter(qb422016, packageName) 111 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:28 112 | qs422016 := string(qb422016.B) 113 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:28 114 | qt422016.ReleaseByteBuffer(qb422016) 115 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:28 116 | return qs422016 117 | //line lib/templates/web/qtpl/fasthttp_router.qtpl:28 118 | } 119 | -------------------------------------------------------------------------------- /lib/templates/webrdb/qtpl/main.qtpl.go: -------------------------------------------------------------------------------- 1 | // This file is automatically generated by qtc from "main.qtpl". 2 | // See https://github.com/valyala/quicktemplate for details. 3 | 4 | //line lib/templates/webrdb/qtpl/main.qtpl:1 5 | package qtpl 6 | 7 | //line lib/templates/webrdb/qtpl/main.qtpl:1 8 | import ( 9 | qtio422016 "io" 10 | 11 | qt422016 "github.com/valyala/quicktemplate" 12 | ) 13 | 14 | //line lib/templates/webrdb/qtpl/main.qtpl:1 15 | var ( 16 | _ = qtio422016.Copy 17 | _ = qt422016.AcquireByteBuffer 18 | ) 19 | 20 | //line lib/templates/webrdb/qtpl/main.qtpl:1 21 | func StreamFastHTTPRouter(qw422016 *qt422016.Writer, packageName string) { 22 | //line lib/templates/webrdb/qtpl/main.qtpl:1 23 | if packageName == "main" { 24 | //line lib/templates/webrdb/qtpl/main.qtpl:1 25 | qw422016.N().S(`package main`) 26 | //line lib/templates/webrdb/qtpl/main.qtpl:1 27 | } else { 28 | //line lib/templates/webrdb/qtpl/main.qtpl:1 29 | qw422016.N().S(`package `) 30 | //line lib/templates/webrdb/qtpl/main.qtpl:1 31 | qw422016.E().S(packageName) 32 | //line lib/templates/webrdb/qtpl/main.qtpl:1 33 | } 34 | //line lib/templates/webrdb/qtpl/main.qtpl:1 35 | qw422016.N().S(` 36 | 37 | import (`) 38 | //line lib/templates/webrdb/qtpl/main.qtpl:3 39 | if packageName == "main" { 40 | //line lib/templates/webrdb/qtpl/main.qtpl:3 41 | qw422016.N().S(` 42 | "flag" 43 | 44 | `) 45 | //line lib/templates/webrdb/qtpl/main.qtpl:6 46 | } 47 | //line lib/templates/webrdb/qtpl/main.qtpl:6 48 | qw422016.N().S(` "github.com/kirillDanshin/dlog" 49 | "github.com/kirillDanshin/fap/web" 50 | "github.com/kirillDanshin/myutils" 51 | 52 | r "gopkg.in/dancannon/gorethink.v2" 53 | ) 54 | var (`) 55 | //line lib/templates/webrdb/qtpl/main.qtpl:12 56 | if packageName == "main" { 57 | //line lib/templates/webrdb/qtpl/main.qtpl:12 58 | qw422016.N().S(` 59 | address = flag.String("address", "127.0.0.1:3270", "address to bind") 60 | rdbAddr = flag.String("rdbAddr", "127.0.0.1:28015", "rethinkdb address for connection") 61 | rDBName = flag.String("rDB", "fap", "rethinkdb database name") 62 | `) 63 | //line lib/templates/webrdb/qtpl/main.qtpl:16 64 | } 65 | //line lib/templates/webrdb/qtpl/main.qtpl:16 66 | qw422016.N().S(` 67 | rdb *r.Session 68 | ) 69 | `) 70 | //line lib/templates/webrdb/qtpl/main.qtpl:19 71 | if packageName == "main" { 72 | //line lib/templates/webrdb/qtpl/main.qtpl:19 73 | qw422016.N().S(`func main() { 74 | flag.Parse() 75 | addr := *address 76 | rdbAddress := *rdbAddr 77 | rDB := *rDBName 78 | `) 79 | //line lib/templates/webrdb/qtpl/main.qtpl:24 80 | } else { 81 | //line lib/templates/webrdb/qtpl/main.qtpl:24 82 | qw422016.N().S(`func Run(addr, rdbAddress, rDB string) {`) 83 | //line lib/templates/webrdb/qtpl/main.qtpl:24 84 | } 85 | //line lib/templates/webrdb/qtpl/main.qtpl:24 86 | qw422016.N().S(` 87 | var err error 88 | 89 | dlog.F("Connecting to RethinkDB") 90 | rdb, err = r.Connect(r.ConnectOpts{ 91 | Address: rdbAddress, 92 | Database: rDB, 93 | }) 94 | myutils.LogFatalError(err) 95 | 96 | r.DBCreate(rDB).Run(rdb) 97 | 98 | tl := []string{} 99 | req, err := r.TableList().Run(rdb) 100 | r.TableCreate("stats").Run(rdb) 101 | myutils.LogFatalError(err) 102 | 103 | dlog.D(req.All(&tl)) 104 | dlog.D(tl) 105 | 106 | w := web.New(addr) 107 | 108 | dlog.F("Registering handlers") 109 | 110 | w.RegisterChain(getRouteChain()) 111 | 112 | dlog.F("Listening on %s", addr) 113 | myutils.LogFatalError(w.ListenAndServeGZip()) 114 | } 115 | `) 116 | //line lib/templates/webrdb/qtpl/main.qtpl:53 117 | } 118 | 119 | //line lib/templates/webrdb/qtpl/main.qtpl:53 120 | func WriteFastHTTPRouter(qq422016 qtio422016.Writer, packageName string) { 121 | //line lib/templates/webrdb/qtpl/main.qtpl:53 122 | qw422016 := qt422016.AcquireWriter(qq422016) 123 | //line lib/templates/webrdb/qtpl/main.qtpl:53 124 | StreamFastHTTPRouter(qw422016, packageName) 125 | //line lib/templates/webrdb/qtpl/main.qtpl:53 126 | qt422016.ReleaseWriter(qw422016) 127 | //line lib/templates/webrdb/qtpl/main.qtpl:53 128 | } 129 | 130 | //line lib/templates/webrdb/qtpl/main.qtpl:53 131 | func FastHTTPRouter(packageName string) string { 132 | //line lib/templates/webrdb/qtpl/main.qtpl:53 133 | qb422016 := qt422016.AcquireByteBuffer() 134 | //line lib/templates/webrdb/qtpl/main.qtpl:53 135 | WriteFastHTTPRouter(qb422016, packageName) 136 | //line lib/templates/webrdb/qtpl/main.qtpl:53 137 | qs422016 := string(qb422016.B) 138 | //line lib/templates/webrdb/qtpl/main.qtpl:53 139 | qt422016.ReleaseByteBuffer(qb422016) 140 | //line lib/templates/webrdb/qtpl/main.qtpl:53 141 | return qs422016 142 | //line lib/templates/webrdb/qtpl/main.qtpl:53 143 | } 144 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2016 Kirill Danshin and fap contributors 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------