├── .github
└── workflows
│ └── go.yml
├── LICENSE
├── README.md
├── _example
├── 01_simple
│ ├── .eevee.yml
│ ├── README.md
│ ├── config
│ │ └── user.yml
│ ├── dao
│ │ └── user.go
│ ├── entity
│ │ └── user.go
│ ├── go.mod
│ ├── go.sum
│ ├── mock
│ │ ├── model
│ │ │ └── factory
│ │ │ │ └── user.go
│ │ └── repository
│ │ │ ├── repository.go
│ │ │ └── user.go
│ ├── model
│ │ ├── model.go
│ │ └── user.go
│ ├── repository
│ │ ├── repository.go
│ │ └── user.go
│ ├── schema
│ │ └── users.sql
│ ├── server.go
│ └── testdata
│ │ └── seeds
│ │ └── user.yml
├── 02_relation
│ ├── .eevee.yml
│ ├── README.md
│ ├── config
│ │ ├── field.yml
│ │ ├── group.yml
│ │ ├── skill.yml
│ │ ├── user.yml
│ │ ├── user_field.yml
│ │ └── world.yml
│ ├── dao
│ │ ├── field.go
│ │ ├── group.go
│ │ ├── skill.go
│ │ ├── user.go
│ │ ├── user_field.go
│ │ └── world.go
│ ├── db
│ │ └── init.go
│ ├── entity
│ │ ├── field.go
│ │ ├── group.go
│ │ ├── skill.go
│ │ ├── user.go
│ │ ├── user_field.go
│ │ └── world.go
│ ├── go.mod
│ ├── go.sum
│ ├── graph
│ │ ├── index.html
│ │ └── viz.js
│ ├── mock
│ │ ├── model
│ │ │ └── factory
│ │ │ │ ├── field.go
│ │ │ │ ├── group.go
│ │ │ │ ├── skill.go
│ │ │ │ ├── user.go
│ │ │ │ ├── user_field.go
│ │ │ │ └── world.go
│ │ └── repository
│ │ │ ├── field.go
│ │ │ ├── group.go
│ │ │ ├── repository.go
│ │ │ ├── skill.go
│ │ │ ├── user.go
│ │ │ ├── user_field.go
│ │ │ └── world.go
│ ├── model
│ │ ├── field.go
│ │ ├── group.go
│ │ ├── model.go
│ │ ├── skill.go
│ │ ├── user.go
│ │ ├── user_api.go
│ │ ├── user_field.go
│ │ └── world.go
│ ├── repository
│ │ ├── field.go
│ │ ├── group.go
│ │ ├── repository.go
│ │ ├── skill.go
│ │ ├── user.go
│ │ ├── user_field.go
│ │ └── world.go
│ ├── schema
│ │ ├── fields.sql
│ │ ├── groups.sql
│ │ ├── skills.sql
│ │ ├── user_fields.sql
│ │ ├── users.sql
│ │ └── worlds.sql
│ ├── server.go
│ ├── server_test.go
│ └── testdata
│ │ └── seeds
│ │ ├── field.yml
│ │ ├── group.yml
│ │ ├── skill.yml
│ │ ├── user.yml
│ │ ├── user_field.yml
│ │ └── world.yml
├── 03_api
│ ├── .eevee.yml
│ ├── README.md
│ ├── config
│ │ ├── api
│ │ │ └── user.yml
│ │ └── relation
│ │ │ ├── field.yml
│ │ │ ├── group.yml
│ │ │ ├── skill.yml
│ │ │ ├── user.yml
│ │ │ ├── user_field.yml
│ │ │ └── world.yml
│ ├── dao
│ │ ├── field.go
│ │ ├── group.go
│ │ ├── skill.go
│ │ ├── user.go
│ │ ├── user_field.go
│ │ └── world.go
│ ├── db
│ │ └── init.go
│ ├── docs
│ │ ├── index.md
│ │ └── user_getter.md
│ ├── entity
│ │ ├── field.go
│ │ ├── group.go
│ │ ├── skill.go
│ │ ├── user.go
│ │ ├── user_field.go
│ │ └── world.go
│ ├── go.mod
│ ├── go.sum
│ ├── graph
│ │ ├── index.html
│ │ └── viz.js
│ ├── mock
│ │ ├── model
│ │ │ ├── factory
│ │ │ │ ├── field.go
│ │ │ │ ├── group.go
│ │ │ │ ├── skill.go
│ │ │ │ ├── user.go
│ │ │ │ ├── user_field.go
│ │ │ │ └── world.go
│ │ │ ├── field.go
│ │ │ ├── group.go
│ │ │ ├── skill.go
│ │ │ ├── user.go
│ │ │ ├── user_field.go
│ │ │ └── world.go
│ │ └── repository
│ │ │ ├── field.go
│ │ │ ├── group.go
│ │ │ ├── repository.go
│ │ │ ├── skill.go
│ │ │ ├── user.go
│ │ │ ├── user_field.go
│ │ │ └── world.go
│ ├── model
│ │ ├── field.go
│ │ ├── group.go
│ │ ├── model.go
│ │ ├── skill.go
│ │ ├── user.go
│ │ ├── user_api.go
│ │ ├── user_field.go
│ │ └── world.go
│ ├── repository
│ │ ├── field.go
│ │ ├── group.go
│ │ ├── repository.go
│ │ ├── skill.go
│ │ ├── user.go
│ │ ├── user_field.go
│ │ └── world.go
│ ├── request
│ │ └── user_getter.go
│ ├── response
│ │ └── user_getter.go
│ ├── schema
│ │ ├── fields.sql
│ │ ├── groups.sql
│ │ ├── skills.sql
│ │ ├── user_fields.sql
│ │ ├── users.sql
│ │ └── worlds.sql
│ ├── server.go
│ └── testdata
│ │ └── seeds
│ │ ├── field.yml
│ │ ├── group.yml
│ │ ├── skill.yml
│ │ ├── user.yml
│ │ ├── user_field.yml
│ │ └── world.yml
├── 04_dao_plugin
│ ├── .eevee.yml
│ ├── README.md
│ ├── config
│ │ ├── field.yml
│ │ ├── group.yml
│ │ ├── skill.yml
│ │ ├── user.yml
│ │ ├── user_field.yml
│ │ └── world.yml
│ ├── dao
│ │ ├── field.go
│ │ ├── group.go
│ │ ├── skill.go
│ │ ├── user.go
│ │ ├── user_field.go
│ │ └── world.go
│ ├── db
│ │ └── init.go
│ ├── entity
│ │ ├── field.go
│ │ ├── group.go
│ │ ├── skill.go
│ │ ├── user.go
│ │ ├── user_field.go
│ │ └── world.go
│ ├── go.mod
│ ├── go.sum
│ ├── graph
│ │ ├── index.html
│ │ └── viz.js
│ ├── mock
│ │ ├── model
│ │ │ ├── factory
│ │ │ │ ├── field.go
│ │ │ │ ├── group.go
│ │ │ │ ├── skill.go
│ │ │ │ ├── user.go
│ │ │ │ ├── user_field.go
│ │ │ │ └── world.go
│ │ │ ├── field.go
│ │ │ ├── group.go
│ │ │ ├── skill.go
│ │ │ ├── user.go
│ │ │ ├── user_field.go
│ │ │ └── world.go
│ │ └── repository
│ │ │ ├── field.go
│ │ │ ├── group.go
│ │ │ ├── repository.go
│ │ │ ├── skill.go
│ │ │ ├── user.go
│ │ │ ├── user_field.go
│ │ │ └── world.go
│ ├── model
│ │ ├── field.go
│ │ ├── group.go
│ │ ├── model.go
│ │ ├── skill.go
│ │ ├── user.go
│ │ ├── user_api.go
│ │ ├── user_field.go
│ │ └── world.go
│ ├── repository
│ │ ├── field.go
│ │ ├── group.go
│ │ ├── repository.go
│ │ ├── skill.go
│ │ ├── user.go
│ │ ├── user_field.go
│ │ └── world.go
│ ├── schema
│ │ ├── fields.sql
│ │ ├── groups.sql
│ │ ├── skills.sql
│ │ ├── user_fields.sql
│ │ ├── users.sql
│ │ └── worlds.sql
│ ├── server.go
│ ├── server_test.go
│ └── testdata
│ │ └── seeds
│ │ ├── field.yml
│ │ ├── group.yml
│ │ ├── skill.yml
│ │ ├── user.yml
│ │ ├── user_field.yml
│ │ └── world.yml
└── 05_rapidash_plugin
│ ├── .eevee.yml
│ ├── README.md
│ ├── config
│ ├── field.yml
│ ├── group.yml
│ ├── skill.yml
│ ├── user.yml
│ ├── user_field.yml
│ └── world.yml
│ ├── dao
│ ├── field.go
│ ├── group.go
│ ├── skill.go
│ ├── user.go
│ ├── user_field.go
│ └── world.go
│ ├── db
│ └── init.go
│ ├── entity
│ ├── field.go
│ ├── group.go
│ ├── skill.go
│ ├── user.go
│ ├── user_field.go
│ └── world.go
│ ├── go.mod
│ ├── go.sum
│ ├── mock
│ ├── model
│ │ └── factory
│ │ │ ├── field.go
│ │ │ ├── group.go
│ │ │ ├── skill.go
│ │ │ ├── user.go
│ │ │ ├── user_field.go
│ │ │ └── world.go
│ └── repository
│ │ ├── field.go
│ │ ├── group.go
│ │ ├── repository.go
│ │ ├── skill.go
│ │ ├── user.go
│ │ ├── user_field.go
│ │ └── world.go
│ ├── model
│ ├── field.go
│ ├── group.go
│ ├── model.go
│ ├── skill.go
│ ├── user.go
│ ├── user_field.go
│ └── world.go
│ ├── repository
│ ├── field.go
│ ├── group.go
│ ├── repository.go
│ ├── skill.go
│ ├── user.go
│ ├── user_field.go
│ └── world.go
│ ├── schema
│ ├── fields.sql
│ ├── groups.sql
│ ├── skills.sql
│ ├── user_fields.sql
│ ├── users.sql
│ └── worlds.sql
│ ├── server.go
│ ├── server_test.go
│ └── testdata
│ └── seeds
│ ├── field.yml
│ ├── group.yml
│ ├── skill.yml
│ ├── user.yml
│ ├── user_field.yml
│ └── world.yml
├── api
└── api.go
├── class
├── class.go
├── class_test.go
└── testdata
│ ├── class
│ ├── field.yml
│ ├── group.yml
│ ├── skill.yml
│ ├── user.yml
│ ├── user_field.yml
│ └── world.yml
│ └── schema
│ ├── fields.sql
│ ├── groups.sql
│ ├── skills.sql
│ ├── user_fields.sql
│ ├── users.sql
│ └── worlds.sql
├── cmd
└── eevee
│ └── main.go
├── code
├── code.go
└── extention.go
├── config
├── config.go
├── config_test.go
└── testdata
│ └── eevee.yml
├── dao
├── dao.go
├── dao_test.go
└── testdata
│ ├── class
│ ├── field.yml
│ ├── group.yml
│ ├── skill.yml
│ ├── user.yml
│ ├── user_field.yml
│ └── world.yml
│ ├── dao
│ ├── field.go
│ ├── group.go
│ ├── skill.go
│ ├── user.go
│ ├── user_field.go
│ └── world.go
│ └── eevee.yml
├── eevee.go
├── entity
├── entity.go
├── entity_test.go
└── testdata
│ ├── class
│ ├── field.yml
│ ├── group.yml
│ ├── skill.yml
│ ├── user.yml
│ ├── user_field.yml
│ └── world.yml
│ ├── entity
│ ├── field.go
│ ├── group.go
│ ├── skill.go
│ ├── user.go
│ ├── user_field.go
│ └── world.go
│ └── schema
│ ├── fields.sql
│ ├── user_fields.sql
│ └── users.sql
├── go.mod
├── go.sum
├── graph
└── graph.go
├── model
├── model.go
├── model_test.go
├── render_option.go
├── template.go
└── testdata
│ ├── class
│ ├── field.yml
│ ├── group.yml
│ ├── skill.yml
│ ├── user.yml
│ ├── user_field.yml
│ └── world.yml
│ ├── model
│ ├── field.go
│ ├── group.go
│ ├── model.go
│ ├── skill.go
│ ├── user.go
│ ├── user_field.go
│ └── world.go
│ └── schema
│ ├── fields.sql
│ ├── user_fields.sql
│ └── users.sql
├── plugin
├── dao
│ ├── db.go
│ ├── default.go
│ └── interface.go
├── eevee-octillery-plugin
│ └── dao.go
├── eevee-rapidash-plugin
│ ├── dao.go
│ └── entity.go
├── eevee-request-time-plugin
│ └── dao.go
├── eevee-user-id-plugin
│ └── dao.go
├── entity
│ └── interface.go
└── plugin.go
├── plural
└── plural.go
├── renderer
├── json.go
├── map.go
└── renderer.go
├── repository
├── repository.go
├── repository_test.go
├── template.go
└── testdata
│ ├── class
│ ├── field.yml
│ ├── group.yml
│ ├── skill.yml
│ ├── user.yml
│ ├── user_field.yml
│ └── world.yml
│ ├── mock
│ └── repository
│ │ ├── field.go
│ │ ├── group.go
│ │ ├── repository.go
│ │ ├── skill.go
│ │ ├── user.go
│ │ ├── user_field.go
│ │ └── world.go
│ ├── model
│ ├── field.go
│ ├── user.go
│ └── user_field.go
│ ├── repository
│ ├── field.go
│ ├── group.go
│ ├── repository.go
│ ├── skill.go
│ ├── user.go
│ ├── user_field.go
│ └── world.go
│ └── schema
│ ├── fields.sql
│ ├── user_fields.sql
│ └── users.sql
├── schema
├── schema.go
├── schema_test.go
└── testdata
│ └── schema
│ ├── fields.sql
│ ├── user_fields.sql
│ └── users.sql
├── static
├── resources
│ ├── doc.tmpl
│ ├── graph.tmpl
│ ├── index.tmpl
│ └── viz.js
└── statik.go
├── test
└── test.go
├── types
├── api.go
├── dao.go
├── entity.go
├── model.go
├── name.go
├── repository.go
└── type.go
└── watcher
└── watcher.go
/.github/workflows/go.yml:
--------------------------------------------------------------------------------
1 | name: Go
2 | on: [push]
3 | jobs:
4 | build:
5 | name: Build
6 | runs-on: ubuntu-latest
7 | steps:
8 | - name: Set up Go 1.13
9 | uses: actions/setup-go@v1
10 | with:
11 | go-version: 1.13
12 | id: go
13 |
14 | - name: Check out code into the Go module directory
15 | uses: actions/checkout@v2
16 |
17 | - name: Build
18 | run: go build -v cmd/eevee/main.go
19 |
20 | - name: Test
21 | env:
22 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
23 | run: |
24 | go test -v -coverprofile=coverage.out ./...
25 | bash <(curl -s https://codecov.io/bash)
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Knocknote, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/_example/01_simple/.eevee.yml:
--------------------------------------------------------------------------------
1 | module: simple
2 | class: config
3 | schema: schema
4 |
--------------------------------------------------------------------------------
/_example/01_simple/config/user.yml:
--------------------------------------------------------------------------------
1 | name: user
2 | datastore: db
3 | index:
4 | primary_key: id
5 | members:
6 | - name: id
7 | type: uint64
8 | - name: name
9 | type: string
10 |
--------------------------------------------------------------------------------
/_example/01_simple/entity/user.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type User struct {
6 | ID uint64 `json:"id"`
7 | Name string `json:"name"`
8 | }
9 |
10 | type Users []*User
11 |
12 | func (e Users) IDs() []uint64 {
13 | values := make([]uint64, 0, len(e))
14 | for _, value := range e {
15 | values = append(values, value.ID)
16 | }
17 | return values
18 | }
19 |
20 | func (e Users) Names() []string {
21 | values := make([]string, 0, len(e))
22 | for _, value := range e {
23 | values = append(values, value.Name)
24 | }
25 | return values
26 | }
27 |
--------------------------------------------------------------------------------
/_example/01_simple/go.mod:
--------------------------------------------------------------------------------
1 | module simple
2 |
3 | go 1.12
4 |
5 | require (
6 | github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
7 | github.com/go-sql-driver/mysql v1.4.1
8 | github.com/labstack/echo v3.3.10+incompatible
9 | github.com/labstack/gommon v0.3.0 // indirect
10 | golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 // indirect
11 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7
12 | google.golang.org/appengine v1.6.5 // indirect
13 | )
14 |
--------------------------------------------------------------------------------
/_example/01_simple/mock/model/factory/user.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "simple/entity"
7 | "simple/model"
8 | )
9 |
10 | func DefaultUser() *model.User {
11 | value := &model.User{User: &entity.User{
12 | ID: 0,
13 | Name: "",
14 | }}
15 | return value
16 | }
17 |
18 | func DefaultUsers() *model.Users {
19 | values := &model.Users{}
20 | {
21 | value := &model.User{User: &entity.User{
22 | ID: 0,
23 | Name: "",
24 | }}
25 | values.Add(value)
26 | }
27 | return values
28 | }
29 |
--------------------------------------------------------------------------------
/_example/01_simple/mock/repository/repository.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package repository
4 |
5 | import (
6 | "simple/entity"
7 | "simple/model"
8 | "simple/repository"
9 | )
10 |
11 | type RepositoryMock struct {
12 | user func() *UserMock
13 | }
14 |
15 | func (r *RepositoryMock) User() repository.User {
16 | return r.user()
17 | }
18 | func (r *RepositoryMock) UserMock() *UserMock {
19 | return r.user()
20 | }
21 |
22 | func NewMock() *RepositoryMock {
23 | var (
24 | repo *RepositoryMock
25 | user *UserMock
26 | )
27 | repo = &RepositoryMock{user: func() *UserMock {
28 | if user != nil {
29 | return user
30 | }
31 | user = NewUserMock()
32 | return user
33 | }}
34 | return repo
35 | }
36 |
37 | func (r *RepositoryMock) ToUser(value *entity.User) *model.User {
38 | return r.User().ToModel(value)
39 | }
40 |
--------------------------------------------------------------------------------
/_example/01_simple/model/model.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "context"
7 | "simple/entity"
8 | )
9 |
10 | type ModelConverter interface {
11 | ToUser(*entity.User) *User
12 | }
13 |
14 | type BeforeRenderer interface {
15 | BeforeRender(context.Context) error
16 | }
17 |
18 | type RenderOption struct {
19 | Name string
20 | IsIncludeAll bool
21 | onlyNames map[string]struct{}
22 | exceptNames map[string]struct{}
23 | includes map[string]*RenderOption
24 | }
25 |
26 | func (ro *RenderOption) Exists(name string) bool {
27 | if len(ro.onlyNames) > 0 {
28 | if _, exists := ro.onlyNames[name]; exists {
29 | return true
30 | }
31 | return false
32 | }
33 | if len(ro.exceptNames) > 0 {
34 | if _, exists := ro.exceptNames[name]; exists {
35 | return false
36 | }
37 | return true
38 | }
39 | return true
40 | }
41 |
42 | func (ro *RenderOption) IncludeOption(name string) *RenderOption {
43 | if ro.Name == name {
44 | return ro
45 | }
46 | return ro.includes[name]
47 | }
48 |
49 | type RenderOptionBuilder struct {
50 | onlyNames map[string]struct{}
51 | exceptNames map[string]struct{}
52 | includes map[string]*RenderOption
53 | isIncludeAll bool
54 | }
55 |
56 | func NewRenderOptionBuilder() *RenderOptionBuilder {
57 | return &RenderOptionBuilder{
58 | exceptNames: map[string]struct{}{},
59 | includes: map[string]*RenderOption{},
60 | onlyNames: map[string]struct{}{},
61 | }
62 | }
63 |
64 | func (b *RenderOptionBuilder) Only(names ...string) *RenderOptionBuilder {
65 | for _, name := range names {
66 | b.onlyNames[name] = struct{}{}
67 | }
68 | return b
69 | }
70 |
71 | func (b *RenderOptionBuilder) Except(names ...string) *RenderOptionBuilder {
72 | for _, name := range names {
73 | b.exceptNames[name] = struct{}{}
74 | }
75 | return b
76 | }
77 |
78 | func (b *RenderOptionBuilder) Include(name string) *RenderOptionBuilder {
79 | b.includes[name] = &RenderOption{Name: name}
80 | return b
81 | }
82 |
83 | func (b *RenderOptionBuilder) IncludeWithCallback(name string, callback func(*RenderOptionBuilder)) *RenderOptionBuilder {
84 | builder := NewRenderOptionBuilder()
85 | callback(builder)
86 | opt := builder.Build()
87 | opt.Name = name
88 | b.includes[name] = opt
89 | return b
90 | }
91 |
92 | func (b *RenderOptionBuilder) IncludeAll() *RenderOptionBuilder {
93 | b.isIncludeAll = true
94 | return b
95 | }
96 |
97 | func (b *RenderOptionBuilder) Build() *RenderOption {
98 | return &RenderOption{
99 | IsIncludeAll: b.isIncludeAll,
100 | exceptNames: b.exceptNames,
101 | includes: b.includes,
102 | onlyNames: b.onlyNames,
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/_example/01_simple/repository/repository.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package repository
4 |
5 | import (
6 | "context"
7 | "database/sql"
8 | "simple/entity"
9 | "simple/model"
10 | )
11 |
12 | type Repository interface {
13 | User() User
14 | ToUser(*entity.User) *model.User
15 | }
16 |
17 | type RepositoryImpl struct {
18 | user func() User
19 | }
20 |
21 | func (r *RepositoryImpl) User() User {
22 | return r.user()
23 | }
24 |
25 | func New(ctx context.Context, tx *sql.Tx) *RepositoryImpl {
26 | var (
27 | repo *RepositoryImpl
28 | user *UserImpl
29 | )
30 | repo = &RepositoryImpl{user: func() User {
31 | if user != nil {
32 | return user
33 | }
34 | user = NewUser(ctx, tx)
35 | user.repo = repo
36 | return user
37 | }}
38 | return repo
39 | }
40 |
41 | func (r *RepositoryImpl) ToUser(value *entity.User) *model.User {
42 | return r.User().ToModel(value)
43 | }
44 |
--------------------------------------------------------------------------------
/_example/01_simple/schema/users.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `users` (
2 | `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
3 | `name` varchar(30) DEFAULT NULL,
4 | PRIMARY KEY (`id`)
5 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 |
--------------------------------------------------------------------------------
/_example/01_simple/testdata/seeds/user.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | id: 0
4 | name: ""
5 | collection:
6 | defaults:
7 | - *default
8 |
--------------------------------------------------------------------------------
/_example/02_relation/.eevee.yml:
--------------------------------------------------------------------------------
1 | module: relation
2 | graph: graph
3 | class: config
4 | schema: schema
5 |
--------------------------------------------------------------------------------
/_example/02_relation/README.md:
--------------------------------------------------------------------------------
1 | # How to work example
2 |
3 | ## 1. Automatically resolve relationships between tables at render
4 |
5 | ```go
6 | func getUser(c echo.Context) error {
7 | id, _ := strconv.Atoi(c.Param("id"))
8 | tx, err := db.Begin()
9 | if err != nil {
10 | return err
11 | }
12 | ctx := context.Background()
13 | repo := repository.New(ctx, tx)
14 | user, err := repo.User().FindByID(ctx, uint64(id))
15 | if err != nil {
16 | return err
17 | }
18 | if err := c.JSON(http.StatusOK, user); err != nil {
19 | return err
20 | }
21 | if err := tx.Commit(); err != nil {
22 | return err
23 | }
24 | return nil
25 | }
26 | ```
27 |
28 | ```bash
29 | $ curl localhost:1323/users/1 | jq '.'
30 | ```
31 |
32 | ```json
33 | {
34 | "id": 1,
35 | "name": "john",
36 | "sex": "man",
37 | "age": 30,
38 | "skillId": 1,
39 | "skillRank": 10,
40 | "groupId": 1,
41 | "worldId": 1,
42 | "fieldId": 1,
43 | "userFields": [
44 | {
45 | "id": 1,
46 | "userId": 1,
47 | "fieldId": 1,
48 | "field": {
49 | "id": 1,
50 | "name": "fieldA",
51 | "locationX": 2,
52 | "locationY": 3,
53 | "objectNum": 10,
54 | "level": 20,
55 | "difficulty": 5
56 | }
57 | }
58 | ],
59 | "skillEffect": "fire",
60 | "group": null
61 | }
62 | ```
63 |
--------------------------------------------------------------------------------
/_example/02_relation/config/field.yml:
--------------------------------------------------------------------------------
1 | name: field
2 | datastore: db
3 | index:
4 | primary_key: id
5 | unique_keys:
6 | - - name
7 | - - location_x
8 | - location_y
9 | keys:
10 | - - object_num
11 | - - difficulty
12 | - level
13 | members:
14 | - name: id
15 | type: uint64
16 | - name: name
17 | type: string
18 | - name: location_x
19 | type: int
20 | - name: location_y
21 | type: int
22 | - name: object_num
23 | type: int
24 | - name: level
25 | type: int
26 | - name: difficulty
27 | type: int
28 |
--------------------------------------------------------------------------------
/_example/02_relation/config/group.yml:
--------------------------------------------------------------------------------
1 | name: group
2 | datastore: db
3 | index:
4 | primary_key: id
5 | members:
6 | - name: id
7 | type: uint64
8 | - name: name
9 | type: string
10 |
--------------------------------------------------------------------------------
/_example/02_relation/config/skill.yml:
--------------------------------------------------------------------------------
1 | name: skill
2 | datastore: db
3 | index:
4 | primary_key: id
5 | members:
6 | - name: id
7 | type: uint64
8 | - name: skill_effect
9 | type: string
10 |
--------------------------------------------------------------------------------
/_example/02_relation/config/user.yml:
--------------------------------------------------------------------------------
1 | name: user
2 | datastore: db
3 | index:
4 | primary_key: id
5 | unique_keys:
6 | - - name
7 | - - skill_id
8 | - skill_rank
9 | keys:
10 | - - group_id
11 | - - world_id
12 | - field_id
13 | members:
14 | - name: id
15 | type: uint64
16 | - name: name
17 | type: string
18 | example: john
19 | - name: sex
20 | type: string
21 | - name: age
22 | type: int
23 | - name: skill_id
24 | type: uint64
25 | - name: skill_rank
26 | type: int
27 | - name: group_id
28 | type: uint64
29 | - name: world_id
30 | type: uint64
31 | - name: field_id
32 | type: uint64
33 | - name: user_fields
34 | extend: true
35 | has_many: true
36 | relation:
37 | to: user_field
38 | internal: id
39 | external: user_id
40 | - name: skill
41 | extend: true
42 | render:
43 | inline: true
44 | relation:
45 | to: skill
46 | internal: skill_id
47 | external: id
48 | - name: group
49 | extend: true
50 | render:
51 | json: group
52 | relation:
53 | custom: true
54 | to: group
55 | - name: world
56 | extend: true
57 | render: false
58 | relation:
59 | to: world
60 | internal: world_id
61 | external: id
62 |
--------------------------------------------------------------------------------
/_example/02_relation/config/user_field.yml:
--------------------------------------------------------------------------------
1 | name: user_field
2 | datastore: db
3 | index:
4 | primary_key: id
5 | unique_keys:
6 | - - user_id
7 | - field_id
8 | members:
9 | - name: id
10 | type: uint64
11 | - name: user_id
12 | type: uint64
13 | - name: field_id
14 | type: uint64
15 | - name: field
16 | extend: true
17 | relation:
18 | to: field
19 | internal: field_id
20 | external: id
21 |
--------------------------------------------------------------------------------
/_example/02_relation/config/world.yml:
--------------------------------------------------------------------------------
1 | name: world
2 | datastore: db
3 | index:
4 | primary_key: id
5 | members:
6 | - name: id
7 | type: uint64
8 | - name: name
9 | type: string
10 |
--------------------------------------------------------------------------------
/_example/02_relation/entity/field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type Field struct {
6 | ID uint64 `json:"id"`
7 | Name string `json:"name"`
8 | LocationX int `json:"locationX"`
9 | LocationY int `json:"locationY"`
10 | ObjectNum int `json:"objectNum"`
11 | Level int `json:"level"`
12 | Difficulty int `json:"difficulty"`
13 | }
14 |
15 | type Fields []*Field
16 |
17 | func (e Fields) IDs() []uint64 {
18 | values := make([]uint64, 0, len(e))
19 | for _, value := range e {
20 | values = append(values, value.ID)
21 | }
22 | return values
23 | }
24 |
25 | func (e Fields) Names() []string {
26 | values := make([]string, 0, len(e))
27 | for _, value := range e {
28 | values = append(values, value.Name)
29 | }
30 | return values
31 | }
32 |
33 | func (e Fields) LocationXes() []int {
34 | values := make([]int, 0, len(e))
35 | for _, value := range e {
36 | values = append(values, value.LocationX)
37 | }
38 | return values
39 | }
40 |
41 | func (e Fields) LocationIes() []int {
42 | values := make([]int, 0, len(e))
43 | for _, value := range e {
44 | values = append(values, value.LocationY)
45 | }
46 | return values
47 | }
48 |
49 | func (e Fields) ObjectNums() []int {
50 | values := make([]int, 0, len(e))
51 | for _, value := range e {
52 | values = append(values, value.ObjectNum)
53 | }
54 | return values
55 | }
56 |
57 | func (e Fields) Levels() []int {
58 | values := make([]int, 0, len(e))
59 | for _, value := range e {
60 | values = append(values, value.Level)
61 | }
62 | return values
63 | }
64 |
65 | func (e Fields) Difficulties() []int {
66 | values := make([]int, 0, len(e))
67 | for _, value := range e {
68 | values = append(values, value.Difficulty)
69 | }
70 | return values
71 | }
72 |
--------------------------------------------------------------------------------
/_example/02_relation/entity/group.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type Group struct {
6 | ID uint64 `json:"id"`
7 | Name string `json:"name"`
8 | }
9 |
10 | type Groups []*Group
11 |
12 | func (e Groups) IDs() []uint64 {
13 | values := make([]uint64, 0, len(e))
14 | for _, value := range e {
15 | values = append(values, value.ID)
16 | }
17 | return values
18 | }
19 |
20 | func (e Groups) Names() []string {
21 | values := make([]string, 0, len(e))
22 | for _, value := range e {
23 | values = append(values, value.Name)
24 | }
25 | return values
26 | }
27 |
--------------------------------------------------------------------------------
/_example/02_relation/entity/skill.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type Skill struct {
6 | ID uint64 `json:"id"`
7 | SkillEffect string `json:"skillEffect"`
8 | }
9 |
10 | type Skills []*Skill
11 |
12 | func (e Skills) IDs() []uint64 {
13 | values := make([]uint64, 0, len(e))
14 | for _, value := range e {
15 | values = append(values, value.ID)
16 | }
17 | return values
18 | }
19 |
20 | func (e Skills) SkillEffects() []string {
21 | values := make([]string, 0, len(e))
22 | for _, value := range e {
23 | values = append(values, value.SkillEffect)
24 | }
25 | return values
26 | }
27 |
--------------------------------------------------------------------------------
/_example/02_relation/entity/user.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type User struct {
6 | ID uint64 `json:"id"`
7 | Name string `json:"name"`
8 | Sex string `json:"sex"`
9 | Age int `json:"age"`
10 | SkillID uint64 `json:"skillID"`
11 | SkillRank int `json:"skillRank"`
12 | GroupID uint64 `json:"groupID"`
13 | WorldID uint64 `json:"worldID"`
14 | FieldID uint64 `json:"fieldID"`
15 | }
16 |
17 | type Users []*User
18 |
19 | func (e Users) IDs() []uint64 {
20 | values := make([]uint64, 0, len(e))
21 | for _, value := range e {
22 | values = append(values, value.ID)
23 | }
24 | return values
25 | }
26 |
27 | func (e Users) Names() []string {
28 | values := make([]string, 0, len(e))
29 | for _, value := range e {
30 | values = append(values, value.Name)
31 | }
32 | return values
33 | }
34 |
35 | func (e Users) Sexes() []string {
36 | values := make([]string, 0, len(e))
37 | for _, value := range e {
38 | values = append(values, value.Sex)
39 | }
40 | return values
41 | }
42 |
43 | func (e Users) Ages() []int {
44 | values := make([]int, 0, len(e))
45 | for _, value := range e {
46 | values = append(values, value.Age)
47 | }
48 | return values
49 | }
50 |
51 | func (e Users) SkillIDs() []uint64 {
52 | values := make([]uint64, 0, len(e))
53 | for _, value := range e {
54 | values = append(values, value.SkillID)
55 | }
56 | return values
57 | }
58 |
59 | func (e Users) SkillRanks() []int {
60 | values := make([]int, 0, len(e))
61 | for _, value := range e {
62 | values = append(values, value.SkillRank)
63 | }
64 | return values
65 | }
66 |
67 | func (e Users) GroupIDs() []uint64 {
68 | values := make([]uint64, 0, len(e))
69 | for _, value := range e {
70 | values = append(values, value.GroupID)
71 | }
72 | return values
73 | }
74 |
75 | func (e Users) WorldIDs() []uint64 {
76 | values := make([]uint64, 0, len(e))
77 | for _, value := range e {
78 | values = append(values, value.WorldID)
79 | }
80 | return values
81 | }
82 |
83 | func (e Users) FieldIDs() []uint64 {
84 | values := make([]uint64, 0, len(e))
85 | for _, value := range e {
86 | values = append(values, value.FieldID)
87 | }
88 | return values
89 | }
90 |
--------------------------------------------------------------------------------
/_example/02_relation/entity/user_field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type UserField struct {
6 | ID uint64 `json:"id"`
7 | UserID uint64 `json:"userID"`
8 | FieldID uint64 `json:"fieldID"`
9 | }
10 |
11 | type UserFields []*UserField
12 |
13 | func (e UserFields) IDs() []uint64 {
14 | values := make([]uint64, 0, len(e))
15 | for _, value := range e {
16 | values = append(values, value.ID)
17 | }
18 | return values
19 | }
20 |
21 | func (e UserFields) UserIDs() []uint64 {
22 | values := make([]uint64, 0, len(e))
23 | for _, value := range e {
24 | values = append(values, value.UserID)
25 | }
26 | return values
27 | }
28 |
29 | func (e UserFields) FieldIDs() []uint64 {
30 | values := make([]uint64, 0, len(e))
31 | for _, value := range e {
32 | values = append(values, value.FieldID)
33 | }
34 | return values
35 | }
36 |
--------------------------------------------------------------------------------
/_example/02_relation/entity/world.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type World struct {
6 | ID uint64 `json:"id"`
7 | Name string `json:"name"`
8 | }
9 |
10 | type Worlds []*World
11 |
12 | func (e Worlds) IDs() []uint64 {
13 | values := make([]uint64, 0, len(e))
14 | for _, value := range e {
15 | values = append(values, value.ID)
16 | }
17 | return values
18 | }
19 |
20 | func (e Worlds) Names() []string {
21 | values := make([]string, 0, len(e))
22 | for _, value := range e {
23 | values = append(values, value.Name)
24 | }
25 | return values
26 | }
27 |
--------------------------------------------------------------------------------
/_example/02_relation/go.mod:
--------------------------------------------------------------------------------
1 | module relation
2 |
3 | go 1.12
4 |
5 | require (
6 | github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
7 | github.com/go-sql-driver/mysql v1.4.1
8 | github.com/labstack/echo v3.3.10+incompatible
9 | github.com/labstack/gommon v0.3.0 // indirect
10 | golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 // indirect
11 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7
12 | google.golang.org/appengine v1.6.2 // indirect
13 | )
14 |
--------------------------------------------------------------------------------
/_example/02_relation/mock/model/factory/field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "relation/entity"
7 | "relation/model"
8 | )
9 |
10 | func DefaultField() *model.Field {
11 | value := &model.Field{Field: &entity.Field{
12 | Difficulty: 0,
13 | ID: 0,
14 | Level: 0,
15 | LocationX: 0,
16 | LocationY: 0,
17 | Name: "",
18 | ObjectNum: 0,
19 | }}
20 | return value
21 | }
22 |
23 | func DefaultFields() *model.Fields {
24 | values := &model.Fields{}
25 | {
26 | value := &model.Field{Field: &entity.Field{
27 | Difficulty: 0,
28 | ID: 0,
29 | Level: 0,
30 | LocationX: 0,
31 | LocationY: 0,
32 | Name: "",
33 | ObjectNum: 0,
34 | }}
35 | values.Add(value)
36 | }
37 | return values
38 | }
39 |
--------------------------------------------------------------------------------
/_example/02_relation/mock/model/factory/group.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "relation/entity"
7 | "relation/model"
8 | )
9 |
10 | func DefaultGroup() *model.Group {
11 | value := &model.Group{Group: &entity.Group{
12 | ID: 0,
13 | Name: "",
14 | }}
15 | return value
16 | }
17 |
18 | func DefaultGroups() *model.Groups {
19 | values := &model.Groups{}
20 | {
21 | value := &model.Group{Group: &entity.Group{
22 | ID: 0,
23 | Name: "",
24 | }}
25 | values.Add(value)
26 | }
27 | return values
28 | }
29 |
--------------------------------------------------------------------------------
/_example/02_relation/mock/model/factory/skill.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "relation/entity"
7 | "relation/model"
8 | )
9 |
10 | func DefaultSkill() *model.Skill {
11 | value := &model.Skill{Skill: &entity.Skill{
12 | ID: 0,
13 | SkillEffect: "",
14 | }}
15 | return value
16 | }
17 |
18 | func DefaultSkills() *model.Skills {
19 | values := &model.Skills{}
20 | {
21 | value := &model.Skill{Skill: &entity.Skill{
22 | ID: 0,
23 | SkillEffect: "",
24 | }}
25 | values.Add(value)
26 | }
27 | return values
28 | }
29 |
--------------------------------------------------------------------------------
/_example/02_relation/mock/model/factory/user.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "context"
7 | "relation/entity"
8 | "relation/model"
9 | )
10 |
11 | func DefaultUser() *model.User {
12 | userFields := DefaultUserFields()
13 | skill := DefaultSkill()
14 | world := DefaultWorld()
15 | value := &model.User{User: &entity.User{
16 | Age: 0,
17 | FieldID: 0,
18 | GroupID: 0,
19 | ID: 0,
20 | Name: "john",
21 | Sex: "",
22 | SkillID: 0,
23 | SkillRank: 0,
24 | WorldID: 0,
25 | }}
26 | value.UserFields = func(context.Context) (*model.UserFields, error) {
27 | return userFields, nil
28 | }
29 | value.Skill = func(context.Context) (*model.Skill, error) {
30 | return skill, nil
31 | }
32 | value.World = func(context.Context) (*model.World, error) {
33 | return world, nil
34 | }
35 | return value
36 | }
37 |
38 | func DefaultUsers() *model.Users {
39 | values := &model.Users{}
40 | {
41 | userFields := DefaultUserFields()
42 | skill := DefaultSkill()
43 | world := DefaultWorld()
44 | value := &model.User{User: &entity.User{
45 | Age: 0,
46 | FieldID: 0,
47 | GroupID: 0,
48 | ID: 0,
49 | Name: "john",
50 | Sex: "",
51 | SkillID: 0,
52 | SkillRank: 0,
53 | WorldID: 0,
54 | }}
55 | value.UserFields = func(context.Context) (*model.UserFields, error) {
56 | return userFields, nil
57 | }
58 | value.Skill = func(context.Context) (*model.Skill, error) {
59 | return skill, nil
60 | }
61 | value.World = func(context.Context) (*model.World, error) {
62 | return world, nil
63 | }
64 | values.Add(value)
65 | }
66 | return values
67 | }
68 |
--------------------------------------------------------------------------------
/_example/02_relation/mock/model/factory/user_field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "context"
7 | "relation/entity"
8 | "relation/model"
9 | )
10 |
11 | func DefaultUserField() *model.UserField {
12 | field := DefaultField()
13 | value := &model.UserField{UserField: &entity.UserField{
14 | FieldID: 0,
15 | ID: 0,
16 | UserID: 0,
17 | }}
18 | value.Field = func(context.Context) (*model.Field, error) {
19 | return field, nil
20 | }
21 | return value
22 | }
23 |
24 | func DefaultUserFields() *model.UserFields {
25 | values := &model.UserFields{}
26 | {
27 | field := DefaultField()
28 | value := &model.UserField{UserField: &entity.UserField{
29 | FieldID: 0,
30 | ID: 0,
31 | UserID: 0,
32 | }}
33 | value.Field = func(context.Context) (*model.Field, error) {
34 | return field, nil
35 | }
36 | values.Add(value)
37 | }
38 | return values
39 | }
40 |
--------------------------------------------------------------------------------
/_example/02_relation/mock/model/factory/world.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "relation/entity"
7 | "relation/model"
8 | )
9 |
10 | func DefaultWorld() *model.World {
11 | value := &model.World{World: &entity.World{
12 | ID: 0,
13 | Name: "",
14 | }}
15 | return value
16 | }
17 |
18 | func DefaultWorlds() *model.Worlds {
19 | values := &model.Worlds{}
20 | {
21 | value := &model.World{World: &entity.World{
22 | ID: 0,
23 | Name: "",
24 | }}
25 | values.Add(value)
26 | }
27 | return values
28 | }
29 |
--------------------------------------------------------------------------------
/_example/02_relation/model/model.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "context"
7 | "relation/entity"
8 | )
9 |
10 | type ModelConverter interface {
11 | ToField(*entity.Field) *Field
12 | ToGroup(*entity.Group) *Group
13 | ToSkill(*entity.Skill) *Skill
14 | ToUser(*entity.User) *User
15 | ToUserField(*entity.UserField) *UserField
16 | ToWorld(*entity.World) *World
17 | }
18 |
19 | type BeforeRenderer interface {
20 | BeforeRender(context.Context) error
21 | }
22 |
23 | type RenderOption struct {
24 | Name string
25 | IsIncludeAll bool
26 | onlyNames map[string]struct{}
27 | exceptNames map[string]struct{}
28 | includes map[string]*RenderOption
29 | }
30 |
31 | func (ro *RenderOption) Exists(name string) bool {
32 | if len(ro.onlyNames) > 0 {
33 | if _, exists := ro.onlyNames[name]; exists {
34 | return true
35 | }
36 | return false
37 | }
38 | if len(ro.exceptNames) > 0 {
39 | if _, exists := ro.exceptNames[name]; exists {
40 | return false
41 | }
42 | return true
43 | }
44 | return true
45 | }
46 |
47 | func (ro *RenderOption) IncludeOption(name string) *RenderOption {
48 | if ro.Name == name {
49 | return ro
50 | }
51 | return ro.includes[name]
52 | }
53 |
54 | type RenderOptionBuilder struct {
55 | onlyNames map[string]struct{}
56 | exceptNames map[string]struct{}
57 | includes map[string]*RenderOption
58 | isIncludeAll bool
59 | }
60 |
61 | func NewRenderOptionBuilder() *RenderOptionBuilder {
62 | return &RenderOptionBuilder{
63 | exceptNames: map[string]struct{}{},
64 | includes: map[string]*RenderOption{},
65 | onlyNames: map[string]struct{}{},
66 | }
67 | }
68 |
69 | func (b *RenderOptionBuilder) Only(names ...string) *RenderOptionBuilder {
70 | for _, name := range names {
71 | b.onlyNames[name] = struct{}{}
72 | }
73 | return b
74 | }
75 |
76 | func (b *RenderOptionBuilder) Except(names ...string) *RenderOptionBuilder {
77 | for _, name := range names {
78 | b.exceptNames[name] = struct{}{}
79 | }
80 | return b
81 | }
82 |
83 | func (b *RenderOptionBuilder) Include(name string) *RenderOptionBuilder {
84 | b.includes[name] = &RenderOption{Name: name}
85 | return b
86 | }
87 |
88 | func (b *RenderOptionBuilder) IncludeWithCallback(name string, callback func(*RenderOptionBuilder)) *RenderOptionBuilder {
89 | builder := NewRenderOptionBuilder()
90 | callback(builder)
91 | opt := builder.Build()
92 | opt.Name = name
93 | b.includes[name] = opt
94 | return b
95 | }
96 |
97 | func (b *RenderOptionBuilder) IncludeAll() *RenderOptionBuilder {
98 | b.isIncludeAll = true
99 | return b
100 | }
101 |
102 | func (b *RenderOptionBuilder) Build() *RenderOption {
103 | return &RenderOption{
104 | IsIncludeAll: b.isIncludeAll,
105 | exceptNames: b.exceptNames,
106 | includes: b.includes,
107 | onlyNames: b.onlyNames,
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/_example/02_relation/model/user_api.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import "context"
4 |
5 | func (m *User) Group(ctx context.Context) (*Group, error) {
6 | return nil, nil
7 | }
8 |
--------------------------------------------------------------------------------
/_example/02_relation/schema/fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | `location_x` int NOT NULL,
5 | `location_y` int NOT NULL,
6 | `object_num` int NOT NULL,
7 | `level` int NOT NULL,
8 | `difficulty` int NOT NULL,
9 | PRIMARY KEY (`id`),
10 | UNIQUE KEY `uq_fields_01` (`name`),
11 | UNIQUE KEY `uq_fields_02` (`location_x`, `location_y`),
12 | KEY `idx_fields_03` (`object_num`),
13 | KEY `idx_fields_04` (`difficulty`, `level`)
14 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
15 |
16 |
--------------------------------------------------------------------------------
/_example/02_relation/schema/groups.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `groups` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | PRIMARY KEY (`id`)
5 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 |
--------------------------------------------------------------------------------
/_example/02_relation/schema/skills.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `skills` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `skill_effect` varchar(30) DEFAULT NULL,
4 | PRIMARY KEY (`id`)
5 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 |
--------------------------------------------------------------------------------
/_example/02_relation/schema/user_fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `user_fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `user_id` bigint(20) unsigned NOT NULL,
4 | `field_id` bigint(20) unsigned NOT NULL,
5 | PRIMARY KEY (`id`),
6 | UNIQUE KEY `uq_fields_01` (`user_id`, `field_id`)
7 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
8 |
9 |
--------------------------------------------------------------------------------
/_example/02_relation/schema/users.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `users` (
2 | `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
3 | `name` varchar(30) DEFAULT NULL,
4 | `sex` enum('man','woman') NOT NULL,
5 | `age` int NOT NULL,
6 | `skill_id` bigint(20) unsigned NOT NULL,
7 | `skill_rank` int NOT NULL,
8 | `group_id` bigint(20) unsigned NOT NULL,
9 | `world_id` bigint(20) unsigned NOT NULL,
10 | `field_id` bigint(20) unsigned NOT NULL,
11 | PRIMARY KEY (`id`),
12 | UNIQUE KEY `uq_users_01` (`name`),
13 | UNIQUE KEY `uq_users_02` (`skill_id`, `skill_rank`),
14 | KEY `idx_users_03` (`group_id`),
15 | KEY `idx_users_04` (`world_id`, `field_id`)
16 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
17 |
18 |
--------------------------------------------------------------------------------
/_example/02_relation/schema/worlds.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `worlds` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | PRIMARY KEY (`id`)
5 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 |
7 |
--------------------------------------------------------------------------------
/_example/02_relation/server.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "database/sql"
6 | "net/http"
7 | _ "relation/db"
8 | "relation/repository"
9 | "strconv"
10 |
11 | _ "github.com/go-sql-driver/mysql"
12 | "github.com/labstack/echo"
13 | "github.com/labstack/echo/middleware"
14 | )
15 |
16 | var (
17 | db *sql.DB
18 | )
19 |
20 | func getUser(c echo.Context) error {
21 | id, _ := strconv.Atoi(c.Param("id"))
22 | tx, err := db.Begin()
23 | if err != nil {
24 | return err
25 | }
26 | ctx := context.Background()
27 | repo := repository.New(ctx, tx)
28 | user, err := repo.User().FindByID(ctx, uint64(id))
29 | if err != nil {
30 | return err
31 | }
32 | if err := c.JSON(http.StatusOK, user); err != nil {
33 | return err
34 | }
35 | if err := tx.Commit(); err != nil {
36 | return err
37 | }
38 | return nil
39 | }
40 |
41 | func main() {
42 | e := echo.New()
43 |
44 | conn, err := sql.Open("mysql", "root:@tcp(localhost:3306)/eevee?parseTime=true")
45 | if err != nil {
46 | panic(err)
47 | }
48 | defer conn.Close()
49 |
50 | db = conn
51 |
52 | // Middleware
53 | e.Use(middleware.Logger())
54 | e.Use(middleware.Recover())
55 |
56 | // Routes
57 | e.GET("/users/:id", getUser)
58 |
59 | // Start server
60 | e.Logger.Fatal(e.Start(":1323"))
61 | }
62 |
--------------------------------------------------------------------------------
/_example/02_relation/server_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "relation/mock/model/factory"
6 | "relation/mock/repository"
7 | "testing"
8 | )
9 |
10 | func TestUserGet(t *testing.T) {
11 | repo := repository.NewMock()
12 | ctx := context.Background()
13 | repo.UserMock().EXPECT().FindByID(ctx, 1).Return(factory.DefaultUser(), nil)
14 | u, err := repo.User().FindByID(ctx, 1)
15 | if err != nil {
16 | t.Fatalf("%+v", err)
17 | }
18 | if u.ID != factory.DefaultUser().ID {
19 | t.Fatal("invalid user")
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/_example/02_relation/testdata/seeds/field.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | difficulty: 0
4 | id: 0
5 | level: 0
6 | location_x: 0
7 | location_y: 0
8 | name: ""
9 | object_num: 0
10 | collection:
11 | defaults:
12 | - *default
13 |
--------------------------------------------------------------------------------
/_example/02_relation/testdata/seeds/group.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | id: 0
4 | name: ""
5 | collection:
6 | defaults:
7 | - *default
8 |
--------------------------------------------------------------------------------
/_example/02_relation/testdata/seeds/skill.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | id: 0
4 | skill_effect: ""
5 | collection:
6 | defaults:
7 | - *default
8 |
--------------------------------------------------------------------------------
/_example/02_relation/testdata/seeds/user.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | age: 0
4 | field_id: 0
5 | group: $default
6 | group_id: 0
7 | id: 0
8 | name: john
9 | sex: ""
10 | skill: $default
11 | skill_id: 0
12 | skill_rank: 0
13 | user_fields: $default
14 | world: $default
15 | world_id: 0
16 | collection:
17 | defaults:
18 | - *default
19 |
--------------------------------------------------------------------------------
/_example/02_relation/testdata/seeds/user_field.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | field: $default
4 | field_id: 0
5 | id: 0
6 | user_id: 0
7 | collection:
8 | defaults:
9 | - *default
10 |
--------------------------------------------------------------------------------
/_example/02_relation/testdata/seeds/world.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | id: 0
4 | name: ""
5 | collection:
6 | defaults:
7 | - *default
8 |
--------------------------------------------------------------------------------
/_example/03_api/.eevee.yml:
--------------------------------------------------------------------------------
1 | module: api
2 | graph: graph
3 | class: config/relation
4 | api: config/api
5 |
--------------------------------------------------------------------------------
/_example/03_api/README.md:
--------------------------------------------------------------------------------
1 | # How to work example
2 |
3 | ## 1. Automatically filter response fields
4 |
5 | - Define API definition to config/api/user.yml
6 |
7 | ```yaml
8 | - name: user_getter
9 | desc: return user status
10 | uri: /users/:user_id
11 | method: get
12 | response:
13 | subtypes:
14 | - name: user_getter_subtype
15 | members:
16 | - name: user
17 | type: user
18 | render:
19 | inline: true
20 | - name: param1
21 | type: string
22 | - name: param2
23 | type: int
24 | include:
25 | - name: user
26 | only:
27 | - name
28 | - param1
29 | - param2
30 | include:
31 | - name: user_fields
32 | only:
33 | - field_id
34 | include:
35 | - name: field
36 | only:
37 | - name
38 | type:
39 | - name: user
40 | type: user_getter_subtype
41 | render:
42 | json: user
43 | desc: user status
44 | - name: param1
45 | type: string
46 | desc: param1
47 | ```
48 |
49 | - Run eevee
50 |
51 | ```bash
52 | $ eevee -r config/relation
53 | ```
54 |
55 | - Use response package
56 |
57 | ```go
58 | func getUser(c echo.Context) error {
59 | id, _ := strconv.Atoi(c.Param("id"))
60 | tx, err := db.Begin()
61 | if err != nil {
62 | return err
63 | }
64 | ctx := context.Background()
65 | repo := repository.New(ctx, tx)
66 | user, err := repo.User().FindByID(ctx, uint64(id))
67 | if err != nil {
68 | return err
69 | }
70 | response, err := new(response.UserGetterBuilder).SetUser(&response.UserGetterSubtype{
71 | User: user,
72 | Param1: "sub_param1",
73 | Param2: 100,
74 | }).SetParam1("param1").Build(ctx)
75 | if err != nil {
76 | return err
77 | }
78 | if err := tx.Commit(); err != nil {
79 | return err
80 | }
81 | if err := c.JSON(http.StatusOK, response); err != nil {
82 | return err
83 | }
84 | return nil
85 | }
86 | ```
87 |
88 | ```bash
89 | $ curl localhost:1323/users/1 | jq '.'
90 | ```
91 |
92 | ```json
93 | {
94 | "user": {
95 | "name": "john",
96 | "userFields": [
97 | {
98 | "fieldId": 1,
99 | "field": {
100 | "name": "fieldA"
101 | }
102 | }
103 | ],
104 | "param1": "sub_param1",
105 | "param2": 100
106 | },
107 | "param1": "param1"
108 | }
109 | ```
110 |
--------------------------------------------------------------------------------
/_example/03_api/config/api/user.yml:
--------------------------------------------------------------------------------
1 | - name: user_getter
2 | desc: return user status
3 | uri: /users/{userId}
4 | method: get
5 | request:
6 | parameters:
7 | - name: user_id
8 | type: uint64
9 | in: path
10 | required: true
11 | - name: session
12 | type: string
13 | in: header
14 | response:
15 | subtypes:
16 | - name: user_getter_subtype
17 | members:
18 | - name: user
19 | type: user
20 | render:
21 | inline: true
22 | - name: param1
23 | type: string
24 | - name: param2
25 | type: int
26 | include:
27 | - name: user
28 | only:
29 | - name
30 | - param1
31 | - param2
32 | include:
33 | - name: user_fields
34 | only:
35 | - field_id
36 | include:
37 | - name: field
38 | only:
39 | - name
40 | type:
41 | members:
42 | - name: users
43 | type: user
44 | has_many: true
45 | - name: sub
46 | type: user_getter_subtype
47 | include:
48 | - name: users
49 | only:
50 | - id
51 | - name
52 | include:
53 | - name: user_fields
54 | only:
55 | - field_id
56 | - name: sub
57 |
--------------------------------------------------------------------------------
/_example/03_api/config/relation/field.yml:
--------------------------------------------------------------------------------
1 | name: field
2 | index:
3 | primary_key: id
4 | unique_keys:
5 | - - name
6 | - - location_x
7 | - location_y
8 | keys:
9 | - - object_num
10 | - - difficulty
11 | - level
12 | members:
13 | - name: id
14 | type: uint64
15 | - name: name
16 | type: string
17 | - name: location_x
18 | type: int
19 | - name: location_y
20 | type: int
21 | - name: object_num
22 | type: int
23 | - name: level
24 | type: int
25 | - name: difficulty
26 | type: int
27 |
--------------------------------------------------------------------------------
/_example/03_api/config/relation/group.yml:
--------------------------------------------------------------------------------
1 | name: group
2 | index:
3 | primary_key: id
4 | members:
5 | - name: id
6 | type: uint64
7 | - name: name
8 | type: string
9 |
--------------------------------------------------------------------------------
/_example/03_api/config/relation/skill.yml:
--------------------------------------------------------------------------------
1 | name: skill
2 | index:
3 | primary_key: id
4 | members:
5 | - name: id
6 | type: uint64
7 | - name: skill_effect
8 | type: string
9 |
--------------------------------------------------------------------------------
/_example/03_api/config/relation/user.yml:
--------------------------------------------------------------------------------
1 | name: user
2 | members:
3 | - name: id
4 | type: uint64
5 | - name: name
6 | type: string
7 | - name: sex
8 | type: string
9 | - name: age
10 | type: int
11 | - name: skill_id
12 | type: uint64
13 | - name: skill_rank
14 | type: int
15 | - name: group_id
16 | type: uint64
17 | - name: world_id
18 | type: uint64
19 | - name: field_id
20 | type: uint64
21 | - name: user_fields
22 | has_many: true
23 | extend: true
24 | relation:
25 | to: user_field
26 | internal: id
27 | external: user_id
28 | - name: skill
29 | extend: true
30 | relation:
31 | to: skill
32 | internal: skill_id
33 | external: id
34 | render:
35 | inline: true
36 | - name: group
37 | extend: true
38 | relation:
39 | to: group
40 | custom: true
41 | render:
42 | json: group
43 | - name: world
44 | extend: true
45 | relation:
46 | to: world
47 | internal: world_id
48 | external: id
49 | render: false
50 | index:
51 | primary_key: id
52 | unique_keys:
53 | - - name
54 | - - skill_id
55 | - skill_rank
56 | keys:
57 | - - group_id
58 | - - world_id
59 | - field_id
60 |
--------------------------------------------------------------------------------
/_example/03_api/config/relation/user_field.yml:
--------------------------------------------------------------------------------
1 | name: user_field
2 | index:
3 | primary_key: id
4 | unique_keys:
5 | - - user_id
6 | - field_id
7 | members:
8 | - name: id
9 | type: uint64
10 | - name: user_id
11 | type: uint64
12 | - name: field_id
13 | type: uint64
14 | - name: field
15 | extend: true
16 | relation:
17 | to: field
18 | internal: field_id
19 | external: id
20 |
--------------------------------------------------------------------------------
/_example/03_api/config/relation/world.yml:
--------------------------------------------------------------------------------
1 | name: world
2 | index:
3 | primary_key: id
4 | members:
5 | - name: id
6 | type: uint64
7 | - name: name
8 | type: string
9 |
--------------------------------------------------------------------------------
/_example/03_api/docs/index.md:
--------------------------------------------------------------------------------
1 | ## The table of contents
2 |
3 | ### Endpoints
4 | - get /users/{userId}
5 |
6 |
--------------------------------------------------------------------------------
/_example/03_api/entity/field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type Field struct {
6 | ID uint64 `json:"id"`
7 | Name string `json:"name"`
8 | LocationX int `json:"locationX"`
9 | LocationY int `json:"locationY"`
10 | ObjectNum int `json:"objectNum"`
11 | Level int `json:"level"`
12 | Difficulty int `json:"difficulty"`
13 | }
14 |
15 | type Fields []*Field
16 |
17 | func (e Fields) IDs() []uint64 {
18 | values := make([]uint64, 0, len(e))
19 | for _, value := range e {
20 | values = append(values, value.ID)
21 | }
22 | return values
23 | }
24 |
25 | func (e Fields) Names() []string {
26 | values := make([]string, 0, len(e))
27 | for _, value := range e {
28 | values = append(values, value.Name)
29 | }
30 | return values
31 | }
32 |
33 | func (e Fields) LocationXes() []int {
34 | values := make([]int, 0, len(e))
35 | for _, value := range e {
36 | values = append(values, value.LocationX)
37 | }
38 | return values
39 | }
40 |
41 | func (e Fields) LocationIes() []int {
42 | values := make([]int, 0, len(e))
43 | for _, value := range e {
44 | values = append(values, value.LocationY)
45 | }
46 | return values
47 | }
48 |
49 | func (e Fields) ObjectNums() []int {
50 | values := make([]int, 0, len(e))
51 | for _, value := range e {
52 | values = append(values, value.ObjectNum)
53 | }
54 | return values
55 | }
56 |
57 | func (e Fields) Levels() []int {
58 | values := make([]int, 0, len(e))
59 | for _, value := range e {
60 | values = append(values, value.Level)
61 | }
62 | return values
63 | }
64 |
65 | func (e Fields) Difficulties() []int {
66 | values := make([]int, 0, len(e))
67 | for _, value := range e {
68 | values = append(values, value.Difficulty)
69 | }
70 | return values
71 | }
72 |
--------------------------------------------------------------------------------
/_example/03_api/entity/group.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type Group struct {
6 | ID uint64 `json:"id"`
7 | Name string `json:"name"`
8 | }
9 |
10 | type Groups []*Group
11 |
12 | func (e Groups) IDs() []uint64 {
13 | values := make([]uint64, 0, len(e))
14 | for _, value := range e {
15 | values = append(values, value.ID)
16 | }
17 | return values
18 | }
19 |
20 | func (e Groups) Names() []string {
21 | values := make([]string, 0, len(e))
22 | for _, value := range e {
23 | values = append(values, value.Name)
24 | }
25 | return values
26 | }
27 |
--------------------------------------------------------------------------------
/_example/03_api/entity/skill.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type Skill struct {
6 | ID uint64 `json:"id"`
7 | SkillEffect string `json:"skillEffect"`
8 | }
9 |
10 | type Skills []*Skill
11 |
12 | func (e Skills) IDs() []uint64 {
13 | values := make([]uint64, 0, len(e))
14 | for _, value := range e {
15 | values = append(values, value.ID)
16 | }
17 | return values
18 | }
19 |
20 | func (e Skills) SkillEffects() []string {
21 | values := make([]string, 0, len(e))
22 | for _, value := range e {
23 | values = append(values, value.SkillEffect)
24 | }
25 | return values
26 | }
27 |
--------------------------------------------------------------------------------
/_example/03_api/entity/user.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type User struct {
6 | ID uint64 `json:"id"`
7 | Name string `json:"name"`
8 | Sex string `json:"sex"`
9 | Age int `json:"age"`
10 | SkillID uint64 `json:"skillID"`
11 | SkillRank int `json:"skillRank"`
12 | GroupID uint64 `json:"groupID"`
13 | WorldID uint64 `json:"worldID"`
14 | FieldID uint64 `json:"fieldID"`
15 | }
16 |
17 | type Users []*User
18 |
19 | func (e Users) IDs() []uint64 {
20 | values := make([]uint64, 0, len(e))
21 | for _, value := range e {
22 | values = append(values, value.ID)
23 | }
24 | return values
25 | }
26 |
27 | func (e Users) Names() []string {
28 | values := make([]string, 0, len(e))
29 | for _, value := range e {
30 | values = append(values, value.Name)
31 | }
32 | return values
33 | }
34 |
35 | func (e Users) Sexes() []string {
36 | values := make([]string, 0, len(e))
37 | for _, value := range e {
38 | values = append(values, value.Sex)
39 | }
40 | return values
41 | }
42 |
43 | func (e Users) Ages() []int {
44 | values := make([]int, 0, len(e))
45 | for _, value := range e {
46 | values = append(values, value.Age)
47 | }
48 | return values
49 | }
50 |
51 | func (e Users) SkillIDs() []uint64 {
52 | values := make([]uint64, 0, len(e))
53 | for _, value := range e {
54 | values = append(values, value.SkillID)
55 | }
56 | return values
57 | }
58 |
59 | func (e Users) SkillRanks() []int {
60 | values := make([]int, 0, len(e))
61 | for _, value := range e {
62 | values = append(values, value.SkillRank)
63 | }
64 | return values
65 | }
66 |
67 | func (e Users) GroupIDs() []uint64 {
68 | values := make([]uint64, 0, len(e))
69 | for _, value := range e {
70 | values = append(values, value.GroupID)
71 | }
72 | return values
73 | }
74 |
75 | func (e Users) WorldIDs() []uint64 {
76 | values := make([]uint64, 0, len(e))
77 | for _, value := range e {
78 | values = append(values, value.WorldID)
79 | }
80 | return values
81 | }
82 |
83 | func (e Users) FieldIDs() []uint64 {
84 | values := make([]uint64, 0, len(e))
85 | for _, value := range e {
86 | values = append(values, value.FieldID)
87 | }
88 | return values
89 | }
90 |
--------------------------------------------------------------------------------
/_example/03_api/entity/user_field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type UserField struct {
6 | ID uint64 `json:"id"`
7 | UserID uint64 `json:"userID"`
8 | FieldID uint64 `json:"fieldID"`
9 | }
10 |
11 | type UserFields []*UserField
12 |
13 | func (e UserFields) IDs() []uint64 {
14 | values := make([]uint64, 0, len(e))
15 | for _, value := range e {
16 | values = append(values, value.ID)
17 | }
18 | return values
19 | }
20 |
21 | func (e UserFields) UserIDs() []uint64 {
22 | values := make([]uint64, 0, len(e))
23 | for _, value := range e {
24 | values = append(values, value.UserID)
25 | }
26 | return values
27 | }
28 |
29 | func (e UserFields) FieldIDs() []uint64 {
30 | values := make([]uint64, 0, len(e))
31 | for _, value := range e {
32 | values = append(values, value.FieldID)
33 | }
34 | return values
35 | }
36 |
--------------------------------------------------------------------------------
/_example/03_api/entity/world.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type World struct {
6 | ID uint64 `json:"id"`
7 | Name string `json:"name"`
8 | }
9 |
10 | type Worlds []*World
11 |
12 | func (e Worlds) IDs() []uint64 {
13 | values := make([]uint64, 0, len(e))
14 | for _, value := range e {
15 | values = append(values, value.ID)
16 | }
17 | return values
18 | }
19 |
20 | func (e Worlds) Names() []string {
21 | values := make([]string, 0, len(e))
22 | for _, value := range e {
23 | values = append(values, value.Name)
24 | }
25 | return values
26 | }
27 |
--------------------------------------------------------------------------------
/_example/03_api/go.mod:
--------------------------------------------------------------------------------
1 | module api
2 |
3 | go 1.12
4 |
5 | require (
6 | github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
7 | github.com/go-sql-driver/mysql v1.4.1
8 | github.com/labstack/echo v3.3.10+incompatible
9 | github.com/labstack/gommon v0.3.0 // indirect
10 | golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 // indirect
11 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7
12 | google.golang.org/appengine v1.6.2 // indirect
13 | )
14 |
--------------------------------------------------------------------------------
/_example/03_api/mock/model/factory/field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "api/entity"
7 | "api/model"
8 | )
9 |
10 | func DefaultField() *model.Field {
11 | value := &model.Field{Field: &entity.Field{
12 | Difficulty: 0,
13 | ID: 0,
14 | Level: 0,
15 | LocationX: 0,
16 | LocationY: 0,
17 | Name: "",
18 | ObjectNum: 0,
19 | }}
20 | return value
21 | }
22 |
23 | func DefaultFields() *model.Fields {
24 | values := &model.Fields{}
25 | {
26 | value := &model.Field{Field: &entity.Field{
27 | Difficulty: 0,
28 | ID: 0,
29 | Level: 0,
30 | LocationX: 0,
31 | LocationY: 0,
32 | Name: "",
33 | ObjectNum: 0,
34 | }}
35 | values.Add(value)
36 | }
37 | return values
38 | }
39 |
--------------------------------------------------------------------------------
/_example/03_api/mock/model/factory/group.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "api/entity"
7 | "api/model"
8 | )
9 |
10 | func DefaultGroup() *model.Group {
11 | value := &model.Group{Group: &entity.Group{
12 | ID: 0,
13 | Name: "",
14 | }}
15 | return value
16 | }
17 |
18 | func DefaultGroups() *model.Groups {
19 | values := &model.Groups{}
20 | {
21 | value := &model.Group{Group: &entity.Group{
22 | ID: 0,
23 | Name: "",
24 | }}
25 | values.Add(value)
26 | }
27 | return values
28 | }
29 |
--------------------------------------------------------------------------------
/_example/03_api/mock/model/factory/skill.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "api/entity"
7 | "api/model"
8 | )
9 |
10 | func DefaultSkill() *model.Skill {
11 | value := &model.Skill{Skill: &entity.Skill{
12 | ID: 0,
13 | SkillEffect: "",
14 | }}
15 | return value
16 | }
17 |
18 | func DefaultSkills() *model.Skills {
19 | values := &model.Skills{}
20 | {
21 | value := &model.Skill{Skill: &entity.Skill{
22 | ID: 0,
23 | SkillEffect: "",
24 | }}
25 | values.Add(value)
26 | }
27 | return values
28 | }
29 |
--------------------------------------------------------------------------------
/_example/03_api/mock/model/factory/user.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "api/entity"
7 | "api/model"
8 | "context"
9 | )
10 |
11 | func DefaultUser() *model.User {
12 | userFields := DefaultUserFields()
13 | skill := DefaultSkill()
14 | world := DefaultWorld()
15 | value := &model.User{User: &entity.User{
16 | Age: 0,
17 | FieldID: 0,
18 | GroupID: 0,
19 | ID: 0,
20 | Name: "",
21 | Sex: "",
22 | SkillID: 0,
23 | SkillRank: 0,
24 | WorldID: 0,
25 | }}
26 | value.UserFields = func(context.Context) (*model.UserFields, error) {
27 | return userFields, nil
28 | }
29 | value.Skill = func(context.Context) (*model.Skill, error) {
30 | return skill, nil
31 | }
32 | value.World = func(context.Context) (*model.World, error) {
33 | return world, nil
34 | }
35 | return value
36 | }
37 |
38 | func DefaultUsers() *model.Users {
39 | values := &model.Users{}
40 | {
41 | userFields := DefaultUserFields()
42 | skill := DefaultSkill()
43 | world := DefaultWorld()
44 | value := &model.User{User: &entity.User{
45 | Age: 0,
46 | FieldID: 0,
47 | GroupID: 0,
48 | ID: 0,
49 | Name: "",
50 | Sex: "",
51 | SkillID: 0,
52 | SkillRank: 0,
53 | WorldID: 0,
54 | }}
55 | value.UserFields = func(context.Context) (*model.UserFields, error) {
56 | return userFields, nil
57 | }
58 | value.Skill = func(context.Context) (*model.Skill, error) {
59 | return skill, nil
60 | }
61 | value.World = func(context.Context) (*model.World, error) {
62 | return world, nil
63 | }
64 | values.Add(value)
65 | }
66 | return values
67 | }
68 |
--------------------------------------------------------------------------------
/_example/03_api/mock/model/factory/user_field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "api/entity"
7 | "api/model"
8 | "context"
9 | )
10 |
11 | func DefaultUserField() *model.UserField {
12 | field := DefaultField()
13 | value := &model.UserField{UserField: &entity.UserField{
14 | FieldID: 0,
15 | ID: 0,
16 | UserID: 0,
17 | }}
18 | value.Field = func(context.Context) (*model.Field, error) {
19 | return field, nil
20 | }
21 | return value
22 | }
23 |
24 | func DefaultUserFields() *model.UserFields {
25 | values := &model.UserFields{}
26 | {
27 | field := DefaultField()
28 | value := &model.UserField{UserField: &entity.UserField{
29 | FieldID: 0,
30 | ID: 0,
31 | UserID: 0,
32 | }}
33 | value.Field = func(context.Context) (*model.Field, error) {
34 | return field, nil
35 | }
36 | values.Add(value)
37 | }
38 | return values
39 | }
40 |
--------------------------------------------------------------------------------
/_example/03_api/mock/model/factory/world.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "api/entity"
7 | "api/model"
8 | )
9 |
10 | func DefaultWorld() *model.World {
11 | value := &model.World{World: &entity.World{
12 | ID: 0,
13 | Name: "",
14 | }}
15 | return value
16 | }
17 |
18 | func DefaultWorlds() *model.Worlds {
19 | values := &model.Worlds{}
20 | {
21 | value := &model.World{World: &entity.World{
22 | ID: 0,
23 | Name: "",
24 | }}
25 | values.Add(value)
26 | }
27 | return values
28 | }
29 |
--------------------------------------------------------------------------------
/_example/03_api/mock/model/field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "api/entity"
7 | "api/model"
8 | )
9 |
10 | func DefaultField() *model.Field {
11 | value := model.NewField(&entity.Field{
12 | Difficulty: uint64(0x0),
13 | ID: uint64(0x0),
14 | Level: uint64(0x0),
15 | LocationX: uint64(0x0),
16 | LocationY: uint64(0x0),
17 | Name: "",
18 | ObjectNum: uint64(0x0),
19 | }, nil)
20 | return value
21 | }
22 |
23 | func DefaultsField() *model.Fields {
24 | values := model.NewFields(entity.Fields{})
25 | values.Add(DefaultField())
26 | return values
27 | }
28 |
--------------------------------------------------------------------------------
/_example/03_api/mock/model/group.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "api/entity"
7 | "api/model"
8 | )
9 |
10 | func DefaultGroup() *model.Group {
11 | value := model.NewGroup(&entity.Group{
12 | ID: uint64(0x0),
13 | Name: "",
14 | }, nil)
15 | return value
16 | }
17 |
18 | func DefaultsGroup() *model.Groups {
19 | values := model.NewGroups(entity.Groups{})
20 | values.Add(DefaultGroup())
21 | return values
22 | }
23 |
--------------------------------------------------------------------------------
/_example/03_api/mock/model/skill.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "api/entity"
7 | "api/model"
8 | )
9 |
10 | func DefaultSkill() *model.Skill {
11 | value := model.NewSkill(&entity.Skill{
12 | ID: uint64(0x0),
13 | SkillEffect: "",
14 | }, nil)
15 | return value
16 | }
17 |
18 | func DefaultsSkill() *model.Skills {
19 | values := model.NewSkills(entity.Skills{})
20 | values.Add(DefaultSkill())
21 | return values
22 | }
23 |
--------------------------------------------------------------------------------
/_example/03_api/mock/model/user.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "api/entity"
7 | "api/model"
8 | "context"
9 | )
10 |
11 | func DefaultUser() *model.User {
12 | value := model.NewUser(&entity.User{
13 | Age: uint64(0x0),
14 | FieldID: uint64(0x0),
15 | GroupID: uint64(0x0),
16 | ID: uint64(0x0),
17 | Name: "",
18 | Sex: "",
19 | SkillID: uint64(0x0),
20 | SkillRank: uint64(0x0),
21 | WorldID: uint64(0x0),
22 | }, nil)
23 | value.UserFields = func(context.Context) (*model.UserFields, error) {
24 | return DefaultUserField(), nil
25 | }
26 | value.Skill = func(context.Context) (*model.Skill, error) {
27 | return DefaultSkill(), nil
28 | }
29 | value.World = func(context.Context) (*model.World, error) {
30 | return DefaultWorld(), nil
31 | }
32 | return value
33 | }
34 |
35 | func DefaultsUser() *model.Users {
36 | values := model.NewUsers(entity.Users{})
37 | values.Add(DefaultUser())
38 | return values
39 | }
40 |
--------------------------------------------------------------------------------
/_example/03_api/mock/model/user_field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "api/entity"
7 | "api/model"
8 | "context"
9 | )
10 |
11 | func DefaultUserField() *model.UserField {
12 | value := model.NewUserField(&entity.UserField{
13 | FieldID: uint64(0x0),
14 | ID: uint64(0x0),
15 | UserID: uint64(0x0),
16 | }, nil)
17 | value.Field = func(context.Context) (*model.Field, error) {
18 | return DefaultField(), nil
19 | }
20 | return value
21 | }
22 |
23 | func DefaultsUserField() *model.UserFields {
24 | values := model.NewUserFields(entity.UserFields{})
25 | values.Add(DefaultUserField())
26 | return values
27 | }
28 |
--------------------------------------------------------------------------------
/_example/03_api/mock/model/world.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "api/entity"
7 | "api/model"
8 | )
9 |
10 | func DefaultWorld() *model.World {
11 | value := model.NewWorld(&entity.World{
12 | ID: uint64(0x0),
13 | Name: "",
14 | }, nil)
15 | return value
16 | }
17 |
18 | func DefaultsWorld() *model.Worlds {
19 | values := model.NewWorlds(entity.Worlds{})
20 | values.Add(DefaultWorld())
21 | return values
22 | }
23 |
--------------------------------------------------------------------------------
/_example/03_api/model/model.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "api/entity"
7 | "context"
8 | )
9 |
10 | type ModelConverter interface {
11 | ToField(*entity.Field) *Field
12 | ToGroup(*entity.Group) *Group
13 | ToSkill(*entity.Skill) *Skill
14 | ToUser(*entity.User) *User
15 | ToUserField(*entity.UserField) *UserField
16 | ToWorld(*entity.World) *World
17 | }
18 |
19 | type BeforeRenderer interface {
20 | BeforeRender(context.Context) error
21 | }
22 |
23 | type RenderOption struct {
24 | Name string
25 | IsIncludeAll bool
26 | onlyNames map[string]struct{}
27 | exceptNames map[string]struct{}
28 | includes map[string]*RenderOption
29 | }
30 |
31 | func (ro *RenderOption) Exists(name string) bool {
32 | if len(ro.onlyNames) > 0 {
33 | if _, exists := ro.onlyNames[name]; exists {
34 | return true
35 | }
36 | return false
37 | }
38 | if len(ro.exceptNames) > 0 {
39 | if _, exists := ro.exceptNames[name]; exists {
40 | return false
41 | }
42 | return true
43 | }
44 | return true
45 | }
46 |
47 | func (ro *RenderOption) IncludeOption(name string) *RenderOption {
48 | if ro.Name == name {
49 | return ro
50 | }
51 | return ro.includes[name]
52 | }
53 |
54 | type RenderOptionBuilder struct {
55 | onlyNames map[string]struct{}
56 | exceptNames map[string]struct{}
57 | includes map[string]*RenderOption
58 | isIncludeAll bool
59 | }
60 |
61 | func NewRenderOptionBuilder() *RenderOptionBuilder {
62 | return &RenderOptionBuilder{
63 | exceptNames: map[string]struct{}{},
64 | includes: map[string]*RenderOption{},
65 | onlyNames: map[string]struct{}{},
66 | }
67 | }
68 |
69 | func (b *RenderOptionBuilder) Only(names ...string) *RenderOptionBuilder {
70 | for _, name := range names {
71 | b.onlyNames[name] = struct{}{}
72 | }
73 | return b
74 | }
75 |
76 | func (b *RenderOptionBuilder) Except(names ...string) *RenderOptionBuilder {
77 | for _, name := range names {
78 | b.exceptNames[name] = struct{}{}
79 | }
80 | return b
81 | }
82 |
83 | func (b *RenderOptionBuilder) Include(name string) *RenderOptionBuilder {
84 | b.includes[name] = &RenderOption{Name: name}
85 | return b
86 | }
87 |
88 | func (b *RenderOptionBuilder) IncludeWithCallback(name string, callback func(*RenderOptionBuilder)) *RenderOptionBuilder {
89 | builder := NewRenderOptionBuilder()
90 | callback(builder)
91 | opt := builder.Build()
92 | opt.Name = name
93 | b.includes[name] = opt
94 | return b
95 | }
96 |
97 | func (b *RenderOptionBuilder) IncludeAll() *RenderOptionBuilder {
98 | b.isIncludeAll = true
99 | return b
100 | }
101 |
102 | func (b *RenderOptionBuilder) Build() *RenderOption {
103 | return &RenderOption{
104 | IsIncludeAll: b.isIncludeAll,
105 | exceptNames: b.exceptNames,
106 | includes: b.includes,
107 | onlyNames: b.onlyNames,
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/_example/03_api/model/user_api.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import "context"
4 |
5 | func (m *User) Group(ctx context.Context) (*Group, error) {
6 | return nil, nil
7 | }
8 |
--------------------------------------------------------------------------------
/_example/03_api/request/user_getter.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package request
4 |
5 | import (
6 | "golang.org/x/xerrors"
7 | "net/http"
8 | )
9 |
10 | type UserGetter struct {
11 | UserID uint64
12 | Session string
13 | }
14 |
15 | type UserGetterBuilder struct {
16 | userID *uint64
17 | }
18 |
19 | func (b *UserGetterBuilder) SetUserID(a uint64) *UserGetterBuilder {
20 | b.userID = &a
21 | return b
22 | }
23 |
24 | func (b *UserGetterBuilder) Build(r *http.Request) (*UserGetter, error) {
25 | req := &UserGetter{}
26 | if b.userID == nil {
27 | return nil, xerrors.New("userID is required. but doesn't assigned to builder")
28 | }
29 | if b.userID != nil {
30 | req.UserID = *b.userID
31 | }
32 | req.Session = r.Header.Get("X-Session")
33 | return req, nil
34 | }
35 |
--------------------------------------------------------------------------------
/_example/03_api/schema/fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | `location_x` int NOT NULL,
5 | `location_y` int NOT NULL,
6 | `object_num` int NOT NULL,
7 | `level` int NOT NULL,
8 | `difficulty` int NOT NULL,
9 | PRIMARY KEY (`id`),
10 | UNIQUE KEY `uq_fields_01` (`name`),
11 | UNIQUE KEY `uq_fields_02` (`location_x`, `location_y`),
12 | KEY `idx_fields_03` (`object_num`),
13 | KEY `idx_fields_04` (`difficulty`, `level`)
14 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
15 |
16 |
--------------------------------------------------------------------------------
/_example/03_api/schema/groups.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `groups` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | PRIMARY KEY (`id`)
5 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 |
7 |
--------------------------------------------------------------------------------
/_example/03_api/schema/skills.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `skills` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `skill_effect` varchar(30) DEFAULT NULL,
4 | PRIMARY KEY (`id`)
5 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 |
--------------------------------------------------------------------------------
/_example/03_api/schema/user_fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `user_fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `user_id` bigint(20) unsigned NOT NULL,
4 | `field_id` bigint(20) unsigned NOT NULL,
5 | PRIMARY KEY (`id`),
6 | UNIQUE KEY `uq_fields_01` (`user_id`, `field_id`)
7 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
8 |
9 |
--------------------------------------------------------------------------------
/_example/03_api/schema/users.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `users` (
2 | `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
3 | `name` varchar(30) DEFAULT NULL,
4 | `sex` enum('man','woman') NOT NULL,
5 | `age` int NOT NULL,
6 | `skill_id` bigint(20) unsigned NOT NULL,
7 | `skill_rank` int NOT NULL,
8 | `group_id` bigint(20) unsigned NOT NULL,
9 | `world_id` bigint(20) unsigned NOT NULL,
10 | `field_id` bigint(20) unsigned NOT NULL,
11 | PRIMARY KEY (`id`),
12 | UNIQUE KEY `uq_users_01` (`name`),
13 | UNIQUE KEY `uq_users_02` (`skill_id`, `skill_rank`),
14 | KEY `idx_users_03` (`group_id`),
15 | KEY `idx_users_04` (`world_id`, `field_id`)
16 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
17 |
18 |
--------------------------------------------------------------------------------
/_example/03_api/schema/worlds.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `worlds` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | PRIMARY KEY (`id`)
5 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 |
7 |
--------------------------------------------------------------------------------
/_example/03_api/server.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | _ "api/db"
5 | "api/model"
6 | "api/repository"
7 | "api/request"
8 | "api/response"
9 | "context"
10 | "database/sql"
11 | "net/http"
12 | "strconv"
13 |
14 | _ "github.com/go-sql-driver/mysql"
15 | "github.com/labstack/echo"
16 | "github.com/labstack/echo/middleware"
17 | )
18 |
19 | var (
20 | db *sql.DB
21 | )
22 |
23 | func getUser(c echo.Context) error {
24 | id, _ := strconv.Atoi(c.Param("id"))
25 | req, err := new(request.UserGetterBuilder).SetUserID(uint64(id)).Build(c.Request())
26 | if err != nil {
27 | return err
28 | }
29 | tx, err := db.Begin()
30 | if err != nil {
31 | return err
32 | }
33 | ctx := context.Background()
34 | repo := repository.New(ctx, tx)
35 | user, err := repo.User().FindByID(ctx, req.UserID)
36 | if err != nil {
37 | return err
38 | }
39 | response, err := new(response.UserGetterBuilder).SetSub(&response.UserGetterSubtype{
40 | User: user,
41 | Param1: "sub_param1",
42 | Param2: 100,
43 | }).SetUsers(new(model.Users).Add(user)).Build(ctx)
44 | if err != nil {
45 | return err
46 | }
47 | if err := tx.Commit(); err != nil {
48 | return err
49 | }
50 | if err := c.JSON(http.StatusOK, response); err != nil {
51 | return err
52 | }
53 | return nil
54 | }
55 |
56 | func main() {
57 | e := echo.New()
58 |
59 | conn, err := sql.Open("mysql", "root:@tcp(localhost:3306)/eevee?parseTime=true")
60 | if err != nil {
61 | panic(err)
62 | }
63 | defer conn.Close()
64 |
65 | db = conn
66 |
67 | // Middleware
68 | e.Use(middleware.Logger())
69 | e.Use(middleware.Recover())
70 |
71 | // Routes
72 | e.GET("/users/:id", getUser)
73 |
74 | // Start server
75 | e.Logger.Fatal(e.Start(":1323"))
76 | }
77 |
--------------------------------------------------------------------------------
/_example/03_api/testdata/seeds/field.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | difficulty: 0
4 | id: 0
5 | level: 0
6 | location_x: 0
7 | location_y: 0
8 | name: ""
9 | object_num: 0
10 | collection:
11 | defaults:
12 | - *default
13 |
--------------------------------------------------------------------------------
/_example/03_api/testdata/seeds/group.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | id: 0
4 | name: ""
5 | collection:
6 | defaults:
7 | - *default
8 |
--------------------------------------------------------------------------------
/_example/03_api/testdata/seeds/skill.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | id: 0
4 | skill_effect: ""
5 | collection:
6 | defaults:
7 | - *default
8 |
--------------------------------------------------------------------------------
/_example/03_api/testdata/seeds/user.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | age: 0
4 | field_id: 0
5 | group: $default
6 | group_id: 0
7 | id: 0
8 | name: ""
9 | sex: ""
10 | skill: $default
11 | skill_id: 0
12 | skill_rank: 0
13 | user_fields: $default
14 | world: $default
15 | world_id: 0
16 | collection:
17 | defaults:
18 | - *default
19 |
--------------------------------------------------------------------------------
/_example/03_api/testdata/seeds/user_field.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | field: $default
4 | field_id: 0
5 | id: 0
6 | user_id: 0
7 | collection:
8 | defaults:
9 | - *default
10 |
--------------------------------------------------------------------------------
/_example/03_api/testdata/seeds/world.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | id: 0
4 | name: ""
5 | collection:
6 | defaults:
7 | - *default
8 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/.eevee.yml:
--------------------------------------------------------------------------------
1 | module: daoplugin
2 | class: config
3 | schema: schema
4 | dao:
5 | default: db
6 | datastore:
7 | db:
8 | before-create:
9 | - request-time
10 | before-update:
11 | - request-time
12 | constructor-declare: user-id
13 | constructor: user-id
14 | findby-declare: user-id
15 | findby: user-id
16 | updateby-declare: user-id
17 | updateby: user-id
18 | deleteby-declare: user-id
19 | deleteby: user-id
20 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/README.md:
--------------------------------------------------------------------------------
1 | # How to work example
2 |
3 | ## 1. Automatically resolve relationships between tables at render
4 |
5 | ```go
6 | func getUser(c echo.Context) error {
7 | id, _ := strconv.Atoi(c.Param("id"))
8 | tx, err := db.Begin()
9 | if err != nil {
10 | return err
11 | }
12 | ctx := context.Background()
13 | repo := repository.New(ctx, tx)
14 | user, err := repo.User().FindByID(ctx, uint64(id))
15 | if err != nil {
16 | return err
17 | }
18 | if err := c.JSON(http.StatusOK, user); err != nil {
19 | return err
20 | }
21 | if err := tx.Commit(); err != nil {
22 | return err
23 | }
24 | return nil
25 | }
26 | ```
27 |
28 | ```bash
29 | $ curl localhost:1323/users/1 | jq '.'
30 | ```
31 |
32 | ```json
33 | {
34 | "id": 1,
35 | "name": "john",
36 | "sex": "man",
37 | "age": 30,
38 | "skillId": 1,
39 | "skillRank": 10,
40 | "groupId": 1,
41 | "worldId": 1,
42 | "fieldId": 1,
43 | "userFields": [
44 | {
45 | "id": 1,
46 | "userId": 1,
47 | "fieldId": 1,
48 | "field": {
49 | "id": 1,
50 | "name": "fieldA",
51 | "locationX": 2,
52 | "locationY": 3,
53 | "objectNum": 10,
54 | "level": 20,
55 | "difficulty": 5
56 | }
57 | }
58 | ],
59 | "skillEffect": "fire",
60 | "group": null
61 | }
62 | ```
63 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/config/field.yml:
--------------------------------------------------------------------------------
1 | name: field
2 | datastore: db
3 | index:
4 | primary_key: id
5 | unique_keys:
6 | - - name
7 | - - location_x
8 | - location_y
9 | keys:
10 | - - object_num
11 | - - difficulty
12 | - level
13 | read_only: true
14 | members:
15 | - name: id
16 | type: uint64
17 | - name: name
18 | type: string
19 | - name: location_x
20 | type: int
21 | - name: location_y
22 | type: int
23 | - name: object_num
24 | type: int
25 | - name: level
26 | type: int
27 | - name: difficulty
28 | type: int
29 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/config/group.yml:
--------------------------------------------------------------------------------
1 | name: group
2 | datastore: db
3 | index:
4 | primary_key: id
5 | read_only: true
6 | members:
7 | - name: id
8 | type: uint64
9 | - name: name
10 | type: string
11 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/config/skill.yml:
--------------------------------------------------------------------------------
1 | name: skill
2 | datastore: db
3 | index:
4 | primary_key: id
5 | read_only: true
6 | members:
7 | - name: id
8 | type: uint64
9 | - name: skill_effect
10 | type: string
11 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/config/user.yml:
--------------------------------------------------------------------------------
1 | name: user
2 | datastore: db
3 | index:
4 | primary_key: id
5 | unique_keys:
6 | - - name
7 | - - skill_id
8 | - skill_rank
9 | keys:
10 | - - group_id
11 | - - world_id
12 | - field_id
13 | members:
14 | - name: id
15 | type: uint64
16 | - name: name
17 | type: string
18 | example: john
19 | - name: sex
20 | type: string
21 | - name: age
22 | type: int
23 | - name: skill_id
24 | type: uint64
25 | - name: skill_rank
26 | type: int
27 | - name: group_id
28 | type: uint64
29 | - name: world_id
30 | type: uint64
31 | - name: field_id
32 | type: uint64
33 | - name: created_at
34 | type:
35 | package_name: time
36 | name: Time
37 | - name: updated_at
38 | type:
39 | package_name: time
40 | name: Time
41 | - name: user_fields
42 | extend: true
43 | has_many: true
44 | relation:
45 | to: user_field
46 | internal: id
47 | external: user_id
48 | - name: skill
49 | extend: true
50 | render:
51 | inline: true
52 | relation:
53 | to: skill
54 | internal: skill_id
55 | external: id
56 | - name: group
57 | extend: true
58 | render:
59 | json: group
60 | relation:
61 | custom: true
62 | to: group
63 | - name: world
64 | extend: true
65 | render: false
66 | relation:
67 | to: world
68 | internal: world_id
69 | external: id
70 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/config/user_field.yml:
--------------------------------------------------------------------------------
1 | name: user_field
2 | datastore: db
3 | index:
4 | primary_key: id
5 | unique_keys:
6 | - - user_id
7 | - field_id
8 | members:
9 | - name: id
10 | type: uint64
11 | - name: user_id
12 | type: uint64
13 | - name: field_id
14 | type: uint64
15 | - name: created_at
16 | type:
17 | package_name: time
18 | name: Time
19 | - name: updated_at
20 | type:
21 | package_name: time
22 | name: Time
23 | - name: field
24 | extend: true
25 | relation:
26 | to: field
27 | internal: field_id
28 | external: id
29 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/config/world.yml:
--------------------------------------------------------------------------------
1 | name: world
2 | datastore: db
3 | index:
4 | primary_key: id
5 | read_only: true
6 | members:
7 | - name: id
8 | type: uint64
9 | - name: name
10 | type: string
11 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/entity/field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type Field struct {
6 | ID uint64 `json:"id"`
7 | Name string `json:"name"`
8 | LocationX int `json:"locationX"`
9 | LocationY int `json:"locationY"`
10 | ObjectNum int `json:"objectNum"`
11 | Level int `json:"level"`
12 | Difficulty int `json:"difficulty"`
13 | }
14 |
15 | type Fields []*Field
16 |
17 | func (e Fields) IDs() []uint64 {
18 | values := make([]uint64, 0, len(e))
19 | for _, value := range e {
20 | values = append(values, value.ID)
21 | }
22 | return values
23 | }
24 |
25 | func (e Fields) Names() []string {
26 | values := make([]string, 0, len(e))
27 | for _, value := range e {
28 | values = append(values, value.Name)
29 | }
30 | return values
31 | }
32 |
33 | func (e Fields) LocationXes() []int {
34 | values := make([]int, 0, len(e))
35 | for _, value := range e {
36 | values = append(values, value.LocationX)
37 | }
38 | return values
39 | }
40 |
41 | func (e Fields) LocationIes() []int {
42 | values := make([]int, 0, len(e))
43 | for _, value := range e {
44 | values = append(values, value.LocationY)
45 | }
46 | return values
47 | }
48 |
49 | func (e Fields) ObjectNums() []int {
50 | values := make([]int, 0, len(e))
51 | for _, value := range e {
52 | values = append(values, value.ObjectNum)
53 | }
54 | return values
55 | }
56 |
57 | func (e Fields) Levels() []int {
58 | values := make([]int, 0, len(e))
59 | for _, value := range e {
60 | values = append(values, value.Level)
61 | }
62 | return values
63 | }
64 |
65 | func (e Fields) Difficulties() []int {
66 | values := make([]int, 0, len(e))
67 | for _, value := range e {
68 | values = append(values, value.Difficulty)
69 | }
70 | return values
71 | }
72 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/entity/group.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type Group struct {
6 | ID uint64 `json:"id"`
7 | Name string `json:"name"`
8 | }
9 |
10 | type Groups []*Group
11 |
12 | func (e Groups) IDs() []uint64 {
13 | values := make([]uint64, 0, len(e))
14 | for _, value := range e {
15 | values = append(values, value.ID)
16 | }
17 | return values
18 | }
19 |
20 | func (e Groups) Names() []string {
21 | values := make([]string, 0, len(e))
22 | for _, value := range e {
23 | values = append(values, value.Name)
24 | }
25 | return values
26 | }
27 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/entity/skill.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type Skill struct {
6 | ID uint64 `json:"id"`
7 | SkillEffect string `json:"skillEffect"`
8 | }
9 |
10 | type Skills []*Skill
11 |
12 | func (e Skills) IDs() []uint64 {
13 | values := make([]uint64, 0, len(e))
14 | for _, value := range e {
15 | values = append(values, value.ID)
16 | }
17 | return values
18 | }
19 |
20 | func (e Skills) SkillEffects() []string {
21 | values := make([]string, 0, len(e))
22 | for _, value := range e {
23 | values = append(values, value.SkillEffect)
24 | }
25 | return values
26 | }
27 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/entity/user.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | import "time"
6 |
7 | type User struct {
8 | ID uint64 `json:"id"`
9 | Name string `json:"name"`
10 | Sex string `json:"sex"`
11 | Age int `json:"age"`
12 | SkillID uint64 `json:"skillID"`
13 | SkillRank int `json:"skillRank"`
14 | GroupID uint64 `json:"groupID"`
15 | WorldID uint64 `json:"worldID"`
16 | FieldID uint64 `json:"fieldID"`
17 | CreatedAt time.Time `json:"createdAt"`
18 | UpdatedAt time.Time `json:"updatedAt"`
19 | }
20 |
21 | type Users []*User
22 |
23 | func (e Users) IDs() []uint64 {
24 | values := make([]uint64, 0, len(e))
25 | for _, value := range e {
26 | values = append(values, value.ID)
27 | }
28 | return values
29 | }
30 |
31 | func (e Users) Names() []string {
32 | values := make([]string, 0, len(e))
33 | for _, value := range e {
34 | values = append(values, value.Name)
35 | }
36 | return values
37 | }
38 |
39 | func (e Users) Sexes() []string {
40 | values := make([]string, 0, len(e))
41 | for _, value := range e {
42 | values = append(values, value.Sex)
43 | }
44 | return values
45 | }
46 |
47 | func (e Users) Ages() []int {
48 | values := make([]int, 0, len(e))
49 | for _, value := range e {
50 | values = append(values, value.Age)
51 | }
52 | return values
53 | }
54 |
55 | func (e Users) SkillIDs() []uint64 {
56 | values := make([]uint64, 0, len(e))
57 | for _, value := range e {
58 | values = append(values, value.SkillID)
59 | }
60 | return values
61 | }
62 |
63 | func (e Users) SkillRanks() []int {
64 | values := make([]int, 0, len(e))
65 | for _, value := range e {
66 | values = append(values, value.SkillRank)
67 | }
68 | return values
69 | }
70 |
71 | func (e Users) GroupIDs() []uint64 {
72 | values := make([]uint64, 0, len(e))
73 | for _, value := range e {
74 | values = append(values, value.GroupID)
75 | }
76 | return values
77 | }
78 |
79 | func (e Users) WorldIDs() []uint64 {
80 | values := make([]uint64, 0, len(e))
81 | for _, value := range e {
82 | values = append(values, value.WorldID)
83 | }
84 | return values
85 | }
86 |
87 | func (e Users) FieldIDs() []uint64 {
88 | values := make([]uint64, 0, len(e))
89 | for _, value := range e {
90 | values = append(values, value.FieldID)
91 | }
92 | return values
93 | }
94 |
95 | func (e Users) CreatedAts() []time.Time {
96 | values := make([]time.Time, 0, len(e))
97 | for _, value := range e {
98 | values = append(values, value.CreatedAt)
99 | }
100 | return values
101 | }
102 |
103 | func (e Users) UpdatedAts() []time.Time {
104 | values := make([]time.Time, 0, len(e))
105 | for _, value := range e {
106 | values = append(values, value.UpdatedAt)
107 | }
108 | return values
109 | }
110 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/entity/user_field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | import "time"
6 |
7 | type UserField struct {
8 | ID uint64 `json:"id"`
9 | UserID uint64 `json:"userID"`
10 | FieldID uint64 `json:"fieldID"`
11 | CreatedAt time.Time `json:"createdAt"`
12 | UpdatedAt time.Time `json:"updatedAt"`
13 | }
14 |
15 | type UserFields []*UserField
16 |
17 | func (e UserFields) IDs() []uint64 {
18 | values := make([]uint64, 0, len(e))
19 | for _, value := range e {
20 | values = append(values, value.ID)
21 | }
22 | return values
23 | }
24 |
25 | func (e UserFields) UserIDs() []uint64 {
26 | values := make([]uint64, 0, len(e))
27 | for _, value := range e {
28 | values = append(values, value.UserID)
29 | }
30 | return values
31 | }
32 |
33 | func (e UserFields) FieldIDs() []uint64 {
34 | values := make([]uint64, 0, len(e))
35 | for _, value := range e {
36 | values = append(values, value.FieldID)
37 | }
38 | return values
39 | }
40 |
41 | func (e UserFields) CreatedAts() []time.Time {
42 | values := make([]time.Time, 0, len(e))
43 | for _, value := range e {
44 | values = append(values, value.CreatedAt)
45 | }
46 | return values
47 | }
48 |
49 | func (e UserFields) UpdatedAts() []time.Time {
50 | values := make([]time.Time, 0, len(e))
51 | for _, value := range e {
52 | values = append(values, value.UpdatedAt)
53 | }
54 | return values
55 | }
56 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/entity/world.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type World struct {
6 | ID uint64 `json:"id"`
7 | Name string `json:"name"`
8 | }
9 |
10 | type Worlds []*World
11 |
12 | func (e Worlds) IDs() []uint64 {
13 | values := make([]uint64, 0, len(e))
14 | for _, value := range e {
15 | values = append(values, value.ID)
16 | }
17 | return values
18 | }
19 |
20 | func (e Worlds) Names() []string {
21 | values := make([]string, 0, len(e))
22 | for _, value := range e {
23 | values = append(values, value.Name)
24 | }
25 | return values
26 | }
27 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/go.mod:
--------------------------------------------------------------------------------
1 | module daoplugin
2 |
3 | go 1.12
4 |
5 | require (
6 | github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
7 | github.com/go-sql-driver/mysql v1.4.1
8 | github.com/labstack/echo v3.3.10+incompatible
9 | github.com/labstack/gommon v0.3.0 // indirect
10 | golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 // indirect
11 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7
12 | google.golang.org/appengine v1.6.2 // indirect
13 | )
14 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/mock/model/factory/field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "daoplugin/entity"
7 | "daoplugin/model"
8 | )
9 |
10 | func DefaultField() *model.Field {
11 | value := &model.Field{Field: &entity.Field{
12 | Difficulty: 0,
13 | ID: 0,
14 | Level: 0,
15 | LocationX: 0,
16 | LocationY: 0,
17 | Name: "",
18 | ObjectNum: 0,
19 | }}
20 | return value
21 | }
22 |
23 | func DefaultFields() *model.Fields {
24 | values := &model.Fields{}
25 | {
26 | value := &model.Field{Field: &entity.Field{
27 | Difficulty: 0,
28 | ID: 0,
29 | Level: 0,
30 | LocationX: 0,
31 | LocationY: 0,
32 | Name: "",
33 | ObjectNum: 0,
34 | }}
35 | values.Add(value)
36 | }
37 | return values
38 | }
39 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/mock/model/factory/group.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "daoplugin/entity"
7 | "daoplugin/model"
8 | )
9 |
10 | func DefaultGroup() *model.Group {
11 | value := &model.Group{Group: &entity.Group{
12 | ID: 0,
13 | Name: "",
14 | }}
15 | return value
16 | }
17 |
18 | func DefaultGroups() *model.Groups {
19 | values := &model.Groups{}
20 | {
21 | value := &model.Group{Group: &entity.Group{
22 | ID: 0,
23 | Name: "",
24 | }}
25 | values.Add(value)
26 | }
27 | return values
28 | }
29 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/mock/model/factory/skill.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "daoplugin/entity"
7 | "daoplugin/model"
8 | )
9 |
10 | func DefaultSkill() *model.Skill {
11 | value := &model.Skill{Skill: &entity.Skill{
12 | ID: 0,
13 | SkillEffect: "",
14 | }}
15 | return value
16 | }
17 |
18 | func DefaultSkills() *model.Skills {
19 | values := &model.Skills{}
20 | {
21 | value := &model.Skill{Skill: &entity.Skill{
22 | ID: 0,
23 | SkillEffect: "",
24 | }}
25 | values.Add(value)
26 | }
27 | return values
28 | }
29 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/mock/model/factory/user.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "context"
7 | "daoplugin/entity"
8 | "daoplugin/model"
9 | "time"
10 | )
11 |
12 | func DefaultUser() *model.User {
13 | createdAt, _ := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z")
14 | updatedAt, _ := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z")
15 | userFields := DefaultUserFields()
16 | skill := DefaultSkill()
17 | world := DefaultWorld()
18 | value := &model.User{User: &entity.User{
19 | Age: 0,
20 | CreatedAt: createdAt,
21 | FieldID: 0,
22 | GroupID: 0,
23 | ID: 0,
24 | Name: "john",
25 | Sex: "",
26 | SkillID: 0,
27 | SkillRank: 0,
28 | UpdatedAt: updatedAt,
29 | WorldID: 0,
30 | }}
31 | value.UserFields = func(context.Context) (*model.UserFields, error) {
32 | return userFields, nil
33 | }
34 | value.Skill = func(context.Context) (*model.Skill, error) {
35 | return skill, nil
36 | }
37 | value.World = func(context.Context) (*model.World, error) {
38 | return world, nil
39 | }
40 | return value
41 | }
42 |
43 | func DefaultUsers() *model.Users {
44 | values := &model.Users{}
45 | {
46 | createdAt, _ := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z")
47 | updatedAt, _ := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z")
48 | userFields := DefaultUserFields()
49 | skill := DefaultSkill()
50 | world := DefaultWorld()
51 | value := &model.User{User: &entity.User{
52 | Age: 0,
53 | CreatedAt: createdAt,
54 | FieldID: 0,
55 | GroupID: 0,
56 | ID: 0,
57 | Name: "john",
58 | Sex: "",
59 | SkillID: 0,
60 | SkillRank: 0,
61 | UpdatedAt: updatedAt,
62 | WorldID: 0,
63 | }}
64 | value.UserFields = func(context.Context) (*model.UserFields, error) {
65 | return userFields, nil
66 | }
67 | value.Skill = func(context.Context) (*model.Skill, error) {
68 | return skill, nil
69 | }
70 | value.World = func(context.Context) (*model.World, error) {
71 | return world, nil
72 | }
73 | values.Add(value)
74 | }
75 | return values
76 | }
77 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/mock/model/factory/user_field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "context"
7 | "daoplugin/entity"
8 | "daoplugin/model"
9 | "time"
10 | )
11 |
12 | func DefaultUserField() *model.UserField {
13 | createdAt, _ := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z")
14 | updatedAt, _ := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z")
15 | field := DefaultField()
16 | value := &model.UserField{UserField: &entity.UserField{
17 | CreatedAt: createdAt,
18 | FieldID: 0,
19 | ID: 0,
20 | UpdatedAt: updatedAt,
21 | UserID: 0,
22 | }}
23 | value.Field = func(context.Context) (*model.Field, error) {
24 | return field, nil
25 | }
26 | return value
27 | }
28 |
29 | func DefaultUserFields() *model.UserFields {
30 | values := &model.UserFields{}
31 | {
32 | createdAt, _ := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z")
33 | updatedAt, _ := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z")
34 | field := DefaultField()
35 | value := &model.UserField{UserField: &entity.UserField{
36 | CreatedAt: createdAt,
37 | FieldID: 0,
38 | ID: 0,
39 | UpdatedAt: updatedAt,
40 | UserID: 0,
41 | }}
42 | value.Field = func(context.Context) (*model.Field, error) {
43 | return field, nil
44 | }
45 | values.Add(value)
46 | }
47 | return values
48 | }
49 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/mock/model/factory/world.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "daoplugin/entity"
7 | "daoplugin/model"
8 | )
9 |
10 | func DefaultWorld() *model.World {
11 | value := &model.World{World: &entity.World{
12 | ID: 0,
13 | Name: "",
14 | }}
15 | return value
16 | }
17 |
18 | func DefaultWorlds() *model.Worlds {
19 | values := &model.Worlds{}
20 | {
21 | value := &model.World{World: &entity.World{
22 | ID: 0,
23 | Name: "",
24 | }}
25 | values.Add(value)
26 | }
27 | return values
28 | }
29 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/mock/model/field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "daoplugin/entity"
7 | "daoplugin/model"
8 | )
9 |
10 | func DefaultField() *model.Field {
11 | value := model.NewField(&entity.Field{
12 | Difficulty: 1,
13 | ID: 1,
14 | Level: 1,
15 | LocationX: 1,
16 | LocationY: 1,
17 | Name: "",
18 | ObjectNum: 1,
19 | }, nil)
20 | return value
21 | }
22 |
23 | func DefaultsField() *model.Fields {
24 | values := model.NewFields(entity.Fields{})
25 | values.Add(DefaultField())
26 | return values
27 | }
28 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/mock/model/group.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "daoplugin/entity"
7 | "daoplugin/model"
8 | )
9 |
10 | func DefaultGroup() *model.Group {
11 | value := model.NewGroup(&entity.Group{
12 | ID: 1,
13 | Name: "",
14 | }, nil)
15 | return value
16 | }
17 |
18 | func DefaultsGroup() *model.Groups {
19 | values := model.NewGroups(entity.Groups{})
20 | values.Add(DefaultGroup())
21 | return values
22 | }
23 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/mock/model/skill.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "daoplugin/entity"
7 | "daoplugin/model"
8 | )
9 |
10 | func DefaultSkill() *model.Skill {
11 | value := model.NewSkill(&entity.Skill{
12 | ID: 1,
13 | SkillEffect: "fire",
14 | }, nil)
15 | return value
16 | }
17 |
18 | func DefaultsSkill() *model.Skills {
19 | values := model.NewSkills(entity.Skills{})
20 | values.Add(DefaultSkill())
21 | return values
22 | }
23 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/mock/model/user.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "context"
7 | "daoplugin/entity"
8 | "daoplugin/model"
9 | )
10 |
11 | func DefaultUser() *model.User {
12 | value := model.NewUser(&entity.User{
13 | Age: 0,
14 | FieldID: 0,
15 | GroupID: 0,
16 | ID: 1,
17 | Name: "john",
18 | Sex: "",
19 | SkillID: 0,
20 | SkillRank: 0,
21 | WorldID: 0,
22 | }, nil)
23 | value.UserFields = func(context.Context) (*model.UserFields, error) {
24 | return DefaultsUserField(), nil
25 | }
26 | value.Skill = func(context.Context) (*model.Skill, error) {
27 | return DefaultSkill(), nil
28 | }
29 | value.World = func(context.Context) (*model.World, error) {
30 | return DefaultWorld(), nil
31 | }
32 | return value
33 | }
34 |
35 | func DefaultsUser() *model.Users {
36 | values := model.NewUsers(entity.Users{})
37 | values.Add(DefaultUser())
38 | return values
39 | }
40 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/mock/model/user_field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "context"
7 | "daoplugin/entity"
8 | "daoplugin/model"
9 | )
10 |
11 | func DefaultUserField() *model.UserField {
12 | value := model.NewUserField(&entity.UserField{
13 | FieldID: 0,
14 | ID: 1,
15 | UserID: 1,
16 | }, nil)
17 | value.Field = func(context.Context) (*model.Field, error) {
18 | return DefaultField(), nil
19 | }
20 | return value
21 | }
22 |
23 | func DefaultsUserField() *model.UserFields {
24 | values := model.NewUserFields(entity.UserFields{})
25 | values.Add(DefaultUserField())
26 | return values
27 | }
28 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/mock/model/world.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "daoplugin/entity"
7 | "daoplugin/model"
8 | )
9 |
10 | func DefaultWorld() *model.World {
11 | value := model.NewWorld(&entity.World{
12 | ID: 1,
13 | Name: "",
14 | }, nil)
15 | return value
16 | }
17 |
18 | func DefaultsWorld() *model.Worlds {
19 | values := model.NewWorlds(entity.Worlds{})
20 | values.Add(DefaultWorld())
21 | return values
22 | }
23 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/model/model.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "context"
7 | "daoplugin/entity"
8 | )
9 |
10 | type ModelConverter interface {
11 | ToField(*entity.Field) *Field
12 | ToGroup(*entity.Group) *Group
13 | ToSkill(*entity.Skill) *Skill
14 | ToUser(*entity.User) *User
15 | ToUserField(*entity.UserField) *UserField
16 | ToWorld(*entity.World) *World
17 | }
18 |
19 | type BeforeRenderer interface {
20 | BeforeRender(context.Context) error
21 | }
22 |
23 | type RenderOption struct {
24 | Name string
25 | IsIncludeAll bool
26 | onlyNames map[string]struct{}
27 | exceptNames map[string]struct{}
28 | includes map[string]*RenderOption
29 | }
30 |
31 | func (ro *RenderOption) Exists(name string) bool {
32 | if len(ro.onlyNames) > 0 {
33 | if _, exists := ro.onlyNames[name]; exists {
34 | return true
35 | }
36 | return false
37 | }
38 | if len(ro.exceptNames) > 0 {
39 | if _, exists := ro.exceptNames[name]; exists {
40 | return false
41 | }
42 | return true
43 | }
44 | return true
45 | }
46 |
47 | func (ro *RenderOption) IncludeOption(name string) *RenderOption {
48 | if ro.Name == name {
49 | return ro
50 | }
51 | return ro.includes[name]
52 | }
53 |
54 | type RenderOptionBuilder struct {
55 | onlyNames map[string]struct{}
56 | exceptNames map[string]struct{}
57 | includes map[string]*RenderOption
58 | isIncludeAll bool
59 | }
60 |
61 | func NewRenderOptionBuilder() *RenderOptionBuilder {
62 | return &RenderOptionBuilder{
63 | exceptNames: map[string]struct{}{},
64 | includes: map[string]*RenderOption{},
65 | onlyNames: map[string]struct{}{},
66 | }
67 | }
68 |
69 | func (b *RenderOptionBuilder) Only(names ...string) *RenderOptionBuilder {
70 | for _, name := range names {
71 | b.onlyNames[name] = struct{}{}
72 | }
73 | return b
74 | }
75 |
76 | func (b *RenderOptionBuilder) Except(names ...string) *RenderOptionBuilder {
77 | for _, name := range names {
78 | b.exceptNames[name] = struct{}{}
79 | }
80 | return b
81 | }
82 |
83 | func (b *RenderOptionBuilder) Include(name string) *RenderOptionBuilder {
84 | b.includes[name] = &RenderOption{Name: name}
85 | return b
86 | }
87 |
88 | func (b *RenderOptionBuilder) IncludeWithCallback(name string, callback func(*RenderOptionBuilder)) *RenderOptionBuilder {
89 | builder := NewRenderOptionBuilder()
90 | callback(builder)
91 | opt := builder.Build()
92 | opt.Name = name
93 | b.includes[name] = opt
94 | return b
95 | }
96 |
97 | func (b *RenderOptionBuilder) IncludeAll() *RenderOptionBuilder {
98 | b.isIncludeAll = true
99 | return b
100 | }
101 |
102 | func (b *RenderOptionBuilder) Build() *RenderOption {
103 | return &RenderOption{
104 | IsIncludeAll: b.isIncludeAll,
105 | exceptNames: b.exceptNames,
106 | includes: b.includes,
107 | onlyNames: b.onlyNames,
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/model/user_api.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import "context"
4 |
5 | func (m *User) Group(ctx context.Context) (*Group, error) {
6 | return nil, nil
7 | }
8 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/repository/group.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package repository
4 |
5 | import (
6 | "context"
7 | "daoplugin/dao"
8 | "daoplugin/entity"
9 | "daoplugin/model"
10 | "database/sql"
11 |
12 | "golang.org/x/xerrors"
13 | )
14 |
15 | type Group interface {
16 | ToModel(*entity.Group) *model.Group
17 | ToModels(entity.Groups) *model.Groups
18 | FindAll(context.Context) (*model.Groups, error)
19 | FindByID(context.Context, uint64) (*model.Group, error)
20 | FindByIDs(context.Context, []uint64) (*model.Groups, error)
21 | Count(context.Context) (int64, error)
22 | }
23 |
24 | type GroupImpl struct {
25 | groupDAO dao.Group
26 | repo Repository
27 | }
28 |
29 | func NewGroup(ctx context.Context, tx *sql.Tx) *GroupImpl {
30 | return &GroupImpl{groupDAO: dao.NewGroup(ctx, tx)}
31 | }
32 |
33 | func (r *GroupImpl) ToModel(value *entity.Group) *model.Group {
34 | return r.createCollection(entity.Groups{value}).First()
35 | }
36 |
37 | func (r *GroupImpl) ToModels(values entity.Groups) *model.Groups {
38 | return r.createCollection(values)
39 | }
40 |
41 | func (r *GroupImpl) FindAll(a0 context.Context) (*model.Groups, error) {
42 | values, err := r.groupDAO.FindAll(a0)
43 | if err != nil {
44 | return nil, xerrors.Errorf("failed to FindAll: %w", err)
45 | }
46 | collection := r.createCollection(values)
47 | return collection, nil
48 | }
49 |
50 | func (r *GroupImpl) FindByID(a0 context.Context, a1 uint64) (*model.Group, error) {
51 | value, err := r.groupDAO.FindByID(a0, a1)
52 | if err != nil {
53 | return nil, xerrors.Errorf("failed to FindByID: %w", err)
54 | }
55 | if value == nil {
56 | return nil, nil
57 | }
58 | v := r.createCollection(entity.Groups{value}).First()
59 | return v, nil
60 | }
61 |
62 | func (r *GroupImpl) FindByIDs(a0 context.Context, a1 []uint64) (*model.Groups, error) {
63 | values, err := r.groupDAO.FindByIDs(a0, a1)
64 | if err != nil {
65 | return nil, xerrors.Errorf("failed to FindByIDs: %w", err)
66 | }
67 | collection := r.createCollection(values)
68 | return collection, nil
69 | }
70 |
71 | func (r *GroupImpl) Count(a0 context.Context) (r0 int64, r1 error) {
72 | r0, r1 = r.groupDAO.Count(a0)
73 | if r1 != nil {
74 | r1 = xerrors.Errorf("failed to Count: %w", r1)
75 | }
76 | return
77 | }
78 |
79 | func (r *GroupImpl) createCollection(entities entity.Groups) *model.Groups {
80 | values := model.NewGroups(entities)
81 | for i := 0; i < len(entities); i += 1 {
82 | values.Add(r.create(entities[i], values))
83 | }
84 | return values
85 | }
86 |
87 | func (r *GroupImpl) create(entity *entity.Group, values *model.Groups) *model.Group {
88 | value := model.NewGroup(entity, r.groupDAO)
89 | value.SetConverter(r.repo.(model.ModelConverter))
90 | return value
91 | }
92 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/repository/skill.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package repository
4 |
5 | import (
6 | "context"
7 | "daoplugin/dao"
8 | "daoplugin/entity"
9 | "daoplugin/model"
10 | "database/sql"
11 |
12 | "golang.org/x/xerrors"
13 | )
14 |
15 | type Skill interface {
16 | ToModel(*entity.Skill) *model.Skill
17 | ToModels(entity.Skills) *model.Skills
18 | FindAll(context.Context) (*model.Skills, error)
19 | FindByID(context.Context, uint64) (*model.Skill, error)
20 | FindByIDs(context.Context, []uint64) (*model.Skills, error)
21 | Count(context.Context) (int64, error)
22 | }
23 |
24 | type SkillImpl struct {
25 | skillDAO dao.Skill
26 | repo Repository
27 | }
28 |
29 | func NewSkill(ctx context.Context, tx *sql.Tx) *SkillImpl {
30 | return &SkillImpl{skillDAO: dao.NewSkill(ctx, tx)}
31 | }
32 |
33 | func (r *SkillImpl) ToModel(value *entity.Skill) *model.Skill {
34 | return r.createCollection(entity.Skills{value}).First()
35 | }
36 |
37 | func (r *SkillImpl) ToModels(values entity.Skills) *model.Skills {
38 | return r.createCollection(values)
39 | }
40 |
41 | func (r *SkillImpl) FindAll(a0 context.Context) (*model.Skills, error) {
42 | values, err := r.skillDAO.FindAll(a0)
43 | if err != nil {
44 | return nil, xerrors.Errorf("failed to FindAll: %w", err)
45 | }
46 | collection := r.createCollection(values)
47 | return collection, nil
48 | }
49 |
50 | func (r *SkillImpl) FindByID(a0 context.Context, a1 uint64) (*model.Skill, error) {
51 | value, err := r.skillDAO.FindByID(a0, a1)
52 | if err != nil {
53 | return nil, xerrors.Errorf("failed to FindByID: %w", err)
54 | }
55 | if value == nil {
56 | return nil, nil
57 | }
58 | v := r.createCollection(entity.Skills{value}).First()
59 | return v, nil
60 | }
61 |
62 | func (r *SkillImpl) FindByIDs(a0 context.Context, a1 []uint64) (*model.Skills, error) {
63 | values, err := r.skillDAO.FindByIDs(a0, a1)
64 | if err != nil {
65 | return nil, xerrors.Errorf("failed to FindByIDs: %w", err)
66 | }
67 | collection := r.createCollection(values)
68 | return collection, nil
69 | }
70 |
71 | func (r *SkillImpl) Count(a0 context.Context) (r0 int64, r1 error) {
72 | r0, r1 = r.skillDAO.Count(a0)
73 | if r1 != nil {
74 | r1 = xerrors.Errorf("failed to Count: %w", r1)
75 | }
76 | return
77 | }
78 |
79 | func (r *SkillImpl) createCollection(entities entity.Skills) *model.Skills {
80 | values := model.NewSkills(entities)
81 | for i := 0; i < len(entities); i += 1 {
82 | values.Add(r.create(entities[i], values))
83 | }
84 | return values
85 | }
86 |
87 | func (r *SkillImpl) create(entity *entity.Skill, values *model.Skills) *model.Skill {
88 | value := model.NewSkill(entity, r.skillDAO)
89 | value.SetConverter(r.repo.(model.ModelConverter))
90 | return value
91 | }
92 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/repository/world.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package repository
4 |
5 | import (
6 | "context"
7 | "daoplugin/dao"
8 | "daoplugin/entity"
9 | "daoplugin/model"
10 | "database/sql"
11 |
12 | "golang.org/x/xerrors"
13 | )
14 |
15 | type World interface {
16 | ToModel(*entity.World) *model.World
17 | ToModels(entity.Worlds) *model.Worlds
18 | FindAll(context.Context) (*model.Worlds, error)
19 | FindByID(context.Context, uint64) (*model.World, error)
20 | FindByIDs(context.Context, []uint64) (*model.Worlds, error)
21 | Count(context.Context) (int64, error)
22 | }
23 |
24 | type WorldImpl struct {
25 | worldDAO dao.World
26 | repo Repository
27 | }
28 |
29 | func NewWorld(ctx context.Context, tx *sql.Tx) *WorldImpl {
30 | return &WorldImpl{worldDAO: dao.NewWorld(ctx, tx)}
31 | }
32 |
33 | func (r *WorldImpl) ToModel(value *entity.World) *model.World {
34 | return r.createCollection(entity.Worlds{value}).First()
35 | }
36 |
37 | func (r *WorldImpl) ToModels(values entity.Worlds) *model.Worlds {
38 | return r.createCollection(values)
39 | }
40 |
41 | func (r *WorldImpl) FindAll(a0 context.Context) (*model.Worlds, error) {
42 | values, err := r.worldDAO.FindAll(a0)
43 | if err != nil {
44 | return nil, xerrors.Errorf("failed to FindAll: %w", err)
45 | }
46 | collection := r.createCollection(values)
47 | return collection, nil
48 | }
49 |
50 | func (r *WorldImpl) FindByID(a0 context.Context, a1 uint64) (*model.World, error) {
51 | value, err := r.worldDAO.FindByID(a0, a1)
52 | if err != nil {
53 | return nil, xerrors.Errorf("failed to FindByID: %w", err)
54 | }
55 | if value == nil {
56 | return nil, nil
57 | }
58 | v := r.createCollection(entity.Worlds{value}).First()
59 | return v, nil
60 | }
61 |
62 | func (r *WorldImpl) FindByIDs(a0 context.Context, a1 []uint64) (*model.Worlds, error) {
63 | values, err := r.worldDAO.FindByIDs(a0, a1)
64 | if err != nil {
65 | return nil, xerrors.Errorf("failed to FindByIDs: %w", err)
66 | }
67 | collection := r.createCollection(values)
68 | return collection, nil
69 | }
70 |
71 | func (r *WorldImpl) Count(a0 context.Context) (r0 int64, r1 error) {
72 | r0, r1 = r.worldDAO.Count(a0)
73 | if r1 != nil {
74 | r1 = xerrors.Errorf("failed to Count: %w", r1)
75 | }
76 | return
77 | }
78 |
79 | func (r *WorldImpl) createCollection(entities entity.Worlds) *model.Worlds {
80 | values := model.NewWorlds(entities)
81 | for i := 0; i < len(entities); i += 1 {
82 | values.Add(r.create(entities[i], values))
83 | }
84 | return values
85 | }
86 |
87 | func (r *WorldImpl) create(entity *entity.World, values *model.Worlds) *model.World {
88 | value := model.NewWorld(entity, r.worldDAO)
89 | value.SetConverter(r.repo.(model.ModelConverter))
90 | return value
91 | }
92 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/schema/fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | `location_x` int NOT NULL,
5 | `location_y` int NOT NULL,
6 | `object_num` int NOT NULL,
7 | `level` int NOT NULL,
8 | `difficulty` int NOT NULL,
9 | PRIMARY KEY (`id`),
10 | UNIQUE KEY `uq_fields_01` (`name`),
11 | UNIQUE KEY `uq_fields_02` (`location_x`, `location_y`),
12 | KEY `idx_fields_03` (`object_num`),
13 | KEY `idx_fields_04` (`difficulty`, `level`)
14 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
15 |
16 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/schema/groups.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `groups` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | PRIMARY KEY (`id`)
5 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/schema/skills.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `skills` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `skill_effect` varchar(30) DEFAULT NULL,
4 | PRIMARY KEY (`id`)
5 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/schema/user_fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `user_fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `user_id` bigint(20) unsigned NOT NULL,
4 | `field_id` bigint(20) unsigned NOT NULL,
5 | `created_at` datetime NOT NULL,
6 | `updated_at` datetime NOT NULL,
7 | PRIMARY KEY (`id`),
8 | UNIQUE KEY `uq_fields_01` (`user_id`, `field_id`)
9 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
10 |
11 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/schema/users.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `users` (
2 | `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
3 | `name` varchar(30) DEFAULT NULL,
4 | `sex` enum('man','woman') NOT NULL,
5 | `age` int NOT NULL,
6 | `skill_id` bigint(20) unsigned NOT NULL,
7 | `skill_rank` int NOT NULL,
8 | `group_id` bigint(20) unsigned NOT NULL,
9 | `world_id` bigint(20) unsigned NOT NULL,
10 | `field_id` bigint(20) unsigned NOT NULL,
11 | `created_at` datetime NOT NULL,
12 | `updated_at` datetime NOT NULL,
13 | PRIMARY KEY (`id`),
14 | UNIQUE KEY `uq_users_01` (`name`),
15 | UNIQUE KEY `uq_users_02` (`skill_id`, `skill_rank`),
16 | KEY `idx_users_03` (`group_id`),
17 | KEY `idx_users_04` (`world_id`, `field_id`)
18 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
19 |
20 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/schema/worlds.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `worlds` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | PRIMARY KEY (`id`)
5 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 |
7 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/server.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | _ "daoplugin/db"
6 | "daoplugin/repository"
7 | "database/sql"
8 | "net/http"
9 | "strconv"
10 |
11 | _ "github.com/go-sql-driver/mysql"
12 | "github.com/labstack/echo"
13 | "github.com/labstack/echo/middleware"
14 | )
15 |
16 | var (
17 | db *sql.DB
18 | )
19 |
20 | func getUser(c echo.Context) error {
21 | id, _ := strconv.Atoi(c.Param("id"))
22 | tx, err := db.Begin()
23 | if err != nil {
24 | return err
25 | }
26 | ctx := context.Background()
27 | repo := repository.New(ctx, tx, uint64(id))
28 | user, err := repo.User().FindByID(ctx, uint64(id))
29 | if err != nil {
30 | return err
31 | }
32 | if err := c.JSON(http.StatusOK, user); err != nil {
33 | return err
34 | }
35 | if err := tx.Commit(); err != nil {
36 | return err
37 | }
38 | return nil
39 | }
40 |
41 | func main() {
42 | e := echo.New()
43 |
44 | conn, err := sql.Open("mysql", "root:@tcp(localhost:3306)/eevee?parseTime=true")
45 | if err != nil {
46 | panic(err)
47 | }
48 | defer conn.Close()
49 |
50 | db = conn
51 |
52 | // Middleware
53 | e.Use(middleware.Logger())
54 | e.Use(middleware.Recover())
55 |
56 | // Routes
57 | e.GET("/users/:id", getUser)
58 |
59 | // Start server
60 | e.Logger.Fatal(e.Start(":1323"))
61 | }
62 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/server_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "daoplugin/mock/model"
6 | "daoplugin/mock/repository"
7 | "testing"
8 | )
9 |
10 | func TestUserGet(t *testing.T) {
11 | repo := repository.NewMock()
12 | ctx := context.Background()
13 | repo.User().EXPECT().FindByID(ctx, 1).Return(model.DefaultUser(), nil)
14 | u, err := repo.User().FindByID(ctx, 1)
15 | if err != nil {
16 | t.Fatalf("%+v", err)
17 | }
18 | if u.ID != model.DefaultUser().ID {
19 | t.Fatal("invalid user")
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/testdata/seeds/field.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | difficulty: 0
4 | id: 0
5 | level: 0
6 | location_x: 0
7 | location_y: 0
8 | name: ""
9 | object_num: 0
10 | collection:
11 | defaults:
12 | - *default
13 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/testdata/seeds/group.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | id: 0
4 | name: ""
5 | collection:
6 | defaults:
7 | - *default
8 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/testdata/seeds/skill.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | id: 0
4 | skill_effect: ""
5 | collection:
6 | defaults:
7 | - *default
8 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/testdata/seeds/user.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | age: 0
4 | created_at: 0001-01-01T00:00:00Z
5 | field_id: 0
6 | group: $default
7 | group_id: 0
8 | id: 0
9 | name: john
10 | sex: ""
11 | skill: $default
12 | skill_id: 0
13 | skill_rank: 0
14 | updated_at: 0001-01-01T00:00:00Z
15 | user_fields: $default
16 | world: $default
17 | world_id: 0
18 | collection:
19 | defaults:
20 | - *default
21 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/testdata/seeds/user_field.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | created_at: 0001-01-01T00:00:00Z
4 | field: $default
5 | field_id: 0
6 | id: 0
7 | updated_at: 0001-01-01T00:00:00Z
8 | user_id: 0
9 | collection:
10 | defaults:
11 | - *default
12 |
--------------------------------------------------------------------------------
/_example/04_dao_plugin/testdata/seeds/world.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | id: 0
4 | name: ""
5 | collection:
6 | defaults:
7 | - *default
8 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/.eevee.yml:
--------------------------------------------------------------------------------
1 | module: rapidashplugin
2 | class: config
3 | schema: schema
4 | dao:
5 | default: rapidash
6 | entity:
7 | plugins:
8 | - rapidash
9 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/README.md:
--------------------------------------------------------------------------------
1 | # How to work example
2 |
3 | ## 1. Prepare memcached and MySQL server
4 |
5 | e.g.)
6 |
7 | ```bash
8 | $ memcached -d
9 | ```
10 |
11 | ```bash
12 | $ mysql.server start
13 | ```
14 |
15 | ## 2. Run server
16 |
17 | ```
18 | $ go run server.go
19 | ```
20 |
21 | ## 3. Get user data
22 |
23 | ```bash
24 | $ curl localhost:1323/users/1 | jq '.'
25 | ```
26 |
27 | ```json
28 | {
29 | "id": 1,
30 | "name": "john",
31 | "sex": "man",
32 | "age": 30,
33 | "skillID": 1,
34 | "skillRank": 10,
35 | "groupID": 1,
36 | "worldID": 1,
37 | "fieldID": 1,
38 | "createdAt": 1585820122,
39 | "updatedAt": 1585820122
40 | }
41 | ```
42 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/config/field.yml:
--------------------------------------------------------------------------------
1 | name: field
2 | datastore: rapidash
3 | index:
4 | primary_key: id
5 | unique_keys:
6 | - - name
7 | - - location_x
8 | - location_y
9 | keys:
10 | - - object_num
11 | - - difficulty
12 | - level
13 | members:
14 | - name: id
15 | type: uint64
16 | - name: name
17 | type: string
18 | - name: location_x
19 | type: int
20 | - name: location_y
21 | type: int
22 | - name: object_num
23 | type: int
24 | - name: level
25 | type: int
26 | - name: difficulty
27 | type: int
28 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/config/group.yml:
--------------------------------------------------------------------------------
1 | name: group
2 | datastore: rapidash
3 | index:
4 | primary_key: id
5 | members:
6 | - name: id
7 | type: uint64
8 | - name: name
9 | type: string
10 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/config/skill.yml:
--------------------------------------------------------------------------------
1 | name: skill
2 | datastore: rapidash
3 | index:
4 | primary_key: id
5 | members:
6 | - name: id
7 | type: uint64
8 | - name: skill_effect
9 | type: string
10 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/config/user.yml:
--------------------------------------------------------------------------------
1 | name: user
2 | datastore: rapidash
3 | index:
4 | primary_key: id
5 | unique_keys:
6 | - - name
7 | - - skill_id
8 | - skill_rank
9 | keys:
10 | - - group_id
11 | - - world_id
12 | - field_id
13 | members:
14 | - name: id
15 | type: uint64
16 | - name: name
17 | type: string
18 | - name: sex
19 | type: string
20 | - name: age
21 | type: int
22 | - name: skill_id
23 | type: uint64
24 | - name: skill_rank
25 | type: int
26 | - name: group_id
27 | type: uint64
28 | - name: world_id
29 | type: uint64
30 | - name: field_id
31 | type: uint64
32 | - name: created_at
33 | type:
34 | import: time
35 | package_name: time
36 | name: Time
37 | - name: updated_at
38 | type:
39 | import: time
40 | package_name: time
41 | name: Time
42 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/config/user_field.yml:
--------------------------------------------------------------------------------
1 | name: user_field
2 | datastore: rapidash
3 | index:
4 | primary_key: id
5 | unique_keys:
6 | - - user_id
7 | - field_id
8 | members:
9 | - name: id
10 | type: uint64
11 | - name: user_id
12 | type: uint64
13 | - name: field_id
14 | type: uint64
15 | - name: created_at
16 | type:
17 | import: time
18 | package_name: time
19 | name: Time
20 | - name: updated_at
21 | type:
22 | import: time
23 | package_name: time
24 | name: Time
25 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/config/world.yml:
--------------------------------------------------------------------------------
1 | name: world
2 | datastore: rapidash
3 | index:
4 | primary_key: id
5 | members:
6 | - name: id
7 | type: uint64
8 | - name: name
9 | type: string
10 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/entity/group.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | import (
6 | "go.knocknote.io/rapidash"
7 | "golang.org/x/xerrors"
8 | )
9 |
10 | type Group struct {
11 | ID uint64 `json:"id"`
12 | Name string `json:"name"`
13 | }
14 |
15 | type Groups []*Group
16 |
17 | func (e Groups) IDs() []uint64 {
18 | values := make([]uint64, 0, len(e))
19 | for _, value := range e {
20 | values = append(values, value.ID)
21 | }
22 | return values
23 | }
24 |
25 | func (e Groups) Names() []string {
26 | values := make([]string, 0, len(e))
27 | for _, value := range e {
28 | values = append(values, value.Name)
29 | }
30 | return values
31 | }
32 |
33 | func (e *Group) Struct() *rapidash.Struct {
34 | return rapidash.NewStruct("groups").
35 | FieldUint64("id").
36 | FieldString("name")
37 | }
38 |
39 | func (e *Group) EncodeRapidash(enc rapidash.Encoder) error {
40 | if e.ID != 0 {
41 | enc.Uint64("id", e.ID)
42 | }
43 | enc.String("name", e.Name)
44 | if err := enc.Error(); err != nil {
45 | return xerrors.Errorf("failed to encode: %w", err)
46 | }
47 | return nil
48 | }
49 |
50 | func (e *Groups) EncodeRapidash(enc rapidash.Encoder) error {
51 | for _, v := range *e {
52 | if err := v.EncodeRapidash(enc.New()); err != nil {
53 | return xerrors.Errorf("failed to encode: %w", err)
54 | }
55 | }
56 | return nil
57 | }
58 |
59 | func (e *Group) DecodeRapidash(dec rapidash.Decoder) error {
60 | e.ID = dec.Uint64("id")
61 | e.Name = dec.String("name")
62 | if err := dec.Error(); err != nil {
63 | return xerrors.Errorf("failed to decode: %w", err)
64 | }
65 | return nil
66 | }
67 |
68 | func (e *Groups) DecodeRapidash(dec rapidash.Decoder) error {
69 | decLen := dec.Len()
70 | values := make(Groups, decLen)
71 | for i := 0; i < decLen; i++ {
72 | var v Group
73 | if err := v.DecodeRapidash(dec.At(i)); err != nil {
74 | return xerrors.Errorf("failed to decode: %w", err)
75 | }
76 | values[i] = &v
77 | }
78 | *e = values
79 | return nil
80 | }
81 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/entity/skill.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | import (
6 | "go.knocknote.io/rapidash"
7 | "golang.org/x/xerrors"
8 | )
9 |
10 | type Skill struct {
11 | ID uint64 `json:"id"`
12 | SkillEffect string `json:"skillEffect"`
13 | }
14 |
15 | type Skills []*Skill
16 |
17 | func (e Skills) IDs() []uint64 {
18 | values := make([]uint64, 0, len(e))
19 | for _, value := range e {
20 | values = append(values, value.ID)
21 | }
22 | return values
23 | }
24 |
25 | func (e Skills) SkillEffects() []string {
26 | values := make([]string, 0, len(e))
27 | for _, value := range e {
28 | values = append(values, value.SkillEffect)
29 | }
30 | return values
31 | }
32 |
33 | func (e *Skill) Struct() *rapidash.Struct {
34 | return rapidash.NewStruct("skills").
35 | FieldUint64("id").
36 | FieldString("skill_effect")
37 | }
38 |
39 | func (e *Skill) EncodeRapidash(enc rapidash.Encoder) error {
40 | if e.ID != 0 {
41 | enc.Uint64("id", e.ID)
42 | }
43 | enc.String("skill_effect", e.SkillEffect)
44 | if err := enc.Error(); err != nil {
45 | return xerrors.Errorf("failed to encode: %w", err)
46 | }
47 | return nil
48 | }
49 |
50 | func (e *Skills) EncodeRapidash(enc rapidash.Encoder) error {
51 | for _, v := range *e {
52 | if err := v.EncodeRapidash(enc.New()); err != nil {
53 | return xerrors.Errorf("failed to encode: %w", err)
54 | }
55 | }
56 | return nil
57 | }
58 |
59 | func (e *Skill) DecodeRapidash(dec rapidash.Decoder) error {
60 | e.ID = dec.Uint64("id")
61 | e.SkillEffect = dec.String("skill_effect")
62 | if err := dec.Error(); err != nil {
63 | return xerrors.Errorf("failed to decode: %w", err)
64 | }
65 | return nil
66 | }
67 |
68 | func (e *Skills) DecodeRapidash(dec rapidash.Decoder) error {
69 | decLen := dec.Len()
70 | values := make(Skills, decLen)
71 | for i := 0; i < decLen; i++ {
72 | var v Skill
73 | if err := v.DecodeRapidash(dec.At(i)); err != nil {
74 | return xerrors.Errorf("failed to decode: %w", err)
75 | }
76 | values[i] = &v
77 | }
78 | *e = values
79 | return nil
80 | }
81 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/entity/world.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | import (
6 | "go.knocknote.io/rapidash"
7 | "golang.org/x/xerrors"
8 | )
9 |
10 | type World struct {
11 | ID uint64 `json:"id"`
12 | Name string `json:"name"`
13 | }
14 |
15 | type Worlds []*World
16 |
17 | func (e Worlds) IDs() []uint64 {
18 | values := make([]uint64, 0, len(e))
19 | for _, value := range e {
20 | values = append(values, value.ID)
21 | }
22 | return values
23 | }
24 |
25 | func (e Worlds) Names() []string {
26 | values := make([]string, 0, len(e))
27 | for _, value := range e {
28 | values = append(values, value.Name)
29 | }
30 | return values
31 | }
32 |
33 | func (e *World) Struct() *rapidash.Struct {
34 | return rapidash.NewStruct("worlds").
35 | FieldUint64("id").
36 | FieldString("name")
37 | }
38 |
39 | func (e *World) EncodeRapidash(enc rapidash.Encoder) error {
40 | if e.ID != 0 {
41 | enc.Uint64("id", e.ID)
42 | }
43 | enc.String("name", e.Name)
44 | if err := enc.Error(); err != nil {
45 | return xerrors.Errorf("failed to encode: %w", err)
46 | }
47 | return nil
48 | }
49 |
50 | func (e *Worlds) EncodeRapidash(enc rapidash.Encoder) error {
51 | for _, v := range *e {
52 | if err := v.EncodeRapidash(enc.New()); err != nil {
53 | return xerrors.Errorf("failed to encode: %w", err)
54 | }
55 | }
56 | return nil
57 | }
58 |
59 | func (e *World) DecodeRapidash(dec rapidash.Decoder) error {
60 | e.ID = dec.Uint64("id")
61 | e.Name = dec.String("name")
62 | if err := dec.Error(); err != nil {
63 | return xerrors.Errorf("failed to decode: %w", err)
64 | }
65 | return nil
66 | }
67 |
68 | func (e *Worlds) DecodeRapidash(dec rapidash.Decoder) error {
69 | decLen := dec.Len()
70 | values := make(Worlds, decLen)
71 | for i := 0; i < decLen; i++ {
72 | var v World
73 | if err := v.DecodeRapidash(dec.At(i)); err != nil {
74 | return xerrors.Errorf("failed to decode: %w", err)
75 | }
76 | values[i] = &v
77 | }
78 | *e = values
79 | return nil
80 | }
81 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/go.mod:
--------------------------------------------------------------------------------
1 | module rapidashplugin
2 |
3 | go 1.12
4 |
5 | require (
6 | github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
7 | github.com/go-sql-driver/mysql v1.4.1
8 | github.com/labstack/echo v3.3.10+incompatible
9 | github.com/labstack/gommon v0.3.0 // indirect
10 | go.knocknote.io/rapidash v0.3.0
11 | golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 // indirect
12 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7
13 | )
14 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/mock/model/factory/field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "rapidashplugin/entity"
7 | "rapidashplugin/model"
8 | )
9 |
10 | func DefaultField() *model.Field {
11 | value := &model.Field{Field: &entity.Field{
12 | Difficulty: 0,
13 | ID: 0,
14 | Level: 0,
15 | LocationX: 0,
16 | LocationY: 0,
17 | Name: "",
18 | ObjectNum: 0,
19 | }}
20 | return value
21 | }
22 |
23 | func DefaultFields() *model.Fields {
24 | values := &model.Fields{}
25 | {
26 | value := &model.Field{Field: &entity.Field{
27 | Difficulty: 0,
28 | ID: 0,
29 | Level: 0,
30 | LocationX: 0,
31 | LocationY: 0,
32 | Name: "",
33 | ObjectNum: 0,
34 | }}
35 | values.Add(value)
36 | }
37 | return values
38 | }
39 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/mock/model/factory/group.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "rapidashplugin/entity"
7 | "rapidashplugin/model"
8 | )
9 |
10 | func DefaultGroup() *model.Group {
11 | value := &model.Group{Group: &entity.Group{
12 | ID: 0,
13 | Name: "",
14 | }}
15 | return value
16 | }
17 |
18 | func DefaultGroups() *model.Groups {
19 | values := &model.Groups{}
20 | {
21 | value := &model.Group{Group: &entity.Group{
22 | ID: 0,
23 | Name: "",
24 | }}
25 | values.Add(value)
26 | }
27 | return values
28 | }
29 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/mock/model/factory/skill.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "rapidashplugin/entity"
7 | "rapidashplugin/model"
8 | )
9 |
10 | func DefaultSkill() *model.Skill {
11 | value := &model.Skill{Skill: &entity.Skill{
12 | ID: 0,
13 | SkillEffect: "",
14 | }}
15 | return value
16 | }
17 |
18 | func DefaultSkills() *model.Skills {
19 | values := &model.Skills{}
20 | {
21 | value := &model.Skill{Skill: &entity.Skill{
22 | ID: 0,
23 | SkillEffect: "",
24 | }}
25 | values.Add(value)
26 | }
27 | return values
28 | }
29 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/mock/model/factory/user.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "rapidashplugin/entity"
7 | "rapidashplugin/model"
8 | "time"
9 | )
10 |
11 | func DefaultUser() *model.User {
12 | createdAt, _ := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z")
13 | updatedAt, _ := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z")
14 | value := &model.User{User: &entity.User{
15 | Age: 0,
16 | CreatedAt: createdAt,
17 | FieldID: 0,
18 | GroupID: 0,
19 | ID: 0,
20 | Name: "",
21 | Sex: "",
22 | SkillID: 0,
23 | SkillRank: 0,
24 | UpdatedAt: updatedAt,
25 | WorldID: 0,
26 | }}
27 | return value
28 | }
29 |
30 | func DefaultUsers() *model.Users {
31 | values := &model.Users{}
32 | {
33 | createdAt, _ := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z")
34 | updatedAt, _ := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z")
35 | value := &model.User{User: &entity.User{
36 | Age: 0,
37 | CreatedAt: createdAt,
38 | FieldID: 0,
39 | GroupID: 0,
40 | ID: 0,
41 | Name: "",
42 | Sex: "",
43 | SkillID: 0,
44 | SkillRank: 0,
45 | UpdatedAt: updatedAt,
46 | WorldID: 0,
47 | }}
48 | values.Add(value)
49 | }
50 | return values
51 | }
52 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/mock/model/factory/user_field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "rapidashplugin/entity"
7 | "rapidashplugin/model"
8 | "time"
9 | )
10 |
11 | func DefaultUserField() *model.UserField {
12 | createdAt, _ := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z")
13 | updatedAt, _ := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z")
14 | value := &model.UserField{UserField: &entity.UserField{
15 | CreatedAt: createdAt,
16 | FieldID: 0,
17 | ID: 0,
18 | UpdatedAt: updatedAt,
19 | UserID: 0,
20 | }}
21 | return value
22 | }
23 |
24 | func DefaultUserFields() *model.UserFields {
25 | values := &model.UserFields{}
26 | {
27 | createdAt, _ := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z")
28 | updatedAt, _ := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z")
29 | value := &model.UserField{UserField: &entity.UserField{
30 | CreatedAt: createdAt,
31 | FieldID: 0,
32 | ID: 0,
33 | UpdatedAt: updatedAt,
34 | UserID: 0,
35 | }}
36 | values.Add(value)
37 | }
38 | return values
39 | }
40 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/mock/model/factory/world.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package factory
4 |
5 | import (
6 | "rapidashplugin/entity"
7 | "rapidashplugin/model"
8 | )
9 |
10 | func DefaultWorld() *model.World {
11 | value := &model.World{World: &entity.World{
12 | ID: 0,
13 | Name: "",
14 | }}
15 | return value
16 | }
17 |
18 | func DefaultWorlds() *model.Worlds {
19 | values := &model.Worlds{}
20 | {
21 | value := &model.World{World: &entity.World{
22 | ID: 0,
23 | Name: "",
24 | }}
25 | values.Add(value)
26 | }
27 | return values
28 | }
29 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/model/model.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "context"
7 | "rapidashplugin/entity"
8 | )
9 |
10 | type ModelConverter interface {
11 | ToField(*entity.Field) *Field
12 | ToGroup(*entity.Group) *Group
13 | ToSkill(*entity.Skill) *Skill
14 | ToUser(*entity.User) *User
15 | ToUserField(*entity.UserField) *UserField
16 | ToWorld(*entity.World) *World
17 | }
18 |
19 | type BeforeRenderer interface {
20 | BeforeRender(context.Context) error
21 | }
22 |
23 | type RenderOption struct {
24 | Name string
25 | IsIncludeAll bool
26 | onlyNames map[string]struct{}
27 | exceptNames map[string]struct{}
28 | includes map[string]*RenderOption
29 | }
30 |
31 | func (ro *RenderOption) Exists(name string) bool {
32 | if len(ro.onlyNames) > 0 {
33 | if _, exists := ro.onlyNames[name]; exists {
34 | return true
35 | }
36 | return false
37 | }
38 | if len(ro.exceptNames) > 0 {
39 | if _, exists := ro.exceptNames[name]; exists {
40 | return false
41 | }
42 | return true
43 | }
44 | return true
45 | }
46 |
47 | func (ro *RenderOption) IncludeOption(name string) *RenderOption {
48 | if ro.Name == name {
49 | return ro
50 | }
51 | return ro.includes[name]
52 | }
53 |
54 | type RenderOptionBuilder struct {
55 | onlyNames map[string]struct{}
56 | exceptNames map[string]struct{}
57 | includes map[string]*RenderOption
58 | isIncludeAll bool
59 | }
60 |
61 | func NewRenderOptionBuilder() *RenderOptionBuilder {
62 | return &RenderOptionBuilder{
63 | exceptNames: map[string]struct{}{},
64 | includes: map[string]*RenderOption{},
65 | onlyNames: map[string]struct{}{},
66 | }
67 | }
68 |
69 | func (b *RenderOptionBuilder) Only(names ...string) *RenderOptionBuilder {
70 | for _, name := range names {
71 | b.onlyNames[name] = struct{}{}
72 | }
73 | return b
74 | }
75 |
76 | func (b *RenderOptionBuilder) Except(names ...string) *RenderOptionBuilder {
77 | for _, name := range names {
78 | b.exceptNames[name] = struct{}{}
79 | }
80 | return b
81 | }
82 |
83 | func (b *RenderOptionBuilder) Include(name string) *RenderOptionBuilder {
84 | b.includes[name] = &RenderOption{Name: name}
85 | return b
86 | }
87 |
88 | func (b *RenderOptionBuilder) IncludeWithCallback(name string, callback func(*RenderOptionBuilder)) *RenderOptionBuilder {
89 | builder := NewRenderOptionBuilder()
90 | callback(builder)
91 | opt := builder.Build()
92 | opt.Name = name
93 | b.includes[name] = opt
94 | return b
95 | }
96 |
97 | func (b *RenderOptionBuilder) IncludeAll() *RenderOptionBuilder {
98 | b.isIncludeAll = true
99 | return b
100 | }
101 |
102 | func (b *RenderOptionBuilder) Build() *RenderOption {
103 | return &RenderOption{
104 | IsIncludeAll: b.isIncludeAll,
105 | exceptNames: b.exceptNames,
106 | includes: b.includes,
107 | onlyNames: b.onlyNames,
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/schema/fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | `location_x` int NOT NULL,
5 | `location_y` int NOT NULL,
6 | `object_num` int NOT NULL,
7 | `level` int NOT NULL,
8 | `difficulty` int NOT NULL,
9 | PRIMARY KEY (`id`),
10 | UNIQUE KEY `uq_fields_01` (`name`),
11 | UNIQUE KEY `uq_fields_02` (`location_x`, `location_y`),
12 | KEY `idx_fields_03` (`object_num`),
13 | KEY `idx_fields_04` (`difficulty`, `level`)
14 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
15 |
16 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/schema/groups.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `groups` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | PRIMARY KEY (`id`)
5 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/schema/skills.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `skills` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `skill_effect` varchar(30) DEFAULT NULL,
4 | PRIMARY KEY (`id`)
5 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/schema/user_fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `user_fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `user_id` bigint(20) unsigned NOT NULL,
4 | `field_id` bigint(20) unsigned NOT NULL,
5 | `created_at` datetime NOT NULL,
6 | `updated_at` datetime NOT NULL,
7 | PRIMARY KEY (`id`),
8 | UNIQUE KEY `uq_fields_01` (`user_id`, `field_id`)
9 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
10 |
11 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/schema/users.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `users` (
2 | `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
3 | `name` varchar(30) DEFAULT NULL,
4 | `sex` enum('man','woman') NOT NULL,
5 | `age` int NOT NULL,
6 | `skill_id` bigint(20) unsigned NOT NULL,
7 | `skill_rank` int NOT NULL,
8 | `group_id` bigint(20) unsigned NOT NULL,
9 | `world_id` bigint(20) unsigned NOT NULL,
10 | `field_id` bigint(20) unsigned NOT NULL,
11 | `created_at` datetime NOT NULL,
12 | `updated_at` datetime NOT NULL,
13 | PRIMARY KEY (`id`),
14 | UNIQUE KEY `uq_users_01` (`name`),
15 | UNIQUE KEY `uq_users_02` (`skill_id`, `skill_rank`),
16 | KEY `idx_users_03` (`group_id`),
17 | KEY `idx_users_04` (`world_id`, `field_id`)
18 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
19 |
20 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/schema/worlds.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `worlds` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | PRIMARY KEY (`id`)
5 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 |
7 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/server.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "database/sql"
6 | "net/http"
7 | _ "rapidashplugin/db"
8 | "rapidashplugin/entity"
9 | "rapidashplugin/repository"
10 | "strconv"
11 |
12 | _ "github.com/go-sql-driver/mysql"
13 | "github.com/labstack/echo"
14 | "github.com/labstack/echo/middleware"
15 | "go.knocknote.io/rapidash"
16 | )
17 |
18 | var (
19 | db *sql.DB
20 | cache *rapidash.Rapidash
21 | )
22 |
23 | func begin() (*rapidash.Tx, error) {
24 | tx, err := db.Begin()
25 | if err != nil {
26 | return nil, err
27 | }
28 | cacheTx, err := cache.Begin(tx)
29 | if err != nil {
30 | return nil, err
31 | }
32 | return cacheTx, nil
33 | }
34 |
35 | func getUser(c echo.Context) error {
36 | id, _ := strconv.Atoi(c.Param("id"))
37 | tx, err := begin()
38 | if err != nil {
39 | return err
40 | }
41 | ctx := context.Background()
42 | repo := repository.New(ctx, tx)
43 | user, err := repo.User().FindByID(ctx, uint64(id))
44 | if err != nil {
45 | return err
46 | }
47 | if err := c.JSON(http.StatusOK, user); err != nil {
48 | return err
49 | }
50 | if err := tx.Commit(); err != nil {
51 | return err
52 | }
53 | return nil
54 | }
55 |
56 | func main() {
57 | e := echo.New()
58 |
59 | conn, err := sql.Open("mysql", "root:@tcp(localhost:3306)/eevee?parseTime=true")
60 | if err != nil {
61 | panic(err)
62 | }
63 | defer conn.Close()
64 |
65 | db = conn
66 | c, err := rapidash.New(
67 | rapidash.LogEnabled(true),
68 | rapidash.ServerAddrs([]string{"localhost:11211"}),
69 | )
70 | if err != nil {
71 | panic(err)
72 | }
73 | if err := c.WarmUp(conn, new(entity.User).Struct(), false); err != nil {
74 | panic(err)
75 | }
76 | if err := c.WarmUp(conn, new(entity.UserField).Struct(), false); err != nil {
77 | panic(err)
78 | }
79 | if err := c.WarmUp(conn, new(entity.Field).Struct(), true); err != nil {
80 | panic(err)
81 | }
82 | if err := c.WarmUp(conn, new(entity.World).Struct(), true); err != nil {
83 | panic(err)
84 | }
85 | if err := c.WarmUp(conn, new(entity.Skill).Struct(), true); err != nil {
86 | panic(err)
87 | }
88 | cache = c
89 |
90 | // Middleware
91 | e.Use(middleware.Logger())
92 | e.Use(middleware.Recover())
93 |
94 | // Routes
95 | e.GET("/users/:id", getUser)
96 |
97 | // Start server
98 | e.Logger.Fatal(e.Start(":1323"))
99 | }
100 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/server_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "daoplugin/mock/model"
6 | "daoplugin/mock/repository"
7 | "testing"
8 | )
9 |
10 | func TestUserGet(t *testing.T) {
11 | repo := repository.NewMock()
12 | ctx := context.Background()
13 | repo.User().EXPECT().FindByID(ctx, 1).Return(model.DefaultUser(), nil)
14 | u, err := repo.User().FindByID(ctx, 1)
15 | if err != nil {
16 | t.Fatalf("%+v", err)
17 | }
18 | if u.ID != model.DefaultUser().ID {
19 | t.Fatal("invalid user")
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/testdata/seeds/field.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | difficulty: 0
4 | id: 0
5 | level: 0
6 | location_x: 0
7 | location_y: 0
8 | name: ""
9 | object_num: 0
10 | collection:
11 | defaults:
12 | - *default
13 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/testdata/seeds/group.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | id: 0
4 | name: ""
5 | collection:
6 | defaults:
7 | - *default
8 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/testdata/seeds/skill.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | id: 0
4 | skill_effect: ""
5 | collection:
6 | defaults:
7 | - *default
8 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/testdata/seeds/user.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | age: 0
4 | created_at: 0001-01-01T00:00:00Z
5 | field_id: 0
6 | group_id: 0
7 | id: 0
8 | name: ""
9 | sex: ""
10 | skill_id: 0
11 | skill_rank: 0
12 | updated_at: 0001-01-01T00:00:00Z
13 | world_id: 0
14 | collection:
15 | defaults:
16 | - *default
17 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/testdata/seeds/user_field.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | created_at: 0001-01-01T00:00:00Z
4 | field_id: 0
5 | id: 0
6 | updated_at: 0001-01-01T00:00:00Z
7 | user_id: 0
8 | collection:
9 | defaults:
10 | - *default
11 |
--------------------------------------------------------------------------------
/_example/05_rapidash_plugin/testdata/seeds/world.yml:
--------------------------------------------------------------------------------
1 | single:
2 | default: &default
3 | id: 0
4 | name: ""
5 | collection:
6 | defaults:
7 | - *default
8 |
--------------------------------------------------------------------------------
/class/testdata/class/field.yml:
--------------------------------------------------------------------------------
1 | name: field
2 | datastore: db
3 | index:
4 | primary_key: id
5 | unique_keys:
6 | - - name
7 | - - location_x
8 | - location_y
9 | keys:
10 | - - object_num
11 | - - difficulty
12 | - level
13 | members:
14 | - name: id
15 | type: uint64
16 | - name: name
17 | type: string
18 | - name: location_x
19 | type: int
20 | - name: location_y
21 | type: int
22 | - name: object_num
23 | type: int
24 | - name: level
25 | type: int
26 | - name: difficulty
27 | type: int
28 |
--------------------------------------------------------------------------------
/class/testdata/class/group.yml:
--------------------------------------------------------------------------------
1 | name: group
2 | datastore: db
3 | index:
4 | primary_key: id
5 | members:
6 | - name: id
7 | type: uint64
8 | - name: name
9 | type: string
10 |
--------------------------------------------------------------------------------
/class/testdata/class/skill.yml:
--------------------------------------------------------------------------------
1 | name: skill
2 | datastore: db
3 | index:
4 | primary_key: id
5 | members:
6 | - name: id
7 | type: uint64
8 | - name: skill_effect
9 | type: string
10 |
--------------------------------------------------------------------------------
/class/testdata/class/user.yml:
--------------------------------------------------------------------------------
1 | name: user
2 | datastore: db
3 | index:
4 | primary_key: id
5 | unique_keys:
6 | - - name
7 | - - skill_id
8 | - skill_rank
9 | keys:
10 | - - group_id
11 | - - world_id
12 | - field_id
13 | members:
14 | - name: id
15 | type: uint64
16 | - name: name
17 | type: string
18 | - name: sex
19 | type: string
20 | - name: age
21 | type: int
22 | - name: skill_id
23 | type: uint64
24 | - name: skill_rank
25 | type: int
26 | - name: group_id
27 | type: uint64
28 | - name: world_id
29 | type: uint64
30 | - name: field_id
31 | type: uint64
32 | - name: user_fields
33 | extend: true
34 | has_many: true
35 | relation:
36 | to: user_field
37 | internal: id
38 | external: user_id
39 | - name: skill
40 | extend: true
41 | render:
42 | inline: true
43 | relation:
44 | to: skill
45 | internal: skill_id
46 | external: id
47 | - name: group
48 | extend: true
49 | render:
50 | json: group
51 | relation:
52 | custom: true
53 | to: group
54 | - name: world
55 | extend: true
56 | render: false
57 | relation:
58 | to: world
59 | internal: world_id
60 | external: id
61 | - name: tx
62 | type:
63 | import: database/sql
64 | package_name: sql
65 | name: Tx
66 | is_pointer: true
67 | extend: true
68 | render: false
69 | - name: fn
70 | type: func(context.Context) error
71 | extend: true
72 | render: false
73 |
--------------------------------------------------------------------------------
/class/testdata/class/user_field.yml:
--------------------------------------------------------------------------------
1 | name: user_field
2 | datastore: db
3 | index:
4 | primary_key: id
5 | unique_keys:
6 | - - user_id
7 | - field_id
8 | members:
9 | - name: id
10 | type: uint64
11 | - name: user_id
12 | type: uint64
13 | - name: field_id
14 | type: uint64
15 |
--------------------------------------------------------------------------------
/class/testdata/class/world.yml:
--------------------------------------------------------------------------------
1 | name: world
2 | datastore: db
3 | index:
4 | primary_key: id
5 | members:
6 | - name: id
7 | type: uint64
8 | - name: name
9 | type: string
10 |
--------------------------------------------------------------------------------
/class/testdata/schema/fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | `location_x` int NOT NULL,
5 | `location_y` int NOT NULL,
6 | `object_num` int NOT NULL,
7 | `level` int NOT NULL,
8 | `difficulty` int NOT NULL,
9 | PRIMARY KEY (`id`),
10 | UNIQUE KEY `uq_fields_01` (`name`),
11 | UNIQUE KEY `uq_fields_02` (`location_x`, `location_y`),
12 | KEY `idx_fields_03` (`object_num`),
13 | KEY `idx_fields_04` (`difficulty`, `level`)
14 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
15 |
16 |
--------------------------------------------------------------------------------
/class/testdata/schema/groups.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `groups` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | PRIMARY KEY (`id`)
5 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 |
7 |
--------------------------------------------------------------------------------
/class/testdata/schema/skills.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `skills` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `skill_effect` varchar(30) DEFAULT NULL,
4 | PRIMARY KEY (`id`)
5 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 |
--------------------------------------------------------------------------------
/class/testdata/schema/user_fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `user_fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `user_id` bigint(20) unsigned NOT NULL,
4 | `field_id` bigint(20) unsigned NOT NULL,
5 | PRIMARY KEY (`id`),
6 | UNIQUE KEY `uq_fields_01` (`user_id`, `field_id`)
7 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
8 |
9 |
--------------------------------------------------------------------------------
/class/testdata/schema/users.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `users` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | `sex` enum('man','woman') NOT NULL,
5 | `age` int NOT NULL,
6 | `skill_id` bigint(20) unsigned NOT NULL,
7 | `skill_rank` int NOT NULL,
8 | `group_id` bigint(20) unsigned NOT NULL,
9 | `world_id` bigint(20) unsigned NOT NULL,
10 | `field_id` bigint(20) unsigned NOT NULL,
11 | PRIMARY KEY (`id`),
12 | UNIQUE KEY `uq_users_01` (`name`),
13 | UNIQUE KEY `uq_users_02` (`skill_id`, `skill_rank`),
14 | KEY `idx_users_03` (`group_id`),
15 | KEY `idx_users_04` (`world_id`, `field_id`)
16 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
17 |
18 |
--------------------------------------------------------------------------------
/class/testdata/schema/worlds.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `worlds` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | PRIMARY KEY (`id`)
5 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6 |
7 |
--------------------------------------------------------------------------------
/code/extention.go:
--------------------------------------------------------------------------------
1 | package code
2 |
3 | type CodeHelper interface {
4 | Package(string) string
5 | }
6 |
7 | const GeneratedMarker = "Code generated by eevee. DO NOT EDIT!"
8 | const FuncGeneratedMarker = "generated by eevee"
9 |
10 | func WrapError(h CodeHelper, msg string) *Statement {
11 | return Qual(h.Package("xerrors"), "Errorf").Call(Lit(msg), Err())
12 | }
13 |
14 | func AddStruct(f *File, name string, codes []Code) {
15 | f.Line()
16 | f.Add(GoType().Id(name).Struct(codes...))
17 | }
18 |
19 | func TypeDef(f *File, name string, c Code) {
20 | f.Line()
21 | f.Add(GoType().Id(name).Add(c))
22 | }
23 |
24 | type Import interface {
25 | GetPath() string
26 | GetName() string
27 | }
28 |
29 | type Imports interface {
30 | Each(func(Import))
31 | }
32 |
33 | func NewGeneratedFile(pkg string, imports Imports) *File {
34 | f := NewFile(pkg)
35 | f.HeaderComment(GeneratedMarker)
36 | imports.Each(func(imp Import) {
37 | f.ImportName(imp.GetPath(), imp.GetName())
38 | })
39 | return f
40 | }
41 |
--------------------------------------------------------------------------------
/config/config_test.go:
--------------------------------------------------------------------------------
1 | package config_test
2 |
3 | import (
4 | "path/filepath"
5 | "testing"
6 |
7 | "go.knocknote.io/eevee/config"
8 | )
9 |
10 | func TestConfig(t *testing.T) {
11 | content := `
12 | module: test
13 | class: config/class
14 | api: config/api
15 | schema: schema
16 | graph: graph
17 | document: docs
18 | output: .
19 | dao:
20 | name: infra
21 | default: db
22 | datastore:
23 | db:
24 | before-create: request-time
25 | entity:
26 | name: entity
27 | repository:
28 | name: repository
29 | renderer:
30 | style: lower-camel
31 | plural:
32 | - name: money
33 | one: moneys
34 | context:
35 | import: app/context
36 | `
37 | cfg, err := config.ConfigFromBytes([]byte(content))
38 | if err != nil {
39 | t.Fatalf("%+v", err)
40 | }
41 | if cfg.OutputPathWithPackage("entity") != filepath.Join(".", "entity") {
42 | t.Fatalf("failed to get output path with package: %s", cfg.OutputPathWithPackage("entity"))
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/config/testdata/eevee.yml:
--------------------------------------------------------------------------------
1 | dao:
2 | datastore:
3 | db:
4 | before-create:
5 | - request-time
6 | create: request-time
7 |
--------------------------------------------------------------------------------
/dao/dao_test.go:
--------------------------------------------------------------------------------
1 | package dao_test
2 |
3 | import (
4 | "path/filepath"
5 | "testing"
6 |
7 | "go.knocknote.io/eevee/class"
8 | "go.knocknote.io/eevee/config"
9 | "go.knocknote.io/eevee/dao"
10 | _ "go.knocknote.io/eevee/plugin"
11 | )
12 |
13 | func TestGenerate(t *testing.T) {
14 | cfg := &config.Config{
15 | ClassPath: filepath.Join("testdata", "class"),
16 | OutputPath: filepath.Join("testdata"),
17 | }
18 | classes, err := class.NewReader().ClassByConfig(cfg)
19 | if err != nil {
20 | t.Fatalf("%+v", err)
21 | }
22 | if err := dao.NewGenerator(cfg).Generate(classes); err != nil {
23 | t.Fatalf("%+v", err)
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/dao/testdata/class/field.yml:
--------------------------------------------------------------------------------
1 | name: field
2 | index:
3 | primary_key: id
4 | unique_keys:
5 | - - name
6 | - - location_x
7 | - location_y
8 | keys:
9 | - - object_num
10 | - - difficulty
11 | - level
12 | members:
13 | - name: id
14 | type: uint64
15 | - name: name
16 | type: string
17 | - name: location_x
18 | type: int
19 | - name: location_y
20 | type: int
21 | - name: object_num
22 | type: int
23 | - name: level
24 | type: int
25 | - name: difficulty
26 | type: int
27 |
--------------------------------------------------------------------------------
/dao/testdata/class/group.yml:
--------------------------------------------------------------------------------
1 | name: group
2 | index:
3 | primary_key: id
4 | members:
5 | - name: id
6 | type: uint64
7 | - name: name
8 | type: string
9 |
--------------------------------------------------------------------------------
/dao/testdata/class/skill.yml:
--------------------------------------------------------------------------------
1 | name: skill
2 | index:
3 | primary_key: id
4 | members:
5 | - name: id
6 | type: uint64
7 | - name: skill_effect
8 | type: string
9 |
--------------------------------------------------------------------------------
/dao/testdata/class/user.yml:
--------------------------------------------------------------------------------
1 | name: user
2 | members:
3 | - name: id
4 | type: uint64
5 | - name: name
6 | type: string
7 | - name: sex
8 | type: string
9 | - name: age
10 | type: int
11 | - name: skill_id
12 | type: uint64
13 | - name: skill_rank
14 | type: int
15 | - name: group_id
16 | type: uint64
17 | - name: world_id
18 | type: uint64
19 | - name: field_id
20 | type: uint64
21 | - name: user_fields
22 | has_many: true
23 | extend: true
24 | relation:
25 | to: user_field
26 | internal: id
27 | external: user_id
28 | - name: skill
29 | extend: true
30 | relation:
31 | to: skill
32 | internal: skill_id
33 | external: id
34 | render:
35 | inline: true
36 | - name: group
37 | extend: true
38 | relation:
39 | to: group
40 | custom: true
41 | render:
42 | json: group
43 | - name: world
44 | extend: true
45 | relation:
46 | to: world
47 | internal: world_id
48 | external: id
49 | render: false
50 | - name: tx
51 | type:
52 | import: database/sql
53 | package_name: sql
54 | name: Tx
55 | is_pointer: true
56 | extend: true
57 | render: false
58 | - name: fn
59 | type: 'func(context.Context) error'
60 | extend: true
61 | render: false
62 | index:
63 | primary_key: id
64 | unique_keys:
65 | - - name
66 | - - skill_id
67 | - skill_rank
68 | keys:
69 | - - group_id
70 | - - world_id
71 | - field_id
72 |
--------------------------------------------------------------------------------
/dao/testdata/class/user_field.yml:
--------------------------------------------------------------------------------
1 | name: user_field
2 | index:
3 | primary_key: id
4 | unique_keys:
5 | - - user_id
6 | - field_id
7 | members:
8 | - name: id
9 | type: uint64
10 | - name: user_id
11 | type: uint64
12 | - name: field_id
13 | type: uint64
14 |
--------------------------------------------------------------------------------
/dao/testdata/class/world.yml:
--------------------------------------------------------------------------------
1 | name: world
2 | index:
3 | primary_key: id
4 | members:
5 | - name: id
6 | type: uint64
7 | - name: name
8 | type: string
9 |
--------------------------------------------------------------------------------
/dao/testdata/eevee.yml:
--------------------------------------------------------------------------------
1 | dao:
2 | default: db
3 | datastore:
4 | db:
5 | before-create:
6 | - request-time
7 | constructor-declare: user-id
8 | constructor: user-id
9 | findby-declare: user-id
10 | findby: user-id
11 | updateby-declare: user-id
12 | updateby: user-id
13 | deleteby-declare: user-id
14 | deleteby: user-id
15 | cache:
16 | before-create:
17 | - request-time
18 | entity:
19 | plugins:
20 | - rapidash
21 |
--------------------------------------------------------------------------------
/entity/entity_test.go:
--------------------------------------------------------------------------------
1 | package entity_test
2 |
3 | import (
4 | "path/filepath"
5 | "testing"
6 |
7 | "go.knocknote.io/eevee/class"
8 | "go.knocknote.io/eevee/config"
9 | "go.knocknote.io/eevee/entity"
10 | _ "go.knocknote.io/eevee/plugin"
11 | )
12 |
13 | func TestGenerate(t *testing.T) {
14 | cfg := &config.Config{
15 | OutputPath: filepath.Join("testdata"),
16 | ClassPath: filepath.Join("testdata", "class"),
17 | }
18 | classes, err := class.NewReader().ClassByConfig(cfg)
19 | if err != nil {
20 | t.Fatalf("%+v", err)
21 | }
22 | if err := entity.NewGenerator(cfg).Generate(classes); err != nil {
23 | t.Fatalf("%+v", err)
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/entity/testdata/class/field.yml:
--------------------------------------------------------------------------------
1 | name: field
2 | index:
3 | primary_key: id
4 | unique_keys:
5 | - - name
6 | - - location_x
7 | - location_y
8 | keys:
9 | - - object_num
10 | - - difficulty
11 | - level
12 | members:
13 | - name: id
14 | type: uint64
15 | - name: name
16 | type: string
17 | - name: location_x
18 | type: int
19 | - name: location_y
20 | type: int
21 | - name: object_num
22 | type: int
23 | - name: level
24 | type: int
25 | - name: difficulty
26 | type: int
27 |
--------------------------------------------------------------------------------
/entity/testdata/class/group.yml:
--------------------------------------------------------------------------------
1 | name: group
2 | index:
3 | primary_key: id
4 | members:
5 | - name: id
6 | type: uint64
7 | - name: name
8 | type: string
9 |
--------------------------------------------------------------------------------
/entity/testdata/class/skill.yml:
--------------------------------------------------------------------------------
1 | name: skill
2 | index:
3 | primary_key: id
4 | members:
5 | - name: id
6 | type: uint64
7 | - name: skill_effect
8 | type: string
9 |
--------------------------------------------------------------------------------
/entity/testdata/class/user.yml:
--------------------------------------------------------------------------------
1 | name: user
2 | members:
3 | - name: id
4 | type: uint64
5 | - name: name
6 | type: string
7 | - name: sex
8 | type: string
9 | - name: age
10 | type: int
11 | - name: skill_id
12 | type: uint64
13 | - name: skill_rank
14 | type: int
15 | - name: group_id
16 | type: uint64
17 | - name: world_id
18 | type: uint64
19 | - name: field_id
20 | type: uint64
21 | - name: user_fields
22 | has_many: true
23 | extend: true
24 | relation:
25 | to: user_field
26 | internal: id
27 | external: user_id
28 | - name: skill
29 | extend: true
30 | relation:
31 | to: skill
32 | internal: skill_id
33 | external: id
34 | render:
35 | inline: true
36 | - name: group
37 | extend: true
38 | relation:
39 | to: group
40 | custom: true
41 | render:
42 | json: group
43 | - name: world
44 | extend: true
45 | relation:
46 | to: world
47 | internal: world_id
48 | external: id
49 | render: false
50 | - name: tx
51 | type:
52 | import: database/sql
53 | package_name: sql
54 | name: Tx
55 | is_pointer: true
56 | extend: true
57 | render: false
58 | - name: fn
59 | type: 'func(context.Context) error'
60 | extend: true
61 | render: false
62 | index:
63 | primary_key: id
64 | unique_keys:
65 | - - name
66 | - - skill_id
67 | - skill_rank
68 | keys:
69 | - - group_id
70 | - - world_id
71 | - field_id
72 |
--------------------------------------------------------------------------------
/entity/testdata/class/user_field.yml:
--------------------------------------------------------------------------------
1 | name: user_field
2 | index:
3 | primary_key: id
4 | unique_keys:
5 | - - user_id
6 | - field_id
7 | members:
8 | - name: id
9 | type: uint64
10 | - name: user_id
11 | type: uint64
12 | - name: field_id
13 | type: uint64
14 |
--------------------------------------------------------------------------------
/entity/testdata/class/world.yml:
--------------------------------------------------------------------------------
1 | name: world
2 | index:
3 | primary_key: id
4 | members:
5 | - name: id
6 | type: uint64
7 | - name: name
8 | type: string
9 |
--------------------------------------------------------------------------------
/entity/testdata/entity/field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type Field struct {
6 | ID uint64 `json:"id"`
7 | Name string `json:"name"`
8 | LocationX int `json:"locationX"`
9 | LocationY int `json:"locationY"`
10 | ObjectNum int `json:"objectNum"`
11 | Level int `json:"level"`
12 | Difficulty int `json:"difficulty"`
13 | }
14 |
15 | type Fields []*Field
16 |
17 | func (e Fields) IDs() []uint64 {
18 | values := make([]uint64, 0, len(e))
19 | for _, value := range e {
20 | values = append(values, value.ID)
21 | }
22 | return values
23 | }
24 |
25 | func (e Fields) Names() []string {
26 | values := make([]string, 0, len(e))
27 | for _, value := range e {
28 | values = append(values, value.Name)
29 | }
30 | return values
31 | }
32 |
33 | func (e Fields) LocationXes() []int {
34 | values := make([]int, 0, len(e))
35 | for _, value := range e {
36 | values = append(values, value.LocationX)
37 | }
38 | return values
39 | }
40 |
41 | func (e Fields) LocationIes() []int {
42 | values := make([]int, 0, len(e))
43 | for _, value := range e {
44 | values = append(values, value.LocationY)
45 | }
46 | return values
47 | }
48 |
49 | func (e Fields) ObjectNums() []int {
50 | values := make([]int, 0, len(e))
51 | for _, value := range e {
52 | values = append(values, value.ObjectNum)
53 | }
54 | return values
55 | }
56 |
57 | func (e Fields) Levels() []int {
58 | values := make([]int, 0, len(e))
59 | for _, value := range e {
60 | values = append(values, value.Level)
61 | }
62 | return values
63 | }
64 |
65 | func (e Fields) Difficulties() []int {
66 | values := make([]int, 0, len(e))
67 | for _, value := range e {
68 | values = append(values, value.Difficulty)
69 | }
70 | return values
71 | }
72 |
--------------------------------------------------------------------------------
/entity/testdata/entity/group.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type Group struct {
6 | ID uint64 `json:"id"`
7 | Name string `json:"name"`
8 | }
9 |
10 | type Groups []*Group
11 |
12 | func (e Groups) IDs() []uint64 {
13 | values := make([]uint64, 0, len(e))
14 | for _, value := range e {
15 | values = append(values, value.ID)
16 | }
17 | return values
18 | }
19 |
20 | func (e Groups) Names() []string {
21 | values := make([]string, 0, len(e))
22 | for _, value := range e {
23 | values = append(values, value.Name)
24 | }
25 | return values
26 | }
27 |
--------------------------------------------------------------------------------
/entity/testdata/entity/skill.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type Skill struct {
6 | ID uint64 `json:"id"`
7 | SkillEffect string `json:"skillEffect"`
8 | }
9 |
10 | type Skills []*Skill
11 |
12 | func (e Skills) IDs() []uint64 {
13 | values := make([]uint64, 0, len(e))
14 | for _, value := range e {
15 | values = append(values, value.ID)
16 | }
17 | return values
18 | }
19 |
20 | func (e Skills) SkillEffects() []string {
21 | values := make([]string, 0, len(e))
22 | for _, value := range e {
23 | values = append(values, value.SkillEffect)
24 | }
25 | return values
26 | }
27 |
--------------------------------------------------------------------------------
/entity/testdata/entity/user.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type User struct {
6 | ID uint64 `json:"id"`
7 | Name string `json:"name"`
8 | Sex string `json:"sex"`
9 | Age int `json:"age"`
10 | SkillID uint64 `json:"skillID"`
11 | SkillRank int `json:"skillRank"`
12 | GroupID uint64 `json:"groupID"`
13 | WorldID uint64 `json:"worldID"`
14 | FieldID uint64 `json:"fieldID"`
15 | }
16 |
17 | type Users []*User
18 |
19 | func (e Users) IDs() []uint64 {
20 | values := make([]uint64, 0, len(e))
21 | for _, value := range e {
22 | values = append(values, value.ID)
23 | }
24 | return values
25 | }
26 |
27 | func (e Users) Names() []string {
28 | values := make([]string, 0, len(e))
29 | for _, value := range e {
30 | values = append(values, value.Name)
31 | }
32 | return values
33 | }
34 |
35 | func (e Users) Sexes() []string {
36 | values := make([]string, 0, len(e))
37 | for _, value := range e {
38 | values = append(values, value.Sex)
39 | }
40 | return values
41 | }
42 |
43 | func (e Users) Ages() []int {
44 | values := make([]int, 0, len(e))
45 | for _, value := range e {
46 | values = append(values, value.Age)
47 | }
48 | return values
49 | }
50 |
51 | func (e Users) SkillIDs() []uint64 {
52 | values := make([]uint64, 0, len(e))
53 | for _, value := range e {
54 | values = append(values, value.SkillID)
55 | }
56 | return values
57 | }
58 |
59 | func (e Users) SkillRanks() []int {
60 | values := make([]int, 0, len(e))
61 | for _, value := range e {
62 | values = append(values, value.SkillRank)
63 | }
64 | return values
65 | }
66 |
67 | func (e Users) GroupIDs() []uint64 {
68 | values := make([]uint64, 0, len(e))
69 | for _, value := range e {
70 | values = append(values, value.GroupID)
71 | }
72 | return values
73 | }
74 |
75 | func (e Users) WorldIDs() []uint64 {
76 | values := make([]uint64, 0, len(e))
77 | for _, value := range e {
78 | values = append(values, value.WorldID)
79 | }
80 | return values
81 | }
82 |
83 | func (e Users) FieldIDs() []uint64 {
84 | values := make([]uint64, 0, len(e))
85 | for _, value := range e {
86 | values = append(values, value.FieldID)
87 | }
88 | return values
89 | }
90 |
--------------------------------------------------------------------------------
/entity/testdata/entity/user_field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type UserField struct {
6 | ID uint64 `json:"id"`
7 | UserID uint64 `json:"userID"`
8 | FieldID uint64 `json:"fieldID"`
9 | }
10 |
11 | type UserFields []*UserField
12 |
13 | func (e UserFields) IDs() []uint64 {
14 | values := make([]uint64, 0, len(e))
15 | for _, value := range e {
16 | values = append(values, value.ID)
17 | }
18 | return values
19 | }
20 |
21 | func (e UserFields) UserIDs() []uint64 {
22 | values := make([]uint64, 0, len(e))
23 | for _, value := range e {
24 | values = append(values, value.UserID)
25 | }
26 | return values
27 | }
28 |
29 | func (e UserFields) FieldIDs() []uint64 {
30 | values := make([]uint64, 0, len(e))
31 | for _, value := range e {
32 | values = append(values, value.FieldID)
33 | }
34 | return values
35 | }
36 |
--------------------------------------------------------------------------------
/entity/testdata/entity/world.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package entity
4 |
5 | type World struct {
6 | ID uint64 `json:"id"`
7 | Name string `json:"name"`
8 | }
9 |
10 | type Worlds []*World
11 |
12 | func (e Worlds) IDs() []uint64 {
13 | values := make([]uint64, 0, len(e))
14 | for _, value := range e {
15 | values = append(values, value.ID)
16 | }
17 | return values
18 | }
19 |
20 | func (e Worlds) Names() []string {
21 | values := make([]string, 0, len(e))
22 | for _, value := range e {
23 | values = append(values, value.Name)
24 | }
25 | return values
26 | }
27 |
--------------------------------------------------------------------------------
/entity/testdata/schema/fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | `location_x` int NOT NULL,
5 | `location_y` int NOT NULL,
6 | `object_num` int NOT NULL,
7 | `level` int NOT NULL,
8 | `difficulty` int NOT NULL,
9 | PRIMARY KEY (`id`),
10 | UNIQUE KEY `uq_fields_01` (`name`),
11 | UNIQUE KEY `uq_fields_02` (`location_x`, `location_y`),
12 | KEY `idx_fields_03` (`object_num`),
13 | KEY `idx_fields_04` (`difficulty`, `level`)
14 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
15 |
16 |
--------------------------------------------------------------------------------
/entity/testdata/schema/user_fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `user_fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `user_id` bigint(20) unsigned NOT NULL,
4 | `field_id` bigint(20) unsigned NOT NULL,
5 | PRIMARY KEY (`id`),
6 | UNIQUE KEY `uq_fields_01` (`user_id`, `field_id`)
7 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
8 |
9 |
--------------------------------------------------------------------------------
/entity/testdata/schema/users.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `users` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | `sex` enum('man','woman') NOT NULL,
5 | `age` int NOT NULL,
6 | `skill_id` bigint(20) unsigned NOT NULL,
7 | `skill_rank` int NOT NULL,
8 | `group_id` bigint(20) unsigned NOT NULL,
9 | `world_id` bigint(20) unsigned NOT NULL,
10 | `field_id` bigint(20) unsigned NOT NULL,
11 | PRIMARY KEY (`id`),
12 | UNIQUE KEY `uq_users_01` (`name`),
13 | UNIQUE KEY `uq_users_02` (`skill_id`, `skill_rank`),
14 | KEY `idx_users_03` (`group_id`),
15 | KEY `idx_users_04` (`world_id`, `field_id`)
16 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
17 |
18 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module go.knocknote.io/eevee
2 |
3 | go 1.12
4 |
5 | require (
6 | github.com/blastrain/vitess-sqlparser v0.0.0-20200914074247-af18b79da035
7 | github.com/dave/jennifer v1.3.0
8 | github.com/fsnotify/fsnotify v1.4.7 // indirect
9 | github.com/goccy/go-yaml v1.4.0
10 | github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365
11 | github.com/jessevdk/go-flags v1.4.0
12 | github.com/jinzhu/inflection v1.0.0
13 | github.com/juju/errors v0.0.0-20190207033735-e65537c515d7 // indirect
14 | github.com/rakyll/statik v0.1.6
15 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b
16 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898
17 | gopkg.in/fsnotify.v1 v1.4.7
18 | )
19 |
--------------------------------------------------------------------------------
/model/model_test.go:
--------------------------------------------------------------------------------
1 | package model_test
2 |
3 | import (
4 | "path/filepath"
5 | "testing"
6 |
7 | "go.knocknote.io/eevee/class"
8 | "go.knocknote.io/eevee/config"
9 | "go.knocknote.io/eevee/model"
10 | _ "go.knocknote.io/eevee/plugin"
11 | )
12 |
13 | func TestGenerate(t *testing.T) {
14 | cfg := &config.Config{
15 | ClassPath: filepath.Join("testdata", "class"),
16 | OutputPath: filepath.Join("testdata"),
17 | }
18 | classes, err := class.NewReader().ClassByConfig(cfg)
19 | if err != nil {
20 | t.Fatalf("%+v", err)
21 | }
22 | if err := model.NewGenerator(cfg).Generate(classes); err != nil {
23 | t.Fatalf("%+v", err)
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/model/testdata/class/field.yml:
--------------------------------------------------------------------------------
1 | name: field
2 | index:
3 | primary_key: id
4 | unique_keys:
5 | - - name
6 | - - location_x
7 | - location_y
8 | keys:
9 | - - object_num
10 | - - difficulty
11 | - level
12 | members:
13 | - name: id
14 | type: uint64
15 | - name: name
16 | type: string
17 | - name: location_x
18 | type: int
19 | - name: location_y
20 | type: int
21 | - name: object_num
22 | type: int
23 | - name: level
24 | type: int
25 | - name: difficulty
26 | type: int
27 |
--------------------------------------------------------------------------------
/model/testdata/class/group.yml:
--------------------------------------------------------------------------------
1 | name: group
2 | index:
3 | primary_key: id
4 | members:
5 | - name: id
6 | type: uint64
7 | - name: name
8 | type: string
9 |
--------------------------------------------------------------------------------
/model/testdata/class/skill.yml:
--------------------------------------------------------------------------------
1 | name: skill
2 | index:
3 | primary_key: id
4 | members:
5 | - name: id
6 | type: uint64
7 | - name: skill_effect
8 | type: string
9 |
--------------------------------------------------------------------------------
/model/testdata/class/user.yml:
--------------------------------------------------------------------------------
1 | name: user
2 | members:
3 | - name: id
4 | type: uint64
5 | - name: name
6 | type: string
7 | - name: sex
8 | type: string
9 | - name: age
10 | type: int
11 | - name: skill_id
12 | type: uint64
13 | - name: skill_rank
14 | type: int
15 | - name: group_id
16 | type: uint64
17 | - name: world_id
18 | type: uint64
19 | - name: field_id
20 | type: uint64
21 | - name: user_fields
22 | has_many: true
23 | extend: true
24 | relation:
25 | to: user_field
26 | internal: id
27 | external: user_id
28 | - name: skill
29 | extend: true
30 | relation:
31 | to: skill
32 | internal: skill_id
33 | external: id
34 | render:
35 | inline: true
36 | - name: group
37 | extend: true
38 | relation:
39 | to: group
40 | custom: true
41 | render:
42 | json: group
43 | - name: world
44 | extend: true
45 | relation:
46 | to: world
47 | internal: world_id
48 | external: id
49 | render: false
50 | - name: tx
51 | type:
52 | import: database/sql
53 | package_name: sql
54 | name: Tx
55 | is_pointer: true
56 | extend: true
57 | render: false
58 | - name: fn
59 | type: 'func(context.Context) error'
60 | extend: true
61 | render: false
62 | index:
63 | primary_key: id
64 | unique_keys:
65 | - - name
66 | - - skill_id
67 | - skill_rank
68 | keys:
69 | - - group_id
70 | - - world_id
71 | - field_id
72 |
--------------------------------------------------------------------------------
/model/testdata/class/user_field.yml:
--------------------------------------------------------------------------------
1 | name: user_field
2 | index:
3 | primary_key: id
4 | unique_keys:
5 | - - user_id
6 | - field_id
7 | members:
8 | - name: id
9 | type: uint64
10 | - name: user_id
11 | type: uint64
12 | - name: field_id
13 | type: uint64
14 |
--------------------------------------------------------------------------------
/model/testdata/class/world.yml:
--------------------------------------------------------------------------------
1 | name: world
2 | index:
3 | primary_key: id
4 | members:
5 | - name: id
6 | type: uint64
7 | - name: name
8 | type: string
9 |
--------------------------------------------------------------------------------
/model/testdata/model/model.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package model
4 |
5 | import (
6 | "/entity"
7 | "context"
8 | )
9 |
10 | type ModelConverter interface {
11 | ToField(*entity.Field) *Field
12 | ToGroup(*entity.Group) *Group
13 | ToSkill(*entity.Skill) *Skill
14 | ToUser(*entity.User) *User
15 | ToUserField(*entity.UserField) *UserField
16 | ToWorld(*entity.World) *World
17 | }
18 |
19 | type BeforeRenderer interface {
20 | BeforeRender(context.Context) error
21 | }
22 |
23 | type RenderOption struct {
24 | Name string
25 | IsIncludeAll bool
26 | onlyNames map[string]struct{}
27 | exceptNames map[string]struct{}
28 | includes map[string]*RenderOption
29 | }
30 |
31 | func (ro *RenderOption) Exists(name string) bool {
32 | if len(ro.onlyNames) > 0 {
33 | if _, exists := ro.onlyNames[name]; exists {
34 | return true
35 | }
36 | return false
37 | }
38 | if len(ro.exceptNames) > 0 {
39 | if _, exists := ro.exceptNames[name]; exists {
40 | return false
41 | }
42 | return true
43 | }
44 | return true
45 | }
46 |
47 | func (ro *RenderOption) IncludeOption(name string) *RenderOption {
48 | if ro.Name == name {
49 | return ro
50 | }
51 | return ro.includes[name]
52 | }
53 |
54 | type RenderOptionBuilder struct {
55 | onlyNames map[string]struct{}
56 | exceptNames map[string]struct{}
57 | includes map[string]*RenderOption
58 | isIncludeAll bool
59 | }
60 |
61 | func NewRenderOptionBuilder() *RenderOptionBuilder {
62 | return &RenderOptionBuilder{
63 | exceptNames: map[string]struct{}{},
64 | includes: map[string]*RenderOption{},
65 | onlyNames: map[string]struct{}{},
66 | }
67 | }
68 |
69 | func (b *RenderOptionBuilder) Only(names ...string) *RenderOptionBuilder {
70 | for _, name := range names {
71 | b.onlyNames[name] = struct{}{}
72 | }
73 | return b
74 | }
75 |
76 | func (b *RenderOptionBuilder) Except(names ...string) *RenderOptionBuilder {
77 | for _, name := range names {
78 | b.exceptNames[name] = struct{}{}
79 | }
80 | return b
81 | }
82 |
83 | func (b *RenderOptionBuilder) Include(name string) *RenderOptionBuilder {
84 | b.includes[name] = &RenderOption{Name: name}
85 | return b
86 | }
87 |
88 | func (b *RenderOptionBuilder) IncludeWithCallback(name string, callback func(*RenderOptionBuilder)) *RenderOptionBuilder {
89 | builder := NewRenderOptionBuilder()
90 | callback(builder)
91 | opt := builder.Build()
92 | opt.Name = name
93 | b.includes[name] = opt
94 | return b
95 | }
96 |
97 | func (b *RenderOptionBuilder) IncludeAll() *RenderOptionBuilder {
98 | b.isIncludeAll = true
99 | return b
100 | }
101 |
102 | func (b *RenderOptionBuilder) Build() *RenderOption {
103 | return &RenderOption{
104 | IsIncludeAll: b.isIncludeAll,
105 | exceptNames: b.exceptNames,
106 | includes: b.includes,
107 | onlyNames: b.onlyNames,
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/model/testdata/schema/fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | `location_x` int NOT NULL,
5 | `location_y` int NOT NULL,
6 | `object_num` int NOT NULL,
7 | `level` int NOT NULL,
8 | `difficulty` int NOT NULL,
9 | PRIMARY KEY (`id`),
10 | UNIQUE KEY `uq_fields_01` (`name`),
11 | UNIQUE KEY `uq_fields_02` (`location_x`, `location_y`),
12 | KEY `idx_fields_03` (`object_num`),
13 | KEY `idx_fields_04` (`difficulty`, `level`)
14 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
15 |
16 |
--------------------------------------------------------------------------------
/model/testdata/schema/user_fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `user_fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `user_id` bigint(20) unsigned NOT NULL,
4 | `field_id` bigint(20) unsigned NOT NULL,
5 | PRIMARY KEY (`id`),
6 | UNIQUE KEY `uq_fields_01` (`user_id`, `field_id`)
7 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
8 |
9 |
--------------------------------------------------------------------------------
/model/testdata/schema/users.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `users` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | `sex` enum('man','woman') NOT NULL,
5 | `age` int NOT NULL,
6 | `skill_id` bigint(20) unsigned NOT NULL,
7 | `skill_rank` int NOT NULL,
8 | `group_id` bigint(20) unsigned NOT NULL,
9 | `world_id` bigint(20) unsigned NOT NULL,
10 | `field_id` bigint(20) unsigned NOT NULL,
11 | PRIMARY KEY (`id`),
12 | UNIQUE KEY `uq_users_01` (`name`),
13 | UNIQUE KEY `uq_users_02` (`skill_id`, `skill_rank`),
14 | KEY `idx_users_03` (`group_id`),
15 | KEY `idx_users_04` (`world_id`, `field_id`)
16 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
17 |
18 |
--------------------------------------------------------------------------------
/plugin/eevee-octillery-plugin/dao.go:
--------------------------------------------------------------------------------
1 | package eevee
2 |
3 | import (
4 | "go.knocknote.io/eevee/plugin/dao"
5 | "go.knocknote.io/eevee/types"
6 | )
7 |
8 | type OctilleryDataAccessHandler struct {
9 | dao.DefaultPlugin
10 | }
11 |
12 | func init() {
13 | dao.Register("octillery", &OctilleryDataAccessHandler{})
14 | }
15 |
16 | func (*OctilleryDataAccessHandler) Imports(pkgs types.ImportList) types.ImportList {
17 | for _, decl := range []*types.ImportDeclare{
18 | {
19 | Path: "go.knocknote.io/octillery/database/sql",
20 | Name: "sql",
21 | },
22 | } {
23 | pkgs[decl.Name] = decl
24 | }
25 | return pkgs
26 | }
27 |
--------------------------------------------------------------------------------
/plugin/eevee-request-time-plugin/dao.go:
--------------------------------------------------------------------------------
1 | package eevee
2 |
3 | import (
4 | . "go.knocknote.io/eevee/code"
5 | "go.knocknote.io/eevee/plugin/dao"
6 | "go.knocknote.io/eevee/types"
7 | )
8 |
9 | type DAORequestTimePlugin struct {
10 | dao.DefaultPlugin
11 | }
12 |
13 | func init() {
14 | dao.Register("request-time", &DAORequestTimePlugin{})
15 | }
16 |
17 | func (*DAORequestTimePlugin) BeforeCreate(p *types.CreateParam) []Code {
18 | createdAt := p.Class.MemberByName("created_at")
19 | updatedAt := p.Class.MemberByName("updated_at")
20 | if createdAt == nil || updatedAt == nil {
21 | return nil
22 | }
23 | code := []Code{
24 | Id("v").Op(":=").Id("ctx").Dot("Value").Call(Lit("REQUEST_TIME")),
25 | List(Id("requestTime"), Id("ok")).Op(":=").Id("v").Assert(Qual(p.Package("time"), "Time")),
26 | If(
27 | Add(Op("!")).Id("ok"),
28 | ).Block(
29 | Return(Qual(p.Package("xerrors"), "New").Call(Lit("cannot convert time.Time value from ctx.Value(`REQUEST_TIME`)"))),
30 | ),
31 | }
32 | if createdAt.Type.IsPointer {
33 | code = append(code, Id("value").Dot("CreatedAt").Op("=").Op("&").Id("requestTime"))
34 | } else {
35 | code = append(code, Id("value").Dot("CreatedAt").Op("=").Id("requestTime"))
36 | }
37 | if updatedAt.Type.IsPointer {
38 | code = append(code, Id("value").Dot("UpdatedAt").Op("=").Op("&").Id("requestTime"))
39 | } else {
40 | code = append(code, Id("value").Dot("UpdatedAt").Op("=").Id("requestTime"))
41 | }
42 | return code
43 | }
44 |
45 | func (*DAORequestTimePlugin) BeforeUpdate(p *types.UpdateParam) []Code {
46 | updatedAt := p.Class.MemberByName("updated_at")
47 | if updatedAt == nil {
48 | return nil
49 | }
50 | code := []Code{
51 | Id("v").Op(":=").Id("ctx").Dot("Value").Call(Lit("REQUEST_TIME")),
52 | List(Id("requestTime"), Id("ok")).Op(":=").Id("v").Assert(Qual(p.Package("time"), "Time")),
53 | If(
54 | Add(Op("!")).Id("ok"),
55 | ).Block(
56 | Return(Qual(p.Package("xerrors"), "New").Call(Lit("cannot convert time.Time value from ctx.Value(`REQUEST_TIME`)"))),
57 | ),
58 | }
59 | if updatedAt.Type.IsPointer {
60 | code = append(code, Id("value").Dot("UpdatedAt").Op("=").Op("&").Id("requestTime"))
61 | } else {
62 | code = append(code, Id("value").Dot("UpdatedAt").Op("=").Id("requestTime"))
63 | }
64 | return code
65 | }
66 |
--------------------------------------------------------------------------------
/plugin/entity/interface.go:
--------------------------------------------------------------------------------
1 | package entity
2 |
3 | import "go.knocknote.io/eevee/types"
4 |
5 | const (
6 | // AddMethodsPlugin name for hook of AddMethods
7 | AddMethodsPlugin = "add-methods"
8 | )
9 |
10 | type EntityPlugin interface {
11 | Imports(types.ImportList) types.ImportList
12 | AddMethods(*types.EntityMethodHelper) types.Methods
13 | }
14 |
15 | var (
16 | plugins = map[string]EntityPlugin{}
17 | )
18 |
19 | func Register(name string, plugin EntityPlugin) {
20 | plugins[name] = plugin
21 | }
22 |
23 | func Plugin(name string) (EntityPlugin, bool) {
24 | plugin, ok := plugins[name]
25 | return plugin, ok
26 | }
27 |
28 | func Plugins() []EntityPlugin {
29 | plgs := []EntityPlugin{}
30 | for _, plg := range plugins {
31 | plgs = append(plgs, plg)
32 | }
33 | return plgs
34 | }
35 |
--------------------------------------------------------------------------------
/plugin/plugin.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | _ "go.knocknote.io/eevee/plugin/eevee-octillery-plugin"
5 | _ "go.knocknote.io/eevee/plugin/eevee-rapidash-plugin"
6 | _ "go.knocknote.io/eevee/plugin/eevee-request-time-plugin"
7 | _ "go.knocknote.io/eevee/plugin/eevee-user-id-plugin"
8 | )
9 |
--------------------------------------------------------------------------------
/plural/plural.go:
--------------------------------------------------------------------------------
1 | package plural
2 |
3 | import (
4 | "regexp"
5 |
6 | "github.com/jinzhu/inflection"
7 | )
8 |
9 | func Singular(name string) string {
10 | return inflection.Singular(name)
11 | }
12 |
13 | var (
14 | numPattern = regexp.MustCompile(`([0-9]+)$`)
15 | )
16 |
17 | func Plural(name string) string {
18 | if numPattern.MatchString(name) {
19 | return name + "s"
20 | }
21 | return inflection.Plural(name)
22 | }
23 |
24 | func Register(singular, plural string) {
25 | inflection.AddIrregular(singular, plural)
26 | }
27 |
--------------------------------------------------------------------------------
/renderer/renderer.go:
--------------------------------------------------------------------------------
1 | package renderer
2 |
3 | import (
4 | . "go.knocknote.io/eevee/code"
5 | "go.knocknote.io/eevee/types"
6 | )
7 |
8 | type RendererHelper interface {
9 | Receiver() *Statement
10 | Field(string) *Statement
11 | MethodCall(string, ...Code) *Statement
12 | Package(string) string
13 | GetClass() *types.Class
14 | GetImportList() types.ImportList
15 | IsModelPackage() bool
16 | CreateMethodDeclare() *types.MethodDeclare
17 | CreateCollectionMethodDeclare() *types.MethodDeclare
18 | }
19 |
20 | type Renderer interface {
21 | Render(RendererHelper) *types.Method
22 | RenderWithOption(RendererHelper) *types.Method
23 | RenderCollection(RendererHelper) *types.Method
24 | RenderCollectionWithOption(RendererHelper) *types.Method
25 | Marshaler(RendererHelper) *types.Method
26 | MarshalerContext(RendererHelper) *types.Method
27 | MarshalerCollection(RendererHelper) *types.Method
28 | MarshalerCollectionContext(RendererHelper) *types.Method
29 | Unmarshaler(RendererHelper) *types.Method
30 | UnmarshalerCollection(RendererHelper) *types.Method
31 | }
32 |
--------------------------------------------------------------------------------
/repository/repository_test.go:
--------------------------------------------------------------------------------
1 | package repository_test
2 |
3 | import (
4 | "path/filepath"
5 | "testing"
6 |
7 | "go.knocknote.io/eevee/class"
8 | "go.knocknote.io/eevee/config"
9 | _ "go.knocknote.io/eevee/plugin"
10 | "go.knocknote.io/eevee/repository"
11 | )
12 |
13 | func TestGenerate(t *testing.T) {
14 | cfg := &config.Config{
15 | ClassPath: filepath.Join("testdata", "class"),
16 | OutputPath: filepath.Join("testdata"),
17 | }
18 | classes, err := class.NewReader().ClassByConfig(cfg)
19 | if err != nil {
20 | t.Fatalf("%+v", err)
21 | }
22 | if err := repository.NewGenerator(cfg).Generate(classes); err != nil {
23 | t.Fatalf("%+v", err)
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/repository/testdata/class/field.yml:
--------------------------------------------------------------------------------
1 | name: field
2 | index:
3 | primary_key: id
4 | unique_keys:
5 | - - name
6 | - - location_x
7 | - location_y
8 | keys:
9 | - - object_num
10 | - - difficulty
11 | - level
12 | members:
13 | - name: id
14 | type: uint64
15 | - name: name
16 | type: string
17 | - name: location_x
18 | type: int
19 | - name: location_y
20 | type: int
21 | - name: object_num
22 | type: int
23 | - name: level
24 | type: int
25 | - name: difficulty
26 | type: int
27 |
--------------------------------------------------------------------------------
/repository/testdata/class/group.yml:
--------------------------------------------------------------------------------
1 | name: group
2 | index:
3 | primary_key: id
4 | members:
5 | - name: id
6 | type: uint64
7 | - name: name
8 | type: string
9 |
--------------------------------------------------------------------------------
/repository/testdata/class/skill.yml:
--------------------------------------------------------------------------------
1 | name: skill
2 | index:
3 | primary_key: id
4 | members:
5 | - name: id
6 | type: uint64
7 | - name: skill_effect
8 | type: string
9 |
--------------------------------------------------------------------------------
/repository/testdata/class/user.yml:
--------------------------------------------------------------------------------
1 | name: user
2 | members:
3 | - name: id
4 | type: uint64
5 | - name: name
6 | type: string
7 | - name: sex
8 | type: string
9 | - name: age
10 | type: int
11 | - name: skill_id
12 | type: uint64
13 | - name: skill_rank
14 | type: int
15 | - name: group_id
16 | type: uint64
17 | - name: world_id
18 | type: uint64
19 | - name: field_id
20 | type: uint64
21 | - name: user_fields
22 | has_many: true
23 | extend: true
24 | relation:
25 | to: user_field
26 | internal: id
27 | external: user_id
28 | - name: skill
29 | extend: true
30 | relation:
31 | to: skill
32 | internal: skill_id
33 | external: id
34 | render:
35 | inline: true
36 | - name: group
37 | extend: true
38 | relation:
39 | to: group
40 | custom: true
41 | render:
42 | json: group
43 | - name: world
44 | extend: true
45 | relation:
46 | to: world
47 | internal: world_id
48 | external: id
49 | render: false
50 | - name: tx
51 | type:
52 | import: database/sql
53 | package_name: sql
54 | name: Tx
55 | is_pointer: true
56 | extend: true
57 | render: false
58 | - name: fn
59 | type: 'func(context.Context) error'
60 | extend: true
61 | render: false
62 | index:
63 | primary_key: id
64 | unique_keys:
65 | - - name
66 | - - skill_id
67 | - skill_rank
68 | keys:
69 | - - group_id
70 | - - world_id
71 | - field_id
72 |
--------------------------------------------------------------------------------
/repository/testdata/class/user_field.yml:
--------------------------------------------------------------------------------
1 | name: user_field
2 | index:
3 | primary_key: id
4 | unique_keys:
5 | - - user_id
6 | - field_id
7 | members:
8 | - name: id
9 | type: uint64
10 | - name: user_id
11 | type: uint64
12 | - name: field_id
13 | type: uint64
14 |
--------------------------------------------------------------------------------
/repository/testdata/class/world.yml:
--------------------------------------------------------------------------------
1 | name: world
2 | index:
3 | primary_key: id
4 | members:
5 | - name: id
6 | type: uint64
7 | - name: name
8 | type: string
9 |
--------------------------------------------------------------------------------
/repository/testdata/repository/field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package repository
4 |
5 | import (
6 | "/dao"
7 | "/entity"
8 | "/model"
9 | "context"
10 | "database/sql"
11 |
12 | "golang.org/x/xerrors"
13 | )
14 |
15 | type Field interface {
16 | ToModel(*entity.Field) *model.Field
17 | ToModels(entity.Fields) *model.Fields
18 | Create(context.Context, *entity.Field) (*model.Field, error)
19 | Creates(context.Context, entity.Fields) (*model.Fields, error)
20 | }
21 |
22 | type FieldImpl struct {
23 | fieldDAO dao.Field
24 | repo Repository
25 | }
26 |
27 | func NewField(ctx context.Context, tx *sql.Tx) *FieldImpl {
28 | return &FieldImpl{fieldDAO: dao.NewField(ctx, tx)}
29 | }
30 |
31 | func (r *FieldImpl) ToModel(value *entity.Field) *model.Field {
32 | return r.createCollection(entity.Fields{value}).First()
33 | }
34 |
35 | func (r *FieldImpl) ToModels(values entity.Fields) *model.Fields {
36 | return r.createCollection(values)
37 | }
38 |
39 | func (r *FieldImpl) Create(ctx context.Context, value *entity.Field) (*model.Field, error) {
40 | if err := r.fieldDAO.Create(ctx, value); err != nil {
41 | return nil, xerrors.Errorf("cannot Create: %w", err)
42 | }
43 | v := r.ToModel(value)
44 | v.SetSavedValue(value)
45 | v.SetAlreadyCreated(true)
46 | return v, nil
47 | }
48 |
49 | func (r *FieldImpl) Creates(ctx context.Context, entities entity.Fields) (*model.Fields, error) {
50 | for _, v := range entities {
51 | if _, err := r.Create(ctx, v); err != nil {
52 | return nil, xerrors.Errorf("cannot Create: %w", err)
53 | }
54 | }
55 | values := r.ToModels(entities)
56 | values.Each(func(v *model.Field) {
57 | v.SetSavedValue(v.Field)
58 | v.SetAlreadyCreated(true)
59 | })
60 | return values, nil
61 | }
62 |
63 | func (r *FieldImpl) createCollection(entities entity.Fields) *model.Fields {
64 | values := model.NewFields(entities)
65 | for i := 0; i < len(entities); i += 1 {
66 | values.Add(r.create(entities[i], values))
67 | }
68 | return values
69 | }
70 |
71 | func (r *FieldImpl) create(entity *entity.Field, values *model.Fields) *model.Field {
72 | value := model.NewField(entity, r.fieldDAO)
73 | value.SetConverter(r.repo.(model.ModelConverter))
74 | return value
75 | }
76 |
--------------------------------------------------------------------------------
/repository/testdata/repository/group.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package repository
4 |
5 | import (
6 | "/dao"
7 | "/entity"
8 | "/model"
9 | "context"
10 | "database/sql"
11 |
12 | "golang.org/x/xerrors"
13 | )
14 |
15 | type Group interface {
16 | ToModel(*entity.Group) *model.Group
17 | ToModels(entity.Groups) *model.Groups
18 | Create(context.Context, *entity.Group) (*model.Group, error)
19 | Creates(context.Context, entity.Groups) (*model.Groups, error)
20 | }
21 |
22 | type GroupImpl struct {
23 | groupDAO dao.Group
24 | repo Repository
25 | }
26 |
27 | func NewGroup(ctx context.Context, tx *sql.Tx) *GroupImpl {
28 | return &GroupImpl{groupDAO: dao.NewGroup(ctx, tx)}
29 | }
30 |
31 | func (r *GroupImpl) ToModel(value *entity.Group) *model.Group {
32 | return r.createCollection(entity.Groups{value}).First()
33 | }
34 |
35 | func (r *GroupImpl) ToModels(values entity.Groups) *model.Groups {
36 | return r.createCollection(values)
37 | }
38 |
39 | func (r *GroupImpl) Create(ctx context.Context, value *entity.Group) (*model.Group, error) {
40 | if err := r.groupDAO.Create(ctx, value); err != nil {
41 | return nil, xerrors.Errorf("cannot Create: %w", err)
42 | }
43 | v := r.ToModel(value)
44 | v.SetSavedValue(value)
45 | v.SetAlreadyCreated(true)
46 | return v, nil
47 | }
48 |
49 | func (r *GroupImpl) Creates(ctx context.Context, entities entity.Groups) (*model.Groups, error) {
50 | for _, v := range entities {
51 | if _, err := r.Create(ctx, v); err != nil {
52 | return nil, xerrors.Errorf("cannot Create: %w", err)
53 | }
54 | }
55 | values := r.ToModels(entities)
56 | values.Each(func(v *model.Group) {
57 | v.SetSavedValue(v.Group)
58 | v.SetAlreadyCreated(true)
59 | })
60 | return values, nil
61 | }
62 |
63 | func (r *GroupImpl) createCollection(entities entity.Groups) *model.Groups {
64 | values := model.NewGroups(entities)
65 | for i := 0; i < len(entities); i += 1 {
66 | values.Add(r.create(entities[i], values))
67 | }
68 | return values
69 | }
70 |
71 | func (r *GroupImpl) create(entity *entity.Group, values *model.Groups) *model.Group {
72 | value := model.NewGroup(entity, r.groupDAO)
73 | value.SetConverter(r.repo.(model.ModelConverter))
74 | return value
75 | }
76 |
--------------------------------------------------------------------------------
/repository/testdata/repository/skill.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package repository
4 |
5 | import (
6 | "/dao"
7 | "/entity"
8 | "/model"
9 | "context"
10 | "database/sql"
11 |
12 | "golang.org/x/xerrors"
13 | )
14 |
15 | type Skill interface {
16 | ToModel(*entity.Skill) *model.Skill
17 | ToModels(entity.Skills) *model.Skills
18 | Create(context.Context, *entity.Skill) (*model.Skill, error)
19 | Creates(context.Context, entity.Skills) (*model.Skills, error)
20 | }
21 |
22 | type SkillImpl struct {
23 | skillDAO dao.Skill
24 | repo Repository
25 | }
26 |
27 | func NewSkill(ctx context.Context, tx *sql.Tx) *SkillImpl {
28 | return &SkillImpl{skillDAO: dao.NewSkill(ctx, tx)}
29 | }
30 |
31 | func (r *SkillImpl) ToModel(value *entity.Skill) *model.Skill {
32 | return r.createCollection(entity.Skills{value}).First()
33 | }
34 |
35 | func (r *SkillImpl) ToModels(values entity.Skills) *model.Skills {
36 | return r.createCollection(values)
37 | }
38 |
39 | func (r *SkillImpl) Create(ctx context.Context, value *entity.Skill) (*model.Skill, error) {
40 | if err := r.skillDAO.Create(ctx, value); err != nil {
41 | return nil, xerrors.Errorf("cannot Create: %w", err)
42 | }
43 | v := r.ToModel(value)
44 | v.SetSavedValue(value)
45 | v.SetAlreadyCreated(true)
46 | return v, nil
47 | }
48 |
49 | func (r *SkillImpl) Creates(ctx context.Context, entities entity.Skills) (*model.Skills, error) {
50 | for _, v := range entities {
51 | if _, err := r.Create(ctx, v); err != nil {
52 | return nil, xerrors.Errorf("cannot Create: %w", err)
53 | }
54 | }
55 | values := r.ToModels(entities)
56 | values.Each(func(v *model.Skill) {
57 | v.SetSavedValue(v.Skill)
58 | v.SetAlreadyCreated(true)
59 | })
60 | return values, nil
61 | }
62 |
63 | func (r *SkillImpl) createCollection(entities entity.Skills) *model.Skills {
64 | values := model.NewSkills(entities)
65 | for i := 0; i < len(entities); i += 1 {
66 | values.Add(r.create(entities[i], values))
67 | }
68 | return values
69 | }
70 |
71 | func (r *SkillImpl) create(entity *entity.Skill, values *model.Skills) *model.Skill {
72 | value := model.NewSkill(entity, r.skillDAO)
73 | value.SetConverter(r.repo.(model.ModelConverter))
74 | return value
75 | }
76 |
--------------------------------------------------------------------------------
/repository/testdata/repository/user_field.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package repository
4 |
5 | import (
6 | "/dao"
7 | "/entity"
8 | "/model"
9 | "context"
10 | "database/sql"
11 |
12 | "golang.org/x/xerrors"
13 | )
14 |
15 | type UserField interface {
16 | ToModel(*entity.UserField) *model.UserField
17 | ToModels(entity.UserFields) *model.UserFields
18 | Create(context.Context, *entity.UserField) (*model.UserField, error)
19 | Creates(context.Context, entity.UserFields) (*model.UserFields, error)
20 | }
21 |
22 | type UserFieldImpl struct {
23 | userFieldDAO dao.UserField
24 | repo Repository
25 | }
26 |
27 | func NewUserField(ctx context.Context, tx *sql.Tx) *UserFieldImpl {
28 | return &UserFieldImpl{userFieldDAO: dao.NewUserField(ctx, tx)}
29 | }
30 |
31 | func (r *UserFieldImpl) ToModel(value *entity.UserField) *model.UserField {
32 | return r.createCollection(entity.UserFields{value}).First()
33 | }
34 |
35 | func (r *UserFieldImpl) ToModels(values entity.UserFields) *model.UserFields {
36 | return r.createCollection(values)
37 | }
38 |
39 | func (r *UserFieldImpl) Create(ctx context.Context, value *entity.UserField) (*model.UserField, error) {
40 | if err := r.userFieldDAO.Create(ctx, value); err != nil {
41 | return nil, xerrors.Errorf("cannot Create: %w", err)
42 | }
43 | v := r.ToModel(value)
44 | v.SetSavedValue(value)
45 | v.SetAlreadyCreated(true)
46 | return v, nil
47 | }
48 |
49 | func (r *UserFieldImpl) Creates(ctx context.Context, entities entity.UserFields) (*model.UserFields, error) {
50 | for _, v := range entities {
51 | if _, err := r.Create(ctx, v); err != nil {
52 | return nil, xerrors.Errorf("cannot Create: %w", err)
53 | }
54 | }
55 | values := r.ToModels(entities)
56 | values.Each(func(v *model.UserField) {
57 | v.SetSavedValue(v.UserField)
58 | v.SetAlreadyCreated(true)
59 | })
60 | return values, nil
61 | }
62 |
63 | func (r *UserFieldImpl) createCollection(entities entity.UserFields) *model.UserFields {
64 | values := model.NewUserFields(entities)
65 | for i := 0; i < len(entities); i += 1 {
66 | values.Add(r.create(entities[i], values))
67 | }
68 | return values
69 | }
70 |
71 | func (r *UserFieldImpl) create(entity *entity.UserField, values *model.UserFields) *model.UserField {
72 | value := model.NewUserField(entity, r.userFieldDAO)
73 | value.SetConverter(r.repo.(model.ModelConverter))
74 | return value
75 | }
76 |
--------------------------------------------------------------------------------
/repository/testdata/repository/world.go:
--------------------------------------------------------------------------------
1 | // Code generated by eevee. DO NOT EDIT!
2 |
3 | package repository
4 |
5 | import (
6 | "/dao"
7 | "/entity"
8 | "/model"
9 | "context"
10 | "database/sql"
11 |
12 | "golang.org/x/xerrors"
13 | )
14 |
15 | type World interface {
16 | ToModel(*entity.World) *model.World
17 | ToModels(entity.Worlds) *model.Worlds
18 | Create(context.Context, *entity.World) (*model.World, error)
19 | Creates(context.Context, entity.Worlds) (*model.Worlds, error)
20 | }
21 |
22 | type WorldImpl struct {
23 | worldDAO dao.World
24 | repo Repository
25 | }
26 |
27 | func NewWorld(ctx context.Context, tx *sql.Tx) *WorldImpl {
28 | return &WorldImpl{worldDAO: dao.NewWorld(ctx, tx)}
29 | }
30 |
31 | func (r *WorldImpl) ToModel(value *entity.World) *model.World {
32 | return r.createCollection(entity.Worlds{value}).First()
33 | }
34 |
35 | func (r *WorldImpl) ToModels(values entity.Worlds) *model.Worlds {
36 | return r.createCollection(values)
37 | }
38 |
39 | func (r *WorldImpl) Create(ctx context.Context, value *entity.World) (*model.World, error) {
40 | if err := r.worldDAO.Create(ctx, value); err != nil {
41 | return nil, xerrors.Errorf("cannot Create: %w", err)
42 | }
43 | v := r.ToModel(value)
44 | v.SetSavedValue(value)
45 | v.SetAlreadyCreated(true)
46 | return v, nil
47 | }
48 |
49 | func (r *WorldImpl) Creates(ctx context.Context, entities entity.Worlds) (*model.Worlds, error) {
50 | for _, v := range entities {
51 | if _, err := r.Create(ctx, v); err != nil {
52 | return nil, xerrors.Errorf("cannot Create: %w", err)
53 | }
54 | }
55 | values := r.ToModels(entities)
56 | values.Each(func(v *model.World) {
57 | v.SetSavedValue(v.World)
58 | v.SetAlreadyCreated(true)
59 | })
60 | return values, nil
61 | }
62 |
63 | func (r *WorldImpl) createCollection(entities entity.Worlds) *model.Worlds {
64 | values := model.NewWorlds(entities)
65 | for i := 0; i < len(entities); i += 1 {
66 | values.Add(r.create(entities[i], values))
67 | }
68 | return values
69 | }
70 |
71 | func (r *WorldImpl) create(entity *entity.World, values *model.Worlds) *model.World {
72 | value := model.NewWorld(entity, r.worldDAO)
73 | value.SetConverter(r.repo.(model.ModelConverter))
74 | return value
75 | }
76 |
--------------------------------------------------------------------------------
/repository/testdata/schema/fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | `location_x` int NOT NULL,
5 | `location_y` int NOT NULL,
6 | `object_num` int NOT NULL,
7 | `level` int NOT NULL,
8 | `difficulty` int NOT NULL,
9 | PRIMARY KEY (`id`),
10 | UNIQUE KEY `uq_fields_01` (`name`),
11 | UNIQUE KEY `uq_fields_02` (`location_x`, `location_y`),
12 | KEY `idx_fields_03` (`object_num`),
13 | KEY `idx_fields_04` (`difficulty`, `level`)
14 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
15 |
16 |
--------------------------------------------------------------------------------
/repository/testdata/schema/user_fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `user_fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `user_id` bigint(20) unsigned NOT NULL,
4 | `field_id` bigint(20) unsigned NOT NULL,
5 | PRIMARY KEY (`id`),
6 | UNIQUE KEY `uq_fields_01` (`user_id`, `field_id`)
7 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
8 |
9 |
--------------------------------------------------------------------------------
/repository/testdata/schema/users.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `users` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | `sex` enum('man','woman') NOT NULL,
5 | `age` int NOT NULL,
6 | `skill_id` bigint(20) unsigned NOT NULL,
7 | `skill_rank` int NOT NULL,
8 | `group_id` bigint(20) unsigned NOT NULL,
9 | `world_id` bigint(20) unsigned NOT NULL,
10 | `field_id` bigint(20) unsigned NOT NULL,
11 | PRIMARY KEY (`id`),
12 | UNIQUE KEY `uq_users_01` (`name`),
13 | UNIQUE KEY `uq_users_02` (`skill_id`, `skill_rank`),
14 | KEY `idx_users_03` (`group_id`),
15 | KEY `idx_users_04` (`world_id`, `field_id`)
16 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
17 |
18 |
--------------------------------------------------------------------------------
/schema/schema_test.go:
--------------------------------------------------------------------------------
1 | package schema
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestSchema(t *testing.T) {
8 | reader := NewReader()
9 | _, err := reader.SchemaFromPath("testdata/schema")
10 | if err != nil {
11 | t.Fatalf("%+v", err)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/schema/testdata/schema/fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | `location_x` int NOT NULL,
5 | `location_y` int NOT NULL,
6 | `object_num` int NOT NULL,
7 | `level` int NOT NULL,
8 | `difficulty` int NOT NULL,
9 | PRIMARY KEY (`id`),
10 | UNIQUE KEY `uq_fields_01` (`name`),
11 | UNIQUE KEY `uq_fields_02` (`location_x`, `location_y`),
12 | KEY `idx_fields_03` (`object_num`),
13 | KEY `idx_fields_04` (`difficulty`, `level`)
14 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
15 |
16 |
--------------------------------------------------------------------------------
/schema/testdata/schema/user_fields.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `user_fields` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `user_id` bigint(20) unsigned NOT NULL,
4 | `field_id` bigint(20) unsigned NOT NULL,
5 | PRIMARY KEY (`id`),
6 | UNIQUE KEY `uq_fields_01` (`user_id`, `field_id`)
7 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
8 |
9 |
--------------------------------------------------------------------------------
/schema/testdata/schema/users.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `users` (
2 | `id` bigint(20) unsigned NOT NULL,
3 | `name` varchar(30) DEFAULT NULL,
4 | `sex` enum('man','woman') NOT NULL,
5 | `age` int NOT NULL,
6 | `skill_id` bigint(20) unsigned NOT NULL,
7 | `skill_rank` int NOT NULL,
8 | `group_id` bigint(20) unsigned NOT NULL,
9 | `world_id` bigint(20) unsigned NOT NULL,
10 | `field_id` bigint(20) unsigned NOT NULL,
11 | PRIMARY KEY (`id`),
12 | UNIQUE KEY `uq_users_01` (`name`),
13 | UNIQUE KEY `uq_users_02` (`skill_id`, `skill_rank`),
14 | KEY `idx_users_03` (`group_id`),
15 | KEY `idx_users_04` (`world_id`, `field_id`)
16 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
17 |
18 |
--------------------------------------------------------------------------------
/static/resources/doc.tmpl:
--------------------------------------------------------------------------------
1 | ## {{ .Description }}
2 |
3 | ```
4 | {{ .Method }} {{ .URI }}
5 | ```
6 |
7 | {{- if .Request }}
8 |
9 | ### Request Parameters
10 |
11 | | Name | Type | In | Required | Description | Example |
12 | | ---- | ---- | -- | -------- | ----------- | ------- |
13 | {{- range .Request.Params }}
14 | | **{{ .RenderName }}** | {{ .Type }} | {{ .In }} | {{ .Required }} | {{ .Desc }} | `{{ .Example }}` |
15 | {{- end }}
16 |
17 | {{- end }}
18 |
19 | {{- if .Response }}
20 |
21 | ### Response Parameters
22 |
23 |
24 |
25 | | Name | Type | Description | Example |
26 | | ---- | ---- | ----------- | ------- |
27 | {{- range .Response.Attributes }}
28 | | **{{ .Name }}** | {{ .Type }} | {{ .Desc }} | `{{ .Example }}` |
29 | {{- end }}
30 |
31 |
32 |
33 |
34 | ### Response Example
35 |
36 | ```json
37 | {{ .Response.RenderJSON }}
38 | ```
39 |
40 | {{- end }}
41 |
--------------------------------------------------------------------------------
/static/resources/index.tmpl:
--------------------------------------------------------------------------------
1 | ## The table of contents
2 |
3 | ### Endpoints
4 |
5 | {{- range . }}
6 | - {{ .Method }} {{ .URI }}
7 | {{- end }}
8 |
9 |
--------------------------------------------------------------------------------
/types/api.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "go.knocknote.io/eevee/code"
5 | )
6 |
7 | type APIResponseHelper struct {
8 | Class *Class
9 | ReceiverName string
10 | ImportList ImportList
11 | }
12 |
13 | func (h *APIResponseHelper) Receiver() *code.Statement {
14 | return code.Id(h.ReceiverName)
15 | }
16 |
17 | func (h *APIResponseHelper) Field(name string) *code.Statement {
18 | return h.Receiver().Dot(name)
19 | }
20 |
21 | func (h *APIResponseHelper) MethodCall(name string, args ...code.Code) *code.Statement {
22 | return h.Field(name).Call(args...)
23 | }
24 |
25 | func (h *APIResponseHelper) GetClass() *Class {
26 | return h.Class
27 | }
28 |
29 | func (h *APIResponseHelper) GetImportList() ImportList {
30 | return h.ImportList
31 | }
32 |
33 | func (h *APIResponseHelper) CreateMethodDeclare() *MethodDeclare {
34 | return &MethodDeclare{
35 | Class: h.Class,
36 | ReceiverName: h.ReceiverName,
37 | ReceiverClassName: h.Class.Name.CamelName(),
38 | ImportList: h.ImportList,
39 | Args: ValueDeclares{},
40 | Return: ValueDeclares{},
41 | }
42 | }
43 |
44 | func (h *APIResponseHelper) CreateCollectionMethodDeclare() *MethodDeclare {
45 | return &MethodDeclare{
46 | Class: h.Class,
47 | ReceiverName: h.ReceiverName,
48 | ReceiverClassName: h.Class.Name.PluralCamelName(),
49 | ImportList: h.ImportList,
50 | Args: ValueDeclares{},
51 | Return: ValueDeclares{},
52 | }
53 | }
54 |
55 | func (h *APIResponseHelper) Package(name string) string {
56 | return h.ImportList.Package(name)
57 | }
58 |
59 | func (h *APIResponseHelper) IsModelPackage() bool {
60 | return false
61 | }
62 |
--------------------------------------------------------------------------------
/types/dao.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "go.knocknote.io/eevee/code"
5 | )
6 |
7 | type SQL struct {
8 | Query string
9 | Args []code.Code
10 | ScanValues []code.Code
11 | }
12 |
13 | type DAOContext interface{}
14 |
15 | type DataAccessParam struct {
16 | Class *Class
17 | ClassName func() *code.Statement
18 | Receiver func() *code.Statement
19 | ImportList ImportList
20 | SQL *SQL
21 | }
22 |
23 | func (p *DataAccessParam) Package(name string) string {
24 | return p.ImportList.Package(name)
25 | }
26 |
27 | func (p *DataAccessParam) Field(name string) *code.Statement {
28 | return p.Receiver().Dot(name)
29 | }
30 |
31 | type ConstructorParam struct {
32 | DataAccessParam
33 | ImplName string
34 | Args *ConstructorParamArgs
35 | }
36 |
37 | type ConstructorParamArgs struct {
38 | Context func() *code.Statement
39 | }
40 |
41 | type CreateParam struct {
42 | DataAccessParam
43 | Args *CreateParamArgs
44 | }
45 |
46 | type CreateParamArgs struct {
47 | Context func() *code.Statement
48 | Value func() *code.Statement
49 | }
50 |
51 | type UpdateParam struct {
52 | DataAccessParam
53 | Args *UpdateParamArgs
54 | }
55 |
56 | type UpdateParamArgs struct {
57 | Context func() *code.Statement
58 | Value func() *code.Statement
59 | UpdateMap func() *code.Statement
60 | Members []*Member
61 | }
62 |
63 | type DeleteParam struct {
64 | DataAccessParam
65 | Args *DeleteParamArgs
66 | }
67 |
68 | type DeleteParamArgs struct {
69 | Context func() *code.Statement
70 | Value func() *code.Statement
71 | Members []*Member
72 | }
73 |
74 | type FindParam struct {
75 | DataAccessParam
76 | Args *FindParamArgs
77 | IsSingleReturnValue bool
78 | }
79 |
80 | type FindParamArgs struct {
81 | Context func() *code.Statement
82 | Members []*Member
83 | }
84 |
85 | type CountParam struct {
86 | DataAccessParam
87 | Args *CountParamArgs
88 | }
89 |
90 | type CountParamArgs struct {
91 | Context func() *code.Statement
92 | Members []*Member
93 | }
94 |
--------------------------------------------------------------------------------
/types/entity.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | . "go.knocknote.io/eevee/code"
5 | )
6 |
7 | type EntityMethodHelper struct {
8 | Class *Class
9 | ReceiverName string
10 | ImportList ImportList
11 | }
12 |
13 | func (h *EntityMethodHelper) CreateMethodDeclare() *MethodDeclare {
14 | return &MethodDeclare{
15 | Class: h.Class,
16 | ReceiverName: h.ReceiverName,
17 | ReceiverClassName: h.Class.Name.CamelName(),
18 | ImportList: h.ImportList,
19 | Args: ValueDeclares{},
20 | Return: ValueDeclares{},
21 | }
22 | }
23 |
24 | func (h *EntityMethodHelper) CreatePluralMethodDeclare() *MethodDeclare {
25 | return &MethodDeclare{
26 | Class: h.Class,
27 | ReceiverName: h.ReceiverName,
28 | ReceiverClassName: h.Class.Name.PluralCamelName(),
29 | ImportList: h.ImportList,
30 | Args: ValueDeclares{},
31 | Return: ValueDeclares{},
32 | }
33 | }
34 |
35 | func (h *EntityMethodHelper) Field(name string) *Statement {
36 | return Id(h.ReceiverName).Dot(name)
37 | }
38 |
39 | func (h *EntityMethodHelper) Package(name string) string {
40 | return h.ImportList.Package(name)
41 | }
42 |
--------------------------------------------------------------------------------
/types/name.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "fmt"
5 | "regexp"
6 |
7 | "github.com/iancoleman/strcase"
8 | "go.knocknote.io/eevee/plural"
9 | )
10 |
11 | type Name string
12 |
13 | type specialCase struct {
14 | lower string
15 | upper string
16 | startPattern *regexp.Regexp
17 | midPattern *regexp.Regexp
18 | endPattern *regexp.Regexp
19 | }
20 |
21 | var (
22 | specialCases = []*specialCase{
23 | {lower: "id", upper: "ID"},
24 | {lower: "url", upper: "URL"},
25 | {lower: "os", upper: "OS"},
26 | }
27 | )
28 |
29 | func init() {
30 | for _, sc := range specialCases {
31 | sc.startPattern = regexp.MustCompile(fmt.Sprintf(`^%s_`, sc.lower))
32 | sc.midPattern = regexp.MustCompile(fmt.Sprintf(`_%s_`, sc.lower))
33 | sc.endPattern = regexp.MustCompile(fmt.Sprintf(`_%s([0-9]?)s?$`, sc.lower))
34 | }
35 | }
36 |
37 | func matchedSpecialCase(s string) *specialCase {
38 | for _, sc := range specialCases {
39 | if sc.lower == s {
40 | return sc
41 | }
42 | }
43 | return nil
44 | }
45 |
46 | func matchedPluralSpecialCase(s string) *specialCase {
47 | for _, sc := range specialCases {
48 | if sc.lower+"s" == s {
49 | return sc
50 | }
51 | }
52 | return nil
53 | }
54 |
55 | func (n Name) normalize(name string) string {
56 | s := name
57 | for _, sc := range specialCases {
58 | s = sc.startPattern.ReplaceAllString(s, fmt.Sprintf(`^%s_`, sc.upper))
59 | s = sc.midPattern.ReplaceAllString(s, fmt.Sprintf(`_%s_`, sc.upper))
60 | s = sc.endPattern.ReplaceAllString(s, fmt.Sprintf(`%s$1`, sc.upper))
61 | }
62 | return s
63 | }
64 |
65 | func (n Name) normalizePlural(name string) string {
66 | s := name
67 | for _, sc := range specialCases {
68 | s = sc.startPattern.ReplaceAllString(s, fmt.Sprintf(`^%s_`, sc.upper))
69 | s = sc.midPattern.ReplaceAllString(s, fmt.Sprintf(`_%s_`, sc.upper))
70 | s = sc.endPattern.ReplaceAllString(s, fmt.Sprintf(`%s${1}s`, sc.upper))
71 | }
72 | return s
73 | }
74 |
75 | func (n Name) CamelName() string {
76 | sc := matchedSpecialCase(string(n))
77 | if sc != nil {
78 | return sc.upper
79 | }
80 | return strcase.ToCamel(n.normalize(string(n)))
81 | }
82 |
83 | func (n Name) PluralCamelName() string {
84 | name := plural.Plural(string(n))
85 | sc := matchedPluralSpecialCase(string(name))
86 | if sc != nil {
87 | return sc.upper + "s"
88 | }
89 | return strcase.ToCamel(n.normalizePlural(string(name)))
90 | }
91 |
92 | func (n Name) CamelLowerName() string {
93 | return strcase.ToLowerCamel(n.normalize(string(n)))
94 | }
95 |
96 | func (n Name) PluralCamelLowerName() string {
97 | return strcase.ToLowerCamel(n.normalizePlural(plural.Plural(string(n))))
98 | }
99 |
100 | func (n Name) SnakeName() string {
101 | return strcase.ToSnake(string(n))
102 | }
103 |
104 | func (n Name) PluralSnakeName() string {
105 | return strcase.ToSnake(plural.Plural(string(n)))
106 | }
107 |
--------------------------------------------------------------------------------