Hooks
Hooks are functions that execute before or after an operation on a resource.
A Hook can be a resource hook, database hook, or application hook, allowing you to add custom logic to your APIs and extend FastSchema's functionality.
Help us improve
The FastSchema hooks system is still in its early stages, and we're actively working on enhancing it. If you have feedback or suggestions, please let us know.
Most hooks have a similar signature:
// The context object that was passed to the action
context.Context
// Middleware is a function that can be used to add middleware to a resource
type Middleware func(c Context) error
type QueryOption struct {
Schema *schema.Schema `json:"schema"`
Limit uint `json:"limit"`
Offset uint `json:"offset"`
Columns []string `json:"columns"`
Order []string `json:"order"`
Predicates []*Predicate `json:"predicates"`
Query string `json:"query"`
Args any `json:"args"`
// For count query
Column string `json:"column"`
Unique bool `json:"unique"`
}OnPreResolve
func (a *App) OnPreResolve(middlewares ...fs.Middleware)The OnPreResolve hook is executed before the resource handler is called. It can be used to add custom logic before the resource handler is executed.
There are two possible behaviors for the OnPreResolve hook:
Return nilto continue with the normal flow.Return an errorto stop the execution and return the error to the client.
Example:
app, _ := fastschema.New(&fs.Config{
SystemSchemas: []any{Tag{}, Blog{}},
})
app.OnPreResolve(func(ctx fs.Context) error {
user := ctx.User()
resource := ctx.Resource()
if user == nil && resource.ID() == "api.user.me" {
return errors.Unauthenticated("You are not authenticated")
}
return nil
})
app.Start()OnPostResolve
func (a *App) OnPostResolve(middlewares ...fs.Middleware)The OnPostResolve hook is executed after the resource handler is called. It can be used to add custom logic after the resource handler is executed or to manipulate the response before it is sent to the client.
Example:
app, _ := fastschema.New(&fs.Config{
SystemSchemas: []any{Tag{}, Blog{}},
})
app.OnPostResolve(func(ctx fs.Context) error {
// We only want to modify the response of the "api.hello" resource
if ctx.Resource().ID() != "api.hello" {
return nil
}
// If there was an error, we don't want to modify the response
if ctx.Result().Error != nil {
return nil
}
// Modify the response from "Hello World" to "Modified response"
ctx.Result().Data = "Modified response"
// Or set the result to a new value
// ctx.Result(&fs.Result{ Data: "Modified response" })
return nil
})
app.API().Add(fs.Get("hello", func(ctx fs.Context, _ any) (any, error) {
return "Hello World", nil
}, &fs.Meta{Public: true}))
app.Start()OnPreDBQuery
type PreDBQuery = func(
ctx context.Context,
option *QueryOption,
) error
func (a *App) OnPreDBQuery(hooks ...db.PreDBQuery)The OnPreDBQuery hook is executed before the database Get, First, Only operations are performed.
It can be used to manipulate the query before it is executed.
OnPostDBQuery
type PostDBQuery = func(
ctx context.Context,
option *QueryOption,
entities []*schema.Entity,
) ([]*schema.Entity, error)
func (a *App) OnPostDBQuery(hooks ...db.PostDBGet)The OnPostDBQuery hook is executed after the database Get, First, Only operations is performed.
It can be used to manipulate the query result before it is returned to the client.
Example:
app, _ := fastschema.New(&fs.Config{
SystemSchemas: []any{Tag{}, Blog{}},
})
app.OnPostDBQuery(func(
ctx context.Context,
query *db.QueryOption,
entities []*schema.Entity,
) ([]*schema.Entity, error) {
if query.Model.Schema().Name != "file" {
return entities, nil
}
for _, entity := range entities {
path := entity.GetString("path")
if path != "" {
entity.Set("url", app.Disk().URL(path))
}
}
return entities, nil
})
app.Start()PreDBCreate
type PreDBCreate = func(
ctx context.Context,
schema *schema.Schema,
createData *schema.Entity,
) error
func (a *App) OnPreDBCreate(hooks ...db.PreDBCreate)The PreDBCreate hook is executed before the database Create operation is performed.
It can be used to manipulate the data before it is created.
schemais the schema of the entity.createDatais the data used to create the entity.
PostDBCreate
type PostDBCreate = func(
ctx context.Context,
schema *schema.Schema,
dataCreate *schema.Entity,
id uint64,
) error
func (a *App) OnPostDBCreate(hooks ...db.PostDBCreate)The PostDBCreate hook is executed after the database Create operation is performed.
It can be used to trigger additional actions after a new entity is created.
schemais the schema of the entity.idis the ID of the created entity.dataCreateis the data used to create the entity.
Example:
app, _ := fastschema.New(&fs.Config{
SystemSchemas: []any{Tag{}, Blog{}},
})
app.OnPostDBCreate(func(
ctx context.Context,
schema *schema.Schema,
dataCreate *schema.Entity,
id uint64,
) error {
if schema.Name != "file" {
return nil
}
// some logic to handle the file entity
// e.g. move the file to a different location
// or optimize the file for faster access
return nil
})PreDBUpdate
type PreDBUpdate = func(
ctx context.Context,
schema *schema.Schema,
predicates []*Predicate,
updateData *schema.Entity,
) error
func (a *App) OnPreDBUpdate(hooks ...db.PreDBUpdate)The PreDBUpdate hook is executed before the database Update operation is performed.
It can be used to manipulate the update data or the predicates before the update is executed.
schemais the schema of the entity.predicatesare the predicates used to filter the entities for the update.updateDatais the data used to update the entities.
PostDBUpdate
type PostDBUpdate = func(
ctx context.Context,
schema *schema.Schema,
predicates []*Predicate,
updateData *schema.Entity,
originalEntities []*schema.Entity,
affected int,
) error
func (a *App) OnPostDBUpdate(hooks ...db.PostDBUpdate)The PostDBUpdate hook is executed after the database Update operation is performed.
It can be used to trigger additional actions after one or many entities are updated.
schemais the schema of the entity.predicatesare the predicates used to filter the entities for the update.updateDatais the data used to update the entities.originalEntitiesare the entities before the update.affectedis the number of entities affected by the update.
Example:
app, _ := fastschema.New(&fs.Config{
SystemSchemas: []any{Tag{}, Blog{}},
})
app.OnPostDBUpdate(func(
ctx context.Context,
schema *schema.Schema,
predicates []*Predicate,
updateData *schema.Entity,
originalEntities []*schema.Entity,
affected int,
) error {
if schema.Name != "tag" {
return nil
}
// some logic to handle the tag entity update
// e.g. update the tag in a search index
// or update the tag in a cache
return nil
})PreDBDelete
type PreDBDelete = func(
ctx context.Context,
schema *schema.Schema,
predicates []*Predicate,
) error
func (a *App) OnPreDBDelete(hooks ...db.PreDBDelete)The PreDBDelete hook is executed before the database Delete operation is performed.
It can be used to manipulate the predicates before the delete is executed.
schemais the schema of the entity.predicatesare the predicates used to filter the entities for the delete.
PostDBDelete
type PostDBDelete = func(
ctx context.Context,
schema *schema.Schema,
predicates []*Predicate,
originalEntities []*schema.Entity,
affected int,
) error
func (a *App) OnPostDBDelete(hooks ...db.PostDBDelete)The PostDBDelete hook is executed after the database Delete operation is performed.
It can be used to trigger additional actions after one or many entities are deleted.
schemais the schema of the entity.predicatesare the predicates used to filter the entities for the delete.originalEntitiesare the entities before the delete.affectedis the number of entities affected by the delete.
Example:
app, _ := fastschema.New(&fs.Config{
SystemSchemas: []any{Tag{}, Blog{}},
})
app.OnPostDBDelete(func(
ctx context.Context,
schema *schema.Schema,
predicates []*Predicate,
originalEntities []*schema.Entity,
affected int,
) error {
if schema.Name != "tag" {
return nil
}
// some logic to handle the tag entity delete
// e.g. remove the tag from a search index
// or remove the tag from a cache
return nil
})PreDBExec
type PreDBExec = func(
ctx context.Context,
option *QueryOption,
) error
func (a *App) OnPreDBExec(hooks ...db.PreDBExec)The PreDBExec hook is executed before the database Exec operation is performed.
It can be used to manipulate the query before it is executed.
PostDBExec
type PostDBExec = func(
ctx context.Context,
option *QueryOption,
result sql.Result,
) error
func (a *App) OnPostDBExec(hooks ...db.PostDBExec)The PostDBExec hook is executed after the database Exec operation is performed.
It can be used to trigger additional actions after the query is executed.
resultis the result of the query execution.