goald

package module
v0.0.0-...-edf6d9c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 16, 2024 License: MIT Imports: 25 Imported by: 0

README

Goald

Code-first, model-driven opiniated backend framework to cleanly CRUD business objects in a snap, with automatic generation of reflect-free code to have more time to spend on smart stuff (phew!).

Will soon be documented (with VuePress or SveltePress).

Content

The Go code at the root of this project is the core of Goald. Additional features can be found... well, in features.

License

MIT

Documentation

Overview

------------------------------------------------------------------------------------------------ The code here is about describing the business objects through "classes" ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Here are the enums used for building business object classes ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Some utilities to help build classes ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Here is the common code for writing business objects ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ The code here is about how we productively load whole data tree of business objects ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ The code here is about how we describe endpoints ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Out-of-the-box endpoints to quickly have SCRUD working with Business Objects ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ The code here is about registering globally accessible objects. ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Here is the starting point of any Goald app: the initialisation of a server ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Here we configure the the server ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Here are defined the contexts passed in the different layers of our multi-tier architecture: - (no context) for the business object layer (*__.go files) - BloContext for the Business LOgic code (used in *__blo.go files) - DaoContext for the Data Access Objects (used in *__dao.go files) - WebContext for the web endpoints code (used in *__web.go files) ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ The code here is about the loading of data for the server to work properly. Data loaders - which are functions with the same signature - must be registered through a function defined here. Beware: data loaders can be invoked in parallel, so there should not be any dependency between them. If you have some logic about several data loading bits, you must implement it within one data loader. ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Here are the enums used for building business object classes ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ This is about handling HTTP requests ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Defining here all the information ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Here is the global code generation routine ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Here is the code used for generating the DB list ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Here is the code used to generate the "includes", which are utils packages that we should import when we want to be able to use the corresponding applicative packages ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Here is the code used for generating the class files ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Here is the code used for generating the BO models in the web app ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Here is the code used for generating the VMAP (value mapper) files ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ The code here is about checking that the devs haven't forgotten some stuff, like telling each relationship's type, some properties' size, if a class is persisted or not, etc. ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Here we implement the generic data access instructions involved in CRUD N.B. quick & dirty implems for now ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Here we implement the generic business logic involved in CRUD N.B. quick & dirty implems for now ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Here is provided a general way of doing HTTP request to external data providers ------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------ Here we implement some generic request handlers involved in CRUD N.B. quick & dirty implems for now ------------------------------------------------------------------------------------------------

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CreateBO

func CreateBO(bloCtx BloContext, bObj IBusinessObject) error

Controls, DB-inserts, post-treats the given BO TODO - quick & dirty implem for now func CreateBO[BOTYPE IBusinessObject](bloCtx BloContext, bObj *BOTYPE) error {

func DeleteOne

func DeleteOne[ResourceType IBusinessObject](
	handlerFunc func(webCtx WebContext) (ResourceType, hstatus.Code, string),
) *oneForNoneEndpoint[ResourceType]

Declaring an endpoint to delete 1 BO instance with a DELETE request

func Error

func Error(msg string, params ...interface{}) error

func ErrorC

func ErrorC(cause error, msg string, params ...interface{}) error

func GenericHandleCreate

func GenericHandleCreate[BOTYPE IBusinessObject]() *oneForOneEndpoint[BOTYPE, BOTYPE]

func GenericHandleDelete

func GenericHandleDelete[BOTYPE IBusinessObject](idProp IField) *oneForNoneEndpoint[BOTYPE]

func GenericHandleRead

func GenericHandleRead[BOTYPE IBusinessObject](idProp IField, loadingType LoadingType) *oneForNoneEndpoint[BOTYPE]

func GenericHandleUpdate

func GenericHandleUpdate[BOTYPE IBusinessObject](loadingType LoadingType) *oneForOneEndpoint[BOTYPE, BOTYPE]

func GetMany

func GetMany[ResourceType IBusinessObject](
	handlerFunc func(webCtx WebContext) ([]ResourceType, hstatus.Code, string),
	loadingType LoadingType,
) *manyForNoneEndpoint[ResourceType]

Declaring an endpoint to return N BO instances from a GET request

func GetManyWithParams

func GetManyWithParams[ResourceType IBusinessObject, QueryParamsType IURLQueryParams](
	handlerFunc func(webCtx WebContext, queryParams QueryParamsType) ([]ResourceType, hstatus.Code, string),
	loadingType LoadingType,
) *manyForOneEndpoint[QueryParamsType, ResourceType]

Declaring an endpoint to return N BO instance from query parameters that are described with 1 URLQueryParams

func GetOne

func GetOne[ResourceType IBusinessObject](
	handlerFunc func(webCtx WebContext) (ResourceType, hstatus.Code, string),
	loadingType LoadingType,
) *oneForNoneEndpoint[ResourceType]

Declaring an endpoint to return 1 BO instance from a GET request

func HandleGetAll

func HandleGetAll[ResourceType IBusinessObject](webCtx WebContext) ([]ResourceType, hstatus.Code, string)

Simply listing the resources of a targeted type

func HttpGet

func HttpGet[ResponseType any](url string, responseObj *ResponseType) *externalHttpRequest[ResponseType]

func HttpPost

func HttpPost[ResponseType any](url string, responseObj *ResponseType) *externalHttpRequest[ResponseType]

func HttpPut

func HttpPut[ResponseType any](url string, responseObj *ResponseType) *externalHttpRequest[ResponseType]

func In

func In(module moduleName) *moduleClassUtilsRegitry

allows to declare a new module where to register ClassUtils

func LoadBOs

func LoadBOs[ResourceType IBusinessObject](bloCtx BloContext, boClass IBusinessObjectClass, loadingType LoadingType) ([]ResourceType, error)

func NewCommonConfig

func NewCommonConfig() *serverConfig

func PostManyGetMany

func PostManyGetMany[InputType, ResourceType IBusinessObject](
	handlerFunc func(webCtx WebContext, input []InputType) ([]ResourceType, hstatus.Code, string),
	loadingType LoadingType,
) *manyForManyEndpoint[InputType, ResourceType]

Declaring an endpoint to return N BO instance from N POSTed BO instances

func PostOneGetOne

func PostOneGetOne[InputType, ResourceType IBusinessObject](
	handlerFunc func(webCtx WebContext, input InputType) (ResourceType, hstatus.Code, string),
	loadingType LoadingType,
) *oneForOneEndpoint[InputType, ResourceType]

Declaring an endpoint to return 1 BO instance from 1 POSTed BO instance

func PutOne

func PutOne[InputType, ResourceType IBusinessObject](
	handlerFunc func(webCtx WebContext, input ResourceType) (ResourceType, hstatus.Code, string),
	loadingType LoadingType,
) *oneForOneEndpoint[ResourceType, ResourceType]

Declaring an endpoint to return 1 BO instance from 1 PUT BO instance

func RecoverError

func RecoverError(msg string, params ...interface{})

func RegisterClass

func RegisterClass(name className, class IBusinessObjectClass)

registering happens in the "class" package, gence the public function

func RegisterConfig

func RegisterConfig(cfgObj IServerConfig)

func RegisterDataLoader

func RegisterDataLoader(fn dataLoader, migrationPhase bool)

func UpdateBO

func UpdateBO(bloCtx BloContext, input IBusinessObject, loadingType LoadingType) error

Types

type AppContext

type AppContext interface {
	CustomConfig() ICustomConfig // returns the app's custom part of the config
}

------------------------------------------------------------------------------------------------ AppContext contains the minimal info set that should be accessible in all the layers of the app ------------------------------------------------------------------------------------------------

type BObjID

type BObjID int64 // probably a UUID here

type BObjID string // probably a UUID here

type BigIntField

type BigIntField struct {
	// contains filtered or unexported fields
}

func NewBigIntField

func NewBigIntField(owner IBusinessObjectClass, name string, multiple bool) *BigIntField

func (*BigIntField) Max

func (f *BigIntField) Max(max int64) *BigIntField

func (*BigIntField) Min

func (f *BigIntField) Min(min int64) *BigIntField

type BloContext

type BloContext interface {
	GetDaoContext() DaoContext
	// contains filtered or unexported methods
}

------------------------------------------------------------------------------------------------ BloContext is a context that should provide the necessary info for Business LOgic code

type BoolField

type BoolField struct {
	// contains filtered or unexported fields
}

func NewBoolField

func NewBoolField(owner IBusinessObjectClass, name string, multiple bool) *BoolField

func (*BoolField) SetDefaultValue

func (f *BoolField) SetDefaultValue(val string) *field

func (*BoolField) SetMandatory

func (f *BoolField) SetMandatory() *field

func (*BoolField) SetNotPersisted

func (f *BoolField) SetNotPersisted() *field

type BusinessObject

type BusinessObject struct {
	ID BObjID `json:",omitempty"`
	// contains filtered or unexported fields
}

func InstanceOf

func InstanceOf(class IBusinessObjectClass) BusinessObject

func (*BusinessObject) ChangeAfterInsert

func (thisBO *BusinessObject) ChangeAfterInsert(BloContext) error

func (*BusinessObject) ChangeBeforeInsert

func (thisBO *BusinessObject) ChangeBeforeInsert(BloContext) error

func (*BusinessObject) Class

func (thisBO *BusinessObject) Class() IBusinessObjectClass

func (*BusinessObject) GetID

func (thisBO *BusinessObject) GetID() BObjID

func (*BusinessObject) IsValid

func (thisBO *BusinessObject) IsValid(BloContext) error

func (*BusinessObject) Load

func (thisBO *BusinessObject) Load(loadingType LoadingType, with ...*LoadingScenario) *LoadingScenario

type DB

type DB struct {
	*sql.DB
	// contains filtered or unexported fields
}

goald's own DB object

func GetDB

func GetDB(dbID DatabaseID) *DB

func (*DB) Exec

func (thisDB *DB) Exec(query string, args ...any) (sql.Result, error)

proxying this function so as to add functionality

func (*DB) FetchStringColumn

func (thisDB *DB) FetchStringColumn(query string, args ...interface{}) (results []string, err error)

Executes a query that should only return an array of string (1 column)

func (*DB) Query

func (thisDB *DB) Query(query string, args ...any) (*sql.Rows, error)

proxying this function so as to add functionality

type DaoContext

type DaoContext interface {
	// contains filtered or unexported methods
}

------------------------------------------------------------------------------------------------ DaoContext should contain the necessary info for handling database access

type DatabaseID

type DatabaseID string

type DateField

type DateField struct {
	// contains filtered or unexported fields
}

func NewDateField

func NewDateField(owner IBusinessObjectClass, name string, multiple bool) *DateField

func (*DateField) SetDefaultValue

func (f *DateField) SetDefaultValue(val string) *field

func (*DateField) SetMandatory

func (f *DateField) SetMandatory() *field

func (*DateField) SetNotPersisted

func (f *DateField) SetNotPersisted() *field

type DoubleField

type DoubleField struct {
	// contains filtered or unexported fields
}

func NewDoubleField

func NewDoubleField(owner IBusinessObjectClass, name string, multiple bool) *DoubleField

func (*DoubleField) Max

func (f *DoubleField) Max(max float64) *DoubleField

func (*DoubleField) Min

func (f *DoubleField) Min(min float64) *DoubleField

type EnumField

type EnumField struct {
	// contains filtered or unexported fields
}

func NewEnumField

func NewEnumField(owner IBusinessObjectClass, name string, multiple bool, enumName string) *EnumField

func (*EnumField) Only

func (f *EnumField) Only(values ...IEnum) *EnumField

func (*EnumField) SetDefaultValue

func (f *EnumField) SetDefaultValue(val string) *field

func (*EnumField) SetMandatory

func (f *EnumField) SetMandatory() *field

func (*EnumField) SetNotPersisted

func (f *EnumField) SetNotPersisted() *field

type IBusinessObject

type IBusinessObject interface {
	// identification
	Class() IBusinessObjectClass

	GetID() BObjID

	// business logic
	ChangeBeforeInsert(BloContext) error
	IsValid(BloContext) error
	ChangeAfterInsert(BloContext) error
	// contains filtered or unexported methods
}

func DeleteBO

func DeleteBO(bloCtx BloContext, idProp IField, idPropVal string) (IBusinessObject, error)

func ReadBO

func ReadBO(bloCtx BloContext, idProp IField, idPropVal string, loadingType LoadingType) (IBusinessObject, error)

type IBusinessObjectClass

type IBusinessObjectClass interface {
	SetNotPersisted() // to indicate this class has no instance persisted in a database
	SetInDB(db *DB)   // to associate the class with the DB where its instances are stored
	SetAbstract()     // to indicate this class does not model concrete business objects, but most probably a super class

	// access to generic properties (fields & relationships)
	ID() IField
	// contains filtered or unexported methods
}

------------------------------------------------------------------------------------------------ Business object classes ------------------------------------------------------------------------------------------------

func NewClass

func NewClass() IBusinessObjectClass

type IClassUtils

type IClassUtils interface {
	IClassUtilsCore
	NewObject() any // a function to instantiate 1 BO corresponding to this entry
	NewSlice() any  // a function to instantiate an empty slice of BOs corresponding to this entry
}

A ClassUtils is an object associated with a specific Business Object type that provides automatically genrated utility methods to: - instantiate 1 or a slice of this BO type - help serializing / deserializing instances of this BO type - quickly perform ORM operations such as Insert(), Select(), Update(), Delete(), etc... - ...by containing methods such as GetSelectAllQuery(), GetInsertQuery(), etc

Each ClassUtils is loosely coupled to the corresponding BO type through a registry, using the BO class as key.

type IClassUtilsCore

type IClassUtilsCore interface {
	GetValueAsString(IBusinessObject, string) string        // returning a BO's field's value, given the field's name
	SetValueAsString(IBusinessObject, string, string) error // setting a BO's field's value, given the field's name
	// contains filtered or unexported methods
}

A ClassUtils core is a set of information fields that are common to all the Class Utils objects.

func NewClassUtilsCore

func NewClassUtilsCore(srcPath, lastModification string) IClassUtilsCore

type ICommonConfig

type ICommonConfig interface {
	// contains filtered or unexported methods
}

type ICustomConfig

type ICustomConfig interface {
}

type IEnum

type IEnum interface {
	fmt.Stringer // each enum value has a default label
	Val() int
	Values() map[int]string
}

IEnum must be implemented by every enum type

type IExternalHttpRequest

type IExternalHttpRequest interface {
	WithData(dataObj any) IExternalHttpRequest
	WithTimeout(timeout time.Duration) IExternalHttpRequest
	WithBasicAuth(user, pass string) IExternalHttpRequest
	WithHeader(key, value string) IExternalHttpRequest
}

interface & general methods

type IField

type IField interface {
	// contains filtered or unexported methods
}

type IServerConfig

type IServerConfig interface {
	ICommonConfig
	CustomConfig() ICustomConfig // the applicative, custom part of the config
}

type IURLQueryParams

type IURLQueryParams interface {
	IBusinessObject
}

particular business object

type IURLQueryParamsClass

type IURLQueryParamsClass interface {
	IBusinessObjectClass
}

particular business object class

func NewURLQueryParamsClass

func NewURLQueryParamsClass() IURLQueryParamsClass

type IntField

type IntField struct {
	// contains filtered or unexported fields
}

func NewIntField

func NewIntField(owner IBusinessObjectClass, name string, multiple bool) *IntField

func (*IntField) Max

func (f *IntField) Max(max int) *IntField

func (*IntField) Min

func (f *IntField) Min(min int) *IntField

type LoadingScenario

type LoadingScenario struct {
}

func With

func With(relationship *Relationship, with ...*LoadingScenario) *LoadingScenario

type LoadingType

type LoadingType string

A loading type is a key for an object that fully describe how to load business objects with their relationships; a class can define several loading types, used in various situations

type PropertyType

type PropertyType int

PropertyType represents the type of a business object's property

const (
	// PropertyTypeUNKNOWN : when the property type is not recognized
	PropertyTypeUNKNOWN PropertyType = iota - 1

	// PropertyTypeBOOL : for boolean properties
	PropertyTypeBOOL

	// PropertyTypeSTRING : for string properties
	PropertyTypeSTRING

	// PropertyTypeINT : for integer properties
	PropertyTypeINT

	// PropertyTypeINT64 : for integer properties
	PropertyTypeINT64

	// PropertyTypeREAL32 : for 32-bits real number properties
	PropertyTypeREAL32

	// PropertyTypeREAL64 : for 64-bits real number properties
	PropertyTypeREAL64

	// PropertyTypeDATE : for date properties
	PropertyTypeDATE

	// PropertyTypeENUM : for enum properties
	PropertyTypeENUM

	// PropertyTypeRELATIONSHIP : for relationships to other entities
	PropertyTypeRELATIONSHIP
)

func (PropertyType) String

func (thisProperty PropertyType) String() string

func (PropertyType) Val

func (thisProperty PropertyType) Val() int

Val helps implement the IEnum interface

func (PropertyType) Values

func (thisProperty PropertyType) Values() map[int]string

Values helps implement the IEnum interface

type RealField

type RealField struct {
	// contains filtered or unexported fields
}

func NewRealField

func NewRealField(owner IBusinessObjectClass, name string, multiple bool) *RealField

func (*RealField) Max

func (f *RealField) Max(max float32) *RealField

func (*RealField) Min

func (f *RealField) Min(min float32) *RealField

type Relationship

type Relationship struct {
	// contains filtered or unexported fields
}

func NewRelationship

func NewRelationship(owner IBusinessObjectClass, name string, multiple bool, target IBusinessObjectClass) *Relationship

Allows to declare a new relationship on a given class

func (*Relationship) SetChildToParent

func (r *Relationship) SetChildToParent(backRefRelation *Relationship) *Relationship

Sets a relationship as a "child to parent" one; the backref relationship is needed

func (*Relationship) SetOneWay

func (r *Relationship) SetOneWay() *Relationship

Sets a relationship as a "one way" one; is with no back ref

func (*Relationship) SetSourceToTarget

func (r *Relationship) SetSourceToTarget(backRefRelation *Relationship) *Relationship

Sets a relationship as a "parent to children" one; the backref relationship is needed

type ServerContext

type ServerContext interface {
	BloContext
	Start()
}

------------------------------------------------------------------------------------------------ ServerContext is a particular Business Logic Context used at app startup Implemented by the `server` struct

func NewServer

func NewServer() ServerContext

This function should be called in each Goald-based app

type StringField

type StringField struct {
	// contains filtered or unexported fields
}

func NewStringField

func NewStringField(owner IBusinessObjectClass, name string, multiple bool) *StringField

func (*StringField) SetDefaultValue

func (f *StringField) SetDefaultValue(val string) *field

func (*StringField) SetMandatory

func (f *StringField) SetMandatory() *field

func (*StringField) SetNotPersisted

func (f *StringField) SetNotPersisted() *field

func (*StringField) SetSize

func (sf *StringField) SetSize(size int) *field

type URLQueryParams

type URLQueryParams struct {
	BusinessObject
}

particular business object implem

type WebContext

type WebContext interface {
	GetBloContext() BloContext
	GetTargetRefOrID() string
	GetResourceClass() IBusinessObjectClass // the class of the resource being requested
	GetResourceLoadingType() LoadingType    // returns the loading type of the current main resources (BOs) being worked on
	// contains filtered or unexported methods
}

------------------------------------------------------------------------------------------------ WebContext provides the necessary info to applicatively handle incoming HTTP requests

Directories

Path Synopsis
_include
_class
Generated file, do not edit!
Generated file, do not edit!
i18n
Generated file, do not edit!
Generated file, do not edit!
features
hstatus
------------------------------------------------------------------------------------------------ This package is used to type the HTTP status codes, and allowing using them, rather than writing bare values like 200, 401, etc.
------------------------------------------------------------------------------------------------ This package is used to type the HTTP status codes, and allowing using them, rather than writing bare values like 200, 401, etc.
i18n
------------------------------------------------------------------------------------------------ Here, mainly about loading the translations at startup ------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------ Here, mainly about loading the translations at startup ------------------------------------------------------------------------------------------------
i18n/classutils
Generated file, do not edit!
Generated file, do not edit!
utils
------------------------------------------------------------------------------------------------ Ensuring we have a very limited use of the 'reflect' package.
------------------------------------------------------------------------------------------------ Ensuring we have a very limited use of the 'reflect' package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL