glew
is a (in development / unstable) rapid prototyping and development tool, used to create starter web boiler-plate projects with CRUD+ functionality. The goal is to be able to create a set of convention following models, feed it to glew, and have developer friendly flexible starter code ready produced. Its basically a glorified project template that makes some assumptions and 3rd party library choices to provide more functionality. It's designed to be a best practices basic starting point REST api generator.
The basic functionality out of the box:
- Complete golang runtime with an API.
- Complex multi app cli pattern boiler plate.
- Includes db creator + initializer wrapper.
- Includes functionality for dynamic api stack.
- Includes separate run cmd and server for flexible ops.
- API Basic error handling
- panic handling.
- hides internal errors.
- parses certain db errors(FK,Unique,Check) as 400 status code.
- Gzip, recovery, console logger middlewares are enabled.
- Basic status controller endpoint check.
- Exposes expvar endpoint.
- Includes 'internal' utilities useful for developing apps.
- Includes
drone.yml
initial build template. - Includes
docker-compose.yml
starter for local dev. - Includes alpine
nobody:nouser
, CA and TZ info,Dockerfile
starter for local dev. - Includes
.gitignore
and basicMakefile
for easy testing. - All code supports a tenant id and enforces this very explicitly.
- All apps configured through env variables.
For each model set provided a "feature" will be created. Each Feature has the following functionality:
- A CRUD controller
- Create, Read, List, Put, Patch, Delete
- All endpoints bind user input to data models.
- All endpoints validate user input.
- All endpoints have swagger documentation boiler plate text.
- List endpoint supports paging and dynamic query filtering.
- Delete and Patch endpoints supports multi model operations in a single transaction.
- Typed data store and interfaces.
- Basic db migration up/down of tables.
- Basic CRUD SQL statements.
- Utilities
- Model initializer.
- Model string trimmer.
- Inter model mapping.
- All code is tenant aware via simple tenantId.
- wanted to streamline creating applications with a batteries included approach (one in which I get to select the batteries), with batteries lighter ie more directly hackable/modifiable than something like goa or buffalo.
- reason to learn/experiment with
go/ast
,go/parser
,go/token
glew relies heavily on 3rd party libraries for abstracting code and is mostly glue code between the libraries. Most of the applications data specific functionality is driven by the struct via tags.
These are the primary dependencies and what they are responsible for:
Library | Handles |
---|---|
gin | base web framework |
validator | input validation |
sqlx | sql interface |
pgx | postgres driver |
rql | dynamic web queries |
swag | swagger generator |
migrate | db migration |
viper | configuration |
cobra | cli |
ladon | authorization |
authboss | authentication |
vue.js | base ui framework |
vue-router | ui router |
vee-validate | ui inline validation |
vuex | ui state store |
bulma | base css framework |
buefy | buefy + bulma components |
- No complex types - it currently just handles the basic stuff (go std types) and will begin to break when you go outside of that.
- Doesn't handle relationships - its just a "code printer". It knows basic things about fields and basic types (See #1) because thats easy. In a way it supports one to many parent -> child type relations by having a struct field that references another resource. Features should be loaded into the app generator with dependencies ordered first. This is simply because the database create scripts will need to be reordered otherwise. It doesn't do anything for many to many relationships and this is not planned.
./cmd
- the cmd package contains the wire up code for the cli../pkg/static
- base copy paste static templates. This is the dumb starter project static contents../pkg/templates
- this is the base templates for various code features. This is the core bootstrapper code thats being replaced../pkg
- this is where glews core library is.
The product of this application is a cli project folder with the following layout:
./
- all the dev tool (drone, go modules, configs and main.go./cmd
- the cli commands../cmd/cli/tools
- tools cli area../cmd/cli/apis
- for apis../db/migrations
- database migration scripts to be used withgo migrate
or{{.CLINAME}} all
or{{.CLINAME}} tools migrate
./core
- schema for your models and related operations./core_seed
- database seed insert script for quick testing.
./internal
- internal libraries and extension utilities for 3rd party libraries../pkg
- the applications relevant to the platform/apis
- all of the apis (core)
You can run glew in two ways, in code or as a cli.
touch models.go
git clone https://github.com/kartso/glew.git
go install
glew
type TestModel struct {
StringField string `db:"string_field" json:"stringField"`
NumField int `db:"num_field" json:"numField"`
ID int `db:"id" json:"id"`
Code string `db:"code" json:"code"`
TimeField time.Time `db:"time_field" json:"timeField"`
}
type CreateTestModel struct {
StringField string `db:"string_field" json:"stringField"`
NumField int `db:"num_field" json:"numField"`
ID int `db:"id" json:"id"`
Code string `db:"code" json:"code"`
TimeField time.Time `db:"time_field" json:"timeField"`
}
type UpdateTestModel struct {
StringField string `db:"string_field" json:"stringField"`
NumField int `db:"num_field" json:"numField"`
ID int `db:"id" json:"id"`
Code string `db:"code" json:"code"`
TimeField time.Time `db:"time_field" json:"timeField"`
}
func main() {
/*
CONFIG
destDir - the output directory from this run
appName - the name of the application and docker runtime
importPath - application go import directory, aka the directory of the app to reference itself
*/
app := pkg.NewApp(pkg.Frontend{}, pkg.Backend{}, pkg.DB{})
destDir := "out"
appName := "testApp"
importPath := "github.com/karsto/glew/out"
verticals := []pkg.VerticalMeta{}
vertical, _ := app.GenerateVerticalMeta(TestModel{}, "TestVertical", CreateTestModel{}, UpdateTestModel{})
verticals = append(verticals, vertical)
ctx := pkg.BaseAPPCTX{
ImportPath: importPath,
}
features := pkg.NewConfig()
files, _ := app.GenerateApp(features, destDir, appName, verticals, ctx)
err = pkg.WriteFiles(files, destDir)
if err != nil {
panic(err)
}
TODO:
- struct tags
- options