A web framework written in GO on-top of echo
to ease your application development. Our main goal is not to compete with other Go
framework instead we are mainly focusing on tooling
and structuring
a project to make developers life a bit easier and less stressful to maintain their project more in a lean way.
- BEAN (豆)
- Additional Features
- Install the package by
go install github.com/retail-ai-inc/bean/v2/cmd/bean@latest
- Create a project directory
mkdir myproject && cd myproject
- Initialize the project using bean by
bean init myproject
or
bean init github.com/me/myproject
The above command will produce a nice directory structure with all necessary configuration files and code to start your project quickly. Now, let's build your project and start:
make build
./myproject start
bean.mp4
Bean is using service repository pattern for any database, file or external transaction. The repository
provides a collection of interfaces to access data stored in a database, file system or external service. Data is returned in the form of structs
or interface
. The main idea to use Repository Pattern
is to create a bridge between models and handlers. Here is a simple pictorial map to understand the service-repository pattern in a simple manner:
bean create repo login
bean create repo logout
Above two commands will create 2 repository files under repositories
folder as login.go
and logout.go
.
Now let's associate the above repository files with a service called auth
:
bean create service auth --repo login --repo logout
Above command will create a pre-defined sample service file under services
folder as auth.go
and automatically set the type authService struct
and func NewAuthService
.
Now you can run make build
or make build-slim
to compile your newly created service with repositories.
bean create service auth --repo login --repo profile,logout
OR
bean create service auth -r login -r profile,logout
Above command will create both service repository files if it doesn't exist and automatically set the association.
bean create handler auth
Above command will create a pre-defined sample handler file under handlers
folder as auth.go
. Furthermore, if you already create an auth
service with same name as auth
then bean will automatically associate your handler with the auth service in route.go
.
Bean supporting 2 build commands:
make build
- This is usual go build command.make build-slim
- This will create a slim down version of your binary by turning off the DWARF debugging information and Go symbol table. Furthemore, this will exclude file system paths from the resulting binary using-trimpath
.
Bean has a pre-builtin logging system. If you open the env.json
file from your project directory then you should see some configuration like below:
"accessLog": {
"on": true,
"bodyDump": true,
"path": "",
"bodyDumpMaskParam": []
}
on
- Turn on/off the logging system. Default istrue
.bodyDump
- Log the request-response body in the log file. This is helpful for debugging purpose. Defaulttrue
path
- Set the log file path. You can set likelogs/console.log
. Empty log path allow bean to log intostdout
bodyDumpMaskParam
- For security purpose if you don't wannabodyDump
some sensetive request parameter then you can add those as a string into the slice like["password", "secret"]
. Default is empty.
The logger in bean is an instance of log.Logger interface from the github.com/labstack/gommon/log
package [compatible with the standard log.Logger interface], there are multiple levels of logging such as Debug
, Info
, Warn
, Error
and to customize the formatting of the log messages. The logger also supports like Debugf
, Infof
, Warnf
, Errorf
, Debugj
, Infoj
, Warnj
, Errorj
.
The logger can be used in any of the layers handler
, service
, repository
.
Example:-
log.Logger().Debugf("This is a debug message for request %s", c.Request().URL.Path)
Bean provides a built-in testing framework to test your project. To run the test, you need to run the following command from your project directory like below:
bean test ./... -output=html -output-file=./your/proejct/report
If you want to know more about the testing command then you can run bean test --help
from your project directory.
With helper functions undertest
package, you can easily test your project. The test
package provides the following helper functions:-
-
SetupConfig
- This function will setup the config for your test. You can pass theenv.json
file path as a parameter. It will read config undertest
tag from theenv.json
file and set the configTestConfig
for your test so that you can use the config in your test easily. -
SetSeverity
- This function will set different severity levels for different tests so that you can make a result report of your testing more organized; you can see aggregated results of your tests based on the severity level either in JSON or HTML format. -
other util functions - These contains some helper functions like
SkipTestIfInSkipList
(that is supposed to be used along withTestConfig
) to make your testing easier.
A project built with bean also provides the following executable commands alongside the start
command :-
- gen secret
- aes:encrypt/aes:decrypt
- route list
In env.json
file bean is maintaining a key called secret
. This is a 32 character long random alphanumeric string. It's a multi purpose hash key or salt which you can use in your project to generate JWT, one way hash password, encrypt some private data or session. By default, bean
is providing a secret however, you can generate a new one by entering the following command from your terminal:
./myproject gen secret
This command has two subcommands encrypt and decrypt used for encrypting and decrypting files using the AES encryption algorithm.
AES encryption is a symmetric encryption technique and it requires the use of a password to crypt the data, bean uses the password secret
in env.json
as the default password which is created when initializing the project. If you want to use a different password you can use gen secret
command to update the key.
For encrypting data
./myproject aes:encrypt <string_to_encypt>
For decrypting data
./myproject aes:decrypt <string_to_decypt>
This command enables us to list the routes that the web server is currently serving alongside the correspoding methods and handler functions supporting them.
./myproject route list
After initializing your project using bean
you should able to see a directory like commands/gopher/
. Inside this directory there is a file called gopher.go
. This file represents the command as below:
./myproject gopher
Usually you don't need to modify gopher.go
file. Now, let's create a new command file as commands/gopher/helloworld.go
and paste the following codes:
package gopher
import (
"errors"
"fmt"
"github.com/retail-ai-inc/bean/v2"
"github.com/retail-ai-inc/bean/v2/trace"
"github.com/spf13/cobra"
)
func init() {
cmd := &cobra.Command{
Use: "helloworld",
Short: "Hello world!",
Long: `This command will just print hello world otherwise hello mars`,
RunE: func(cmd *cobra.Command, args []string) error {
NewHellowWorld()
err := helloWorld("hello")
if err != nil {
// If you turn on `sentry` via env.json then the error will be captured by sentry otherwise ignore.
trace.SentryCaptureException(cmd.Context(), err)
}
return err
},
}
GopherCmd.AddCommand(cmd)
}
func NewHellowWorld() {
// IMPORTANT: If you pass `false` then database connection will not be initialized.
_ = initBean(false)
}
func helloWorld(h string) error {
if h == "hello" {
fmt.Println("hellow world")
return nil
}
return errors.New("hello mars")
}
Now, compile your project and run the command as ./myproject gopher helloworld
. The command will just print the hellow world
.
Bean
supports a memory-efficient local K/V store. To configure it, you need to activate it from your database
parameter in env.json like below:
"memory": {
"on": true,
"delKeyAPI": {
"endPoint": "/memory/key/:key",
"authBearerToken": "<set_any_token_string_of_your_choice>"
}
}
How to use in the code:
import "github.com/retail-ai-inc/bean/v2/store/memory"
// Initialize the local memory store with key type `string` and value type `any`
m := memory.NewMemory()
// The third parameter is the `ttl`. O means forever.
m.SetMemory("Hello", "World", 0)
data, found := m.GetMemory("Hello")
if !found {
// Do something
}
m.DelMemory("Hello")
The delKeyAPI
parameter will help you proactively delete your local cache if you cache something from your database like SQL or NOSQL. For example, suppose you cache some access token in your local memory, which resides in your database, to avoid too many connections with your database. In that case, if your access token gets changed from the database, you can trigger the delKeyAPI
endpoint with the key and Bearer <authBearerToken>
as the header parameter then bean
will delete the key from the local cache. Here, you must be careful if you run the bean
application in a k8s
container because then you have to trigger the delKeyAPI
for all your pods separately by IP address from k8s
.
Please refer to the helpers
package in this codebase or go doc for more information.
Bean provides the config.Config
struct to enable the user to tweak the configuration of their consumer project as per their requirement .
Bean configs default values are picked from the env.json
file, but can be updated during runtime as well.
https://pkg.go.dev/github.com/retail-ai-inc/bean#Config
config.Config
Some of the configurable parameters are:
-
Environment
: represents the environment in which the project is running (e.g. development, production, etc.) -
DebugLogPath
: represents the path of the debug log file. -
Secret
: represents a secret string key used for encryption and decryption in the project. Example Usecase:- while encoding/decoding JWTs. -
HTTP
: represents a custom wrapper to deal with HTTP/HTTPS requests. The wrapper provides by default some common features but also some exclusive features like:--
BodyLimit
: Sets the maximum allowed size for a request body, return413 - Request Entity Too Large
if the size exceeds the limit. -
IsHttpsRedirect
: A boolean that represents whether to redirect HTTP requests to HTTPS or not. -
KeepAlive
: A boolean that represents whether to keep the HTTP connection alive or not. -
AllowedMethod
: A slice of strings that represents the allowed HTTP methods. Example:-["DELETE","GET","POST","PUT"]
-
SSL
: used when web server uses HTTPS for communication. The SSL struct contains the following parameters:--
On
: A boolean that represents whether SSL is enabled or not. -
CertFile
: represents the path of the certificate file. -
PrivFile
: represents the path of the private key file. -
MinTLSVersion
: represents the minimum TLS version required.
-
-
-
Prometheus
: represents the configuration for the Prometheus metrics. The Prometheus struct contains the following parameters:--
On
: A boolean that represents whether Prometheus is enabled or not. -
SkipEndpoints
: represents the endpoints/paths to skip from Prometheus metrics. -
Subsystem
: represents the subsystem name for the Prometheus metrics. The default value isecho
if empty.
-
The TenantAlterDbHostParam
is helful in multitenant scenarios when we need to run some
cloudfunction or cron and you cannot connect your memorystore/SQL/mongo server from
cloudfunction/VM using the usual host
ip.
bean.TenantAlterDbHostParam = "gcpHost"
A CRUD project that you can refer to understand how bean works with service repository pattern. https://github.com/RohitChaurasia97/movie_tracker