GoatCLI
O czym będzie mowa?
GoatCLI
GoatCore
GoatCMS
Czym jest GoatCLI?
Prosta aplikacja
git clone https://github.com/goatcms/emptyapp
cd $GOPATH/src/github.com/goatcms
git clone https://github.com/goatcms/emptyapp.git
cd emptyapp
goatcli build
go build ./main.go
./main run --loglvl=dev
Architektura
DANE (tłumaczenia, opis struktur, …)
GoatCLI
Kod (Twój projekt)
Szablony (opis budowania)
GoatCLI
Twoja aplikacja
Moduły
DANE
Definicja budowania
Szablony budowania
Opis pobierania danych
Opis pobierania haseł
Definicja budowania
Szablony budowania
Więcej modułów
Definicja budowania
Szablony budowania
Więcej modułów
KOD
Repozytorium
CACHE
Moduł/Projekt
Definicja budowania
Szablony budowania
Opis pobierania danych
Opis pobierania haseł
Opis pobierania parametrów
Dane prywatne (hasła, …)
Parametry
Dane
/.goat/build/template/<name>/…/*.tmpl
/.goat/build.def.json
/.goat/build/<type>/<name>.json
/.goat/data.def.json
/.goat/secrets.def.json
/.goat/properties.def.json
/.goat/secrets.json (.gitignore)
/.goat/properties.json
Properties
.goat/properties.def.json
[{
"prompt":"Insert application userfriendly name",
"key":"app.name",
"type":"line",
"min":1,
"max":50
}, {
"prompt":"Insert application default web port",
"key":"app.port",
"type":"numeric",
"min":1,
"max":4
}, …
]
.goat/properties.json
{
"app": {
"id": "goatapp",
"lang": {
"default": "en"
},
"name": "GoatApp",
"port": "5555"
},
"goatcms_package": "github.com/goatcms/emptyapp/modules/goatcms"
}
Secrets
.goat/secrets.def.json
[{
"prompt":"Insert SMTP address (like smtp.gmail.com:465)",
"key":"smtp.address",
"type":"line",
"min":1,
"max":1024,
"pattern": "^[a-zA-Z0-9]+[a-zA-Z0-9\\.]*[a-zA-Z0-9]+(:[0-9]+)?$"
},{
"prompt":"Insert SMTP username",
"key":"smtp.user",
"type":"line",
"min":1,
"max":1024,
"pattern": "^[a-zA-Z0-9_\\.\\@]+?$"
}, …
]
Data
.goat/data.def.json
[{
"type":"model",
"properties":[{
"prompt":"insert single entity name",
"key":"entity",
"type":"line",
"min":1,
"max":30,
"pattern": "^[a-zA-z]+[a-zA-Z0-9]*$"
}, … ]
}, … ]
.goat/data.def.json
[{
"type":"lang",
"collections":[{
"type": "map",
"prompt": "Insert translates",
"properties": [{
"prompt":"Insert translate",
"key":"text",
"type":"line",
"min":1,
"max":1024
}]
}]
}, … ]
Build
.goat/build.def.json
[{
"to":"config",
"template":"config",
},{
"to":"translates",
"template":"translates",
},{
"to":"templates/views/admin",
"template":"admin/views",
},{
"to":"templates/helpers/forms",
"template":"form/view",
}]
.goat/build/
.goat/build/templates/admin/views/main.tmpl
{{- $ctx := . -}}
{{- range $index, $key := (keys .Data "model.") -}}
{{- $path := (print $ctx.To "/model/" $key "/list/main.gohtml") -}}
{{- if not ($ctx.Filesystem.IsFile $path) -}}
{{- $ctx.Out.File $path -}}
{{- template "admin.views.model.list" (ctx $ctx (print "model." $key) "") -}}
{{- $ctx.Out.EOF -}}
{{- end -}}
{{- end -}}
.../model/list.gohtml.tmpl
{{- define "admin.views.model.list" -}}
{{- $ctx := . -}}
{{- /* ... */ -}}
{{- noescape "{{- define \"content\" -}}" }}
<h1>{{$entityName}}</h1>
<div class="top-nav">
{{- $hrefAttr := (print "href=\"/admin/" (lower $entityName) "/insert\"") }}
<a type="button" class="btn btn-primary" {{$hrefAttr|safeHTMLAttr}}>
{{noescape "{{" }} TranslateFor "insert_btn" $prefix }}</a>
</a>
</div>
{{ noescape "{{- end }}" }}
{{- end -}}
Modules
.goat/modules.def.json
[{
"srcClone": "https://github.com/goatcms/goatcms.git",
"srcDir": "modules/goatcms",
}]
(goatcms)/.goat/replaces.def.json
[{
"from": "github.com/goatcms/goatcms",
"to": "{{goatcms_package}}",
"pattern": ".*\.go",
}]
GoatCMS
GoatCMS
CustomApp
GoatCore
dao
entities
http
commands
controllers
services
cmsapp
GoatCMS - Entities
user.go
type User struct {
ID *int64 `json:"id"`
Firstname *string `json:"firstname" db:"Firstname"`
Lastname *string `json:"lastname" db:"Lastname"`
Email *string `json:"email" db:"Email"`
Password *string `json:"password" db:"Password"`
Roles *string `json:"roles" db:"Roles"`
Username *string `json:"username" db:"Username"`
}
User.java
package com.goatcms.goatforandroid.entities;
public class User {
public Long id;
public String firstname;
public String lastname;
public String email;
public String password;
public String roles;
public String username;
public User() {}
}
user.go
var UserSystemFieldsAndID = &UserFields{
ID: true,
Firstname: false,
Lastname: false,
Email: false,
Password: true,
Roles: true,
Username: false,
}
type UserFields struct {
ID bool
Firstname bool
Lastname bool
Email bool
Password bool
Roles bool
Username bool
}
user_json.go
package entities
import (
"fmt"
"github.com/buger/jsonparser"
"github.com/goatcms/goatcore/varutil"
"strconv"
"strings"
)
func UserFromJSON(e *User, json []byte, fields *UserFields) (err error) {
return jsonparser.ObjectEach(json, func(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error {
//…
})
}
GoatCMS - DAO
user.go
type UserCriteriaWhere struct {
Firstname *StringFieldCriteria
Lastname *StringFieldCriteria
Email *StringFieldCriteria
Password *StringFieldCriteria
Roles *StringFieldCriteria
Username *StringFieldCriteria
}
type UserCriteriaRelated struct {
}
type UserCriteria struct {
Fields *entities.UserFields
Where UserCriteriaWhere
Related UserCriteriaRelated
Order UserCriteriaOrder
}
user.go
type UserCriteriaSearch interface {
Find(scope app.Scope, criteria *UserCriteria, pager *Pager) (rows UserRows, err error)
}
type UserCriteriaDeleter interface {
Delete(scope app.Scope, criteria *UserCriteria) (err error)
}
type UserCriteriaCounter interface {
Count(scope app.Scope, criteria *UserCriteria) (count int64, err error)
}
GoatCMS - Tłumaczenia
translates/pl/layout.json
{"pl.layout":{
"footer": "GoatCMS",
"head_title": "GoatCMS",
"navbar": {
"home": "GoatCMS",
"signin": "Logowanie",
"signout": "Wylogowanie",
"signup": "Rejestracja"
}
}}
.../res/bundles/home/values-pl/strings.xml
<resources>
<string name="home_nav_admin_fragment">FRAGMENT (ADMIN)</string>
<string name="home_nav_admin_session">SESSION (ADMIN)</string>
<string name="home_nav_admin_user">USER (ADMIN)</string>
</resources>
Dziękuję za uwagę
Linki