1
0
mirror of https://github.com/pocketbase/pocketbase.git synced 2025-03-18 21:57:50 +02:00

added additional godoc and updated the OAuth2 form to use the same created record pointer

This commit is contained in:
Gani Georgiev 2024-10-24 08:37:22 +03:00
parent c41a4dfc07
commit 0b7741f1f7
28 changed files with 4020 additions and 3750 deletions

View File

@ -29,14 +29,14 @@ func bindBatchApi(app core.App, rg *router.RouterGroup[*core.RequestEvent]) {
type HandleFunc func(e *core.RequestEvent) error
type BatchActionHandlerFunc func(app core.App, ir *core.InternalRequest, params map[string]string, next func() error) HandleFunc
type BatchActionHandlerFunc func(app core.App, ir *core.InternalRequest, params map[string]string, next func(data any) error) HandleFunc
// ValidBatchActions defines a map with the supported batch InternalRequest actions.
//
// Note: when adding new routes make sure that their middlewares are inlined!
var ValidBatchActions = map[*regexp.Regexp]BatchActionHandlerFunc{
// "upsert" handler
regexp.MustCompile(`^PUT /api/collections/(?P<collection>[^\/\?]+)/records(?P<query>\?.*)?$`): func(app core.App, ir *core.InternalRequest, params map[string]string, next func() error) HandleFunc {
regexp.MustCompile(`^PUT /api/collections/(?P<collection>[^\/\?]+)/records(?P<query>\?.*)?$`): func(app core.App, ir *core.InternalRequest, params map[string]string, next func(any) error) HandleFunc {
var id string
if len(ir.Body) > 0 && ir.Body["id"] != "" {
id = cast.ToString(ir.Body["id"])
@ -59,13 +59,13 @@ var ValidBatchActions = map[*regexp.Regexp]BatchActionHandlerFunc{
ir.URL = "/api/collections/" + params["collection"] + "/records" + params["query"]
return recordCreate(next)
},
regexp.MustCompile(`^POST /api/collections/(?P<collection>[^\/\?]+)/records(\?.*)?$`): func(app core.App, ir *core.InternalRequest, params map[string]string, next func() error) HandleFunc {
regexp.MustCompile(`^POST /api/collections/(?P<collection>[^\/\?]+)/records(\?.*)?$`): func(app core.App, ir *core.InternalRequest, params map[string]string, next func(any) error) HandleFunc {
return recordCreate(next)
},
regexp.MustCompile(`^PATCH /api/collections/(?P<collection>[^\/\?]+)/records/(?P<id>[^\/\?]+)(\?.*)?$`): func(app core.App, ir *core.InternalRequest, params map[string]string, next func() error) HandleFunc {
regexp.MustCompile(`^PATCH /api/collections/(?P<collection>[^\/\?]+)/records/(?P<id>[^\/\?]+)(\?.*)?$`): func(app core.App, ir *core.InternalRequest, params map[string]string, next func(any) error) HandleFunc {
return recordUpdate(next)
},
regexp.MustCompile(`^DELETE /api/collections/(?P<collection>[^\/\?]+)/records/(?P<id>[^\/\?]+)(\?.*)?$`): func(app core.App, ir *core.InternalRequest, params map[string]string, next func() error) HandleFunc {
regexp.MustCompile(`^DELETE /api/collections/(?P<collection>[^\/\?]+)/records/(?P<id>[^\/\?]+)(\?.*)?$`): func(app core.App, ir *core.InternalRequest, params map[string]string, next func(any) error) HandleFunc {
return recordDelete(next)
},
}
@ -246,7 +246,7 @@ func (p *batchProcessor) process(activeApp core.App, batch []*core.InternalReque
p.baseEvent,
batch[0],
p.infoContext,
func() error {
func(_ any) error {
if len(batch) == 1 {
return nil
}
@ -277,7 +277,7 @@ func processInternalRequest(
baseEvent *core.RequestEvent,
ir *core.InternalRequest,
infoContext string,
optNext func() error,
optNext func(data any) error,
) (*BatchRequestResult, error) {
handle, params, ok := prepareInternalAction(activeApp, ir, optNext)
if !ok {
@ -475,7 +475,7 @@ func extractPrefixedFiles(request *http.Request, prefixes ...string) (map[string
return result, nil
}
func prepareInternalAction(activeApp core.App, ir *core.InternalRequest, optNext func() error) (HandleFunc, map[string]string, bool) {
func prepareInternalAction(activeApp core.App, ir *core.InternalRequest, optNext func(data any) error) (HandleFunc, map[string]string, bool) {
full := strings.ToUpper(ir.Method) + " " + ir.URL
for re, actionFactory := range ValidBatchActions {

View File

@ -60,6 +60,7 @@ func (api *fileApi) fileToken(e *core.RequestEvent) error {
event := new(core.FileTokenRequestEvent)
event.RequestEvent = e
event.Token = token
event.Record = e.Auth
return e.App.OnFileTokenRequest().Trigger(event, func(e *core.FileTokenRequestEvent) error {
return e.JSON(http.StatusOK, map[string]string{

View File

@ -2,7 +2,6 @@ package apis
import (
"context"
"encoding/json"
"errors"
"fmt"
"log/slog"
@ -335,27 +334,19 @@ func sendOAuth2RecordCreateRequest(txApp core.App, e *core.RecordAuthWithOAuth2R
Body: payload,
}
response, err := processInternalRequest(txApp, e.RequestEvent, ir, core.RequestInfoContextOAuth2, nil)
var createdRecord *core.Record
response, err := processInternalRequest(txApp, e.RequestEvent, ir, core.RequestInfoContextOAuth2, func(data any) error {
createdRecord, _ = data.(*core.Record)
return nil
})
if err != nil {
return nil, err
}
if response.Status != http.StatusOK {
if response.Status != http.StatusOK || createdRecord == nil {
return nil, errors.New("failed to create OAuth2 auth record")
}
recordResponse := struct {
Id string `json:"id"`
}{}
raw, err := json.Marshal(response.Body)
if err != nil {
return nil, err
}
if err = json.Unmarshal(raw, &recordResponse); err != nil {
return nil, err
}
return txApp.FindRecordById(e.Collection, recordResponse.Id)
return createdRecord, nil
}

View File

@ -147,7 +147,7 @@ func recordView(e *core.RequestEvent) error {
})
}
func recordCreate(optFinalizer func() error) func(e *core.RequestEvent) error {
func recordCreate(optFinalizer func(data any) error) func(e *core.RequestEvent) error {
return func(e *core.RequestEvent) error {
collection, err := e.App.FindCachedCollectionByNameOrId(e.Request.PathValue("collection"))
if err != nil || collection == nil {
@ -278,7 +278,7 @@ func recordCreate(optFinalizer func() error) func(e *core.RequestEvent) error {
if optFinalizer != nil {
isOptFinalizerCalled = true
err = optFinalizer()
err = optFinalizer(e.Record)
if err != nil {
return firstApiError(err, e.InternalServerError("", err))
}
@ -292,7 +292,7 @@ func recordCreate(optFinalizer func() error) func(e *core.RequestEvent) error {
// e.g. in case the regular hook chain was stopped and the finalizer cannot be executed as part of the last e.Next() task
if !isOptFinalizerCalled && optFinalizer != nil {
if err := optFinalizer(); err != nil {
if err := optFinalizer(event.Record); err != nil {
return firstApiError(err, e.InternalServerError("", err))
}
}
@ -301,7 +301,7 @@ func recordCreate(optFinalizer func() error) func(e *core.RequestEvent) error {
}
}
func recordUpdate(optFinalizer func() error) func(e *core.RequestEvent) error {
func recordUpdate(optFinalizer func(data any) error) func(e *core.RequestEvent) error {
return func(e *core.RequestEvent) error {
collection, err := e.App.FindCachedCollectionByNameOrId(e.Request.PathValue("collection"))
if err != nil || collection == nil {
@ -404,7 +404,7 @@ func recordUpdate(optFinalizer func() error) func(e *core.RequestEvent) error {
if optFinalizer != nil {
isOptFinalizerCalled = true
err = optFinalizer()
err = optFinalizer(e.Record)
if err != nil {
return firstApiError(err, e.InternalServerError("", fmt.Errorf("update optFinalizer error: %w", err)))
}
@ -418,7 +418,7 @@ func recordUpdate(optFinalizer func() error) func(e *core.RequestEvent) error {
// e.g. in case the regular hook chain was stopped and the finalizer cannot be executed as part of the last e.Next() task
if !isOptFinalizerCalled && optFinalizer != nil {
if err := optFinalizer(); err != nil {
if err := optFinalizer(event.Record); err != nil {
return firstApiError(err, e.InternalServerError("", fmt.Errorf("update optFinalizer error: %w", err)))
}
}
@ -427,7 +427,7 @@ func recordUpdate(optFinalizer func() error) func(e *core.RequestEvent) error {
}
}
func recordDelete(optFinalizer func() error) func(e *core.RequestEvent) error {
func recordDelete(optFinalizer func(data any) error) func(e *core.RequestEvent) error {
return func(e *core.RequestEvent) error {
collection, err := e.App.FindCachedCollectionByNameOrId(e.Request.PathValue("collection"))
if err != nil || collection == nil {
@ -494,7 +494,7 @@ func recordDelete(optFinalizer func() error) func(e *core.RequestEvent) error {
if optFinalizer != nil {
isOptFinalizerCalled = true
err = optFinalizer()
err = optFinalizer(e.Record)
if err != nil {
return firstApiError(err, e.InternalServerError("", fmt.Errorf("delete optFinalizer error: %w", err)))
}
@ -508,7 +508,7 @@ func recordDelete(optFinalizer func() error) func(e *core.RequestEvent) error {
// e.g. in case the regular hook chain was stopped and the finalizer cannot be executed as part of the last e.Next() task
if !isOptFinalizerCalled && optFinalizer != nil {
if err := optFinalizer(); err != nil {
if err := optFinalizer(event.Record); err != nil {
return firstApiError(err, e.InternalServerError("", fmt.Errorf("delete optFinalizer error: %w", err)))
}
}

View File

@ -152,6 +152,7 @@ func TestEnrichRecords(t *testing.T) {
`"test@example.com"`,
`"expand":{"rel_many"`,
`"id":"bgs820n361vj1qd"`,
`"id":"4q1xlclmfloku33"`,
`"id":"oap640cot4yru2s"`,
},
notExpected: []string{

View File

@ -596,7 +596,7 @@ type App interface {
// CanAccessRecord checks if a record is allowed to be accessed by the
// specified requestInfo and accessRule.
//
// Rule and db checks are ignored in case requestInfo.AuthRecord is a superuser.
// Rule and db checks are ignored in case requestInfo.Auth is a superuser.
//
// The returned error indicate that something unexpected happened during
// the check (eg. invalid rule or db query error).
@ -633,17 +633,19 @@ type App interface {
// App event hooks
// ---------------------------------------------------------------
// OnBootstrap hook is triggered on initializing the main application
// OnBootstrap hook is triggered when initializing the main application
// resources (db, app settings, etc).
OnBootstrap() *hook.Hook[*BootstrapEvent]
// OnServe hook is triggered on when the app web server is started
// (after starting the tcp listener but before initializing the blocking serve task),
// OnServe hook is triggered when the app web server is started
// (after starting the TCP listener but before initializing the blocking serve task),
// allowing you to adjust its options and attach new routes or middlewares.
OnServe() *hook.Hook[*ServeEvent]
// OnTerminate hook is triggered when the app is in the process
// of being terminated (ex. on SIGTERM signal).
//
// Note that the app could be terminated abruptly without awaiting the hook completion.
OnTerminate() *hook.Hook[*TerminateEvent]
// OnBackupCreate hook is triggered on each [App.CreateBackup] call.
@ -661,6 +663,9 @@ type App interface {
// OnModelValidate is triggered every time when a model is being validated
// (e.g. triggered by App.Validate() or App.Save()).
//
// For convenience, if you want to listen to only the Record models
// events without doing manual type assertion, you can attach to the OnRecord* proxy hooks.
//
// If the optional "tags" list (Collection id/name, Model table name, etc.) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
@ -680,7 +685,7 @@ type App interface {
// Note that successful execution doesn't guarantee that the model
// is persisted in the database since its wrapping transaction may
// not have been committed yet.
// If you wan to listen to only the actual persisted events, you can
// If you want to listen to only the actual persisted events, you can
// bind to [OnModelAfterCreateSuccess] or [OnModelAfterCreateError] hooks.
//
// For convenience, if you want to listen to only the Record models
@ -703,7 +708,7 @@ type App interface {
// Note that successful execution doesn't guarantee that the model
// is persisted in the database since its wrapping transaction may have been
// committed yet.
// If you wan to listen to only the actual persisted events,
// If you want to listen to only the actual persisted events,
// you can bind to [OnModelAfterCreateSuccess] or [OnModelAfterCreateError] hooks.
//
// For convenience, if you want to listen to only the Record models
@ -718,7 +723,7 @@ type App interface {
// Model DB create persistence.
//
// Note that when a Model is persisted as part of a transaction,
// this hook is triggered AFTER the transaction has been committed.
// this hook is delayed and executed only AFTER the transaction has been committed.
// This hook is NOT triggered in case the transaction rollbacks
// (aka. when the model wasn't persisted).
//
@ -732,10 +737,11 @@ type App interface {
// OnModelAfterCreateError is triggered after each failed
// Model DB create persistence.
// Note that when a Model is persisted as part of a transaction,
// this hook is triggered in one of the following cases:
// - immediately after App.Save() failure
// - on transaction rollback
//
// Note that the execution of this hook is either immediate or delayed
// depending on the error:
// - "immediate" on App.Save() failure
// - "delayed" on transaction rollback
//
// For convenience, if you want to listen to only the Record models
// events without doing manual type assertion, you can attach to the OnRecord* proxy hooks.
@ -759,7 +765,7 @@ type App interface {
// Note that successful execution doesn't guarantee that the model
// is persisted in the database since its wrapping transaction may
// not have been committed yet.
// If you wan to listen to only the actual persisted events, you can
// If you want to listen to only the actual persisted events, you can
// bind to [OnModelAfterUpdateSuccess] or [OnModelAfterUpdateError] hooks.
//
// For convenience, if you want to listen to only the Record models
@ -782,7 +788,7 @@ type App interface {
// Note that successful execution doesn't guarantee that the model
// is persisted in the database since its wrapping transaction may have been
// committed yet.
// If you wan to listen to only the actual persisted events,
// If you want to listen to only the actual persisted events,
// you can bind to [OnModelAfterUpdateSuccess] or [OnModelAfterUpdateError] hooks.
//
// For convenience, if you want to listen to only the Record models
@ -797,7 +803,7 @@ type App interface {
// Model DB update persistence.
//
// Note that when a Model is persisted as part of a transaction,
// this hook is triggered AFTER the transaction has been committed.
// this hook is delayed and executed only AFTER the transaction has been committed.
// This hook is NOT triggered in case the transaction rollbacks
// (aka. when the model changes weren't persisted).
//
@ -812,10 +818,10 @@ type App interface {
// OnModelAfterUpdateError is triggered after each failed
// Model DB update persistence.
//
// Note that when a Model is persisted as part of a transaction,
// this hook is triggered in one of the following cases:
// - immediately after App.Save() failure
// - on transaction rollback
// Note that the execution of this hook is either immediate or delayed
// depending on the error:
// - "immediate" on App.Save() failure
// - "delayed" on transaction rollback
//
// For convenience, if you want to listen to only the Record models
// events without doing manual type assertion, you can attach to the OnRecord* proxy hooks.
@ -833,7 +839,7 @@ type App interface {
// Note that successful execution doesn't guarantee that the model
// is deleted from the database since its wrapping transaction may
// not have been committed yet.
// If you wan to listen to only the actual persisted deleted events, you can
// If you want to listen to only the actual persisted deleted events, you can
// bind to [OnModelAfterDeleteSuccess] or [OnModelAfterDeleteError] hooks.
//
// For convenience, if you want to listen to only the Record models
@ -856,7 +862,7 @@ type App interface {
// Note that successful execution doesn't guarantee that the model
// is deleted from the database since its wrapping transaction may
// not have been committed yet.
// If you wan to listen to only the actual persisted deleted events, you can
// If you want to listen to only the actual persisted deleted events, you can
// bind to [OnModelAfterDeleteSuccess] or [OnModelAfterDeleteError] hooks.
//
// For convenience, if you want to listen to only the Record models
@ -871,7 +877,7 @@ type App interface {
// Model DB delete persistence.
//
// Note that when a Model is deleted as part of a transaction,
// this hook is triggered AFTER the transaction has been committed.
// this hook is delayed and executed only AFTER the transaction has been committed.
// This hook is NOT triggered in case the transaction rollbacks
// (aka. when the model delete wasn't persisted).
//
@ -886,10 +892,10 @@ type App interface {
// OnModelAfterDeleteError is triggered after each failed
// Model DB delete persistence.
//
// Note that when a Model is deleted as part of a transaction,
// this hook is triggered in one of the following cases:
// - immediately after App.Delete() failure
// - on transaction rollback
// Note that the execution of this hook is either immediate or delayed
// depending on the error:
// - "immediate" on App.Delete() failure
// - "delayed" on transaction rollback
//
// For convenience, if you want to listen to only the Record models
// events without doing manual type assertion, you can attach to the OnRecord* proxy hooks.
@ -904,10 +910,9 @@ type App interface {
// ---------------------------------------------------------------
// OnRecordEnrich is triggered every time when a record is enriched
// (during realtime message seriazation, as part of the builtin Record
// responses, or when [apis.EnrichRecord] is invoked).
// (as part of the builtin Record responses, during realtime message seriazation, or when [apis.EnrichRecord] is invoked).
//
// It could be used for example to redact/hide or add computed temp
// It could be used for example to redact/hide or add computed temporary
// Record model props only for the specific request info. For example:
//
// app.OnRecordEnrich("posts").BindFunc(func(e core.*RecordEnrichEvent) {
@ -928,7 +933,7 @@ type App interface {
// triggered and called only if their event data origin matches the tags.
OnRecordEnrich(tags ...string) *hook.TaggedHook[*RecordEnrichEvent]
// OnRecordValidate is a proxy Record model hook for [OnModelValidate].
// OnRecordValidate is a Record proxy model hook of [OnModelValidate].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
@ -937,28 +942,28 @@ type App interface {
// ---------------------------------------------------------------
// OnRecordCreate is a proxy Record model hook for [OnModelCreate].
// OnRecordCreate is a Record proxy model hook of [OnModelCreate].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnRecordCreate(tags ...string) *hook.TaggedHook[*RecordEvent]
// OnRecordCreateExecute is a proxy Record model hook for [OnModelCreateExecute].
// OnRecordCreateExecute is a Record proxy model hook of [OnModelCreateExecute].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnRecordCreateExecute(tags ...string) *hook.TaggedHook[*RecordEvent]
// OnRecordAfterCreateSuccess is a proxy Record model hook for [OnModelAfterCreateSuccess].
// OnRecordAfterCreateSuccess is a Record proxy model hook of [OnModelAfterCreateSuccess].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnRecordAfterCreateSuccess(tags ...string) *hook.TaggedHook[*RecordEvent]
// OnRecordAfterCreateError is a proxy Record model hook for [OnModelAfterCreateError].
// OnRecordAfterCreateError is a Record proxy model hook of [OnModelAfterCreateError].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
@ -967,28 +972,28 @@ type App interface {
// ---------------------------------------------------------------
// OnRecordUpdate is a proxy Record model hook for [OnModelUpdate].
// OnRecordUpdate is a Record proxy model hook of [OnModelUpdate].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnRecordUpdate(tags ...string) *hook.TaggedHook[*RecordEvent]
// OnRecordUpdateExecute is a proxy Record model hook for [OnModelUpdateExecute].
// OnRecordUpdateExecute is a Record proxy model hook of [OnModelUpdateExecute].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnRecordUpdateExecute(tags ...string) *hook.TaggedHook[*RecordEvent]
// OnRecordAfterUpdateSuccess is a proxy Record model hook for [OnModelAfterUpdateSuccess].
// OnRecordAfterUpdateSuccess is a Record proxy model hook of [OnModelAfterUpdateSuccess].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnRecordAfterUpdateSuccess(tags ...string) *hook.TaggedHook[*RecordEvent]
// OnRecordAfterUpdateError is a proxy Record model hook for [OnModelAfterUpdateError].
// OnRecordAfterUpdateError is a Record proxy model hook of [OnModelAfterUpdateError].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
@ -997,28 +1002,28 @@ type App interface {
// ---------------------------------------------------------------
// OnRecordDelete is a proxy Record model hook for [OnModelDelete].
// OnRecordDelete is a Record proxy model hook of [OnModelDelete].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnRecordDelete(tags ...string) *hook.TaggedHook[*RecordEvent]
// OnRecordDeleteExecute is a proxy Record model hook for [OnModelDeleteExecute].
// OnRecordDeleteExecute is a Record proxy model hook of [OnModelDeleteExecute].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnRecordDeleteExecute(tags ...string) *hook.TaggedHook[*RecordEvent]
// OnRecordAfterDeleteSuccess is a proxy Record model hook for [OnModelAfterDeleteSuccess].
// OnRecordAfterDeleteSuccess is a Record proxy model hook of [OnModelAfterDeleteSuccess].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnRecordAfterDeleteSuccess(tags ...string) *hook.TaggedHook[*RecordEvent]
// OnRecordAfterDeleteError is a proxy Record model hook for [OnModelAfterDeleteError].
// OnRecordAfterDeleteError is a Record proxy model hook of [OnModelAfterDeleteError].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
@ -1029,7 +1034,7 @@ type App interface {
// Collection models event hooks
// ---------------------------------------------------------------
// OnCollectionValidate is a proxy Collection model hook for [OnModelValidate].
// OnCollectionValidate is a Collection proxy model hook of [OnModelValidate].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
@ -1038,28 +1043,28 @@ type App interface {
// ---------------------------------------------------------------
// OnCollectionCreate is a proxy Collection model hook for [OnModelCreate].
// OnCollectionCreate is a Collection proxy model hook of [OnModelCreate].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnCollectionCreate(tags ...string) *hook.TaggedHook[*CollectionEvent]
// OnCollectionCreateExecute is a proxy Collection model hook for [OnModelCreateExecute].
// OnCollectionCreateExecute is a Collection proxy model hook of [OnModelCreateExecute].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnCollectionCreateExecute(tags ...string) *hook.TaggedHook[*CollectionEvent]
// OnCollectionAfterCreateSuccess is a proxy Collection model hook for [OnModelAfterCreateSuccess].
// OnCollectionAfterCreateSuccess is a Collection proxy model hook of [OnModelAfterCreateSuccess].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnCollectionAfterCreateSuccess(tags ...string) *hook.TaggedHook[*CollectionEvent]
// OnCollectionAfterCreateError is a proxy Collection model hook for [OnModelAfterCreateError].
// OnCollectionAfterCreateError is a Collection proxy model hook of [OnModelAfterCreateError].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
@ -1068,28 +1073,28 @@ type App interface {
// ---------------------------------------------------------------
// OnCollectionUpdate is a proxy Collection model hook for [OnModelUpdate].
// OnCollectionUpdate is a Collection proxy model hook of [OnModelUpdate].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnCollectionUpdate(tags ...string) *hook.TaggedHook[*CollectionEvent]
// OnCollectionUpdateExecute is a proxy Collection model hook for [OnModelUpdateExecute].
// OnCollectionUpdateExecute is a Collection proxy model hook of [OnModelUpdateExecute].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnCollectionUpdateExecute(tags ...string) *hook.TaggedHook[*CollectionEvent]
// OnCollectionAfterUpdateSuccess is a proxy Collection model hook for [OnModelAfterUpdateSuccess].
// OnCollectionAfterUpdateSuccess is a Collection proxy model hook of [OnModelAfterUpdateSuccess].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnCollectionAfterUpdateSuccess(tags ...string) *hook.TaggedHook[*CollectionEvent]
// OnCollectionAfterUpdateError is a proxy Collection model hook for [OnModelAfterUpdateError].
// OnCollectionAfterUpdateError is a Collection proxy model hook of [OnModelAfterUpdateError].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
@ -1098,28 +1103,28 @@ type App interface {
// ---------------------------------------------------------------
// OnCollectionDelete is a proxy Collection model hook for [OnModelDelete].
// OnCollectionDelete is a Collection proxy model hook of [OnModelDelete].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnCollectionDelete(tags ...string) *hook.TaggedHook[*CollectionEvent]
// OnCollectionDeleteExecute is a proxy Collection model hook for [OnModelDeleteExecute].
// OnCollectionDeleteExecute is a Collection proxy model hook of [OnModelDeleteExecute].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnCollectionDeleteExecute(tags ...string) *hook.TaggedHook[*CollectionEvent]
// OnCollectionAfterDeleteSuccess is a proxy Collection model hook for [OnModelAfterDeleteSuccess].
// OnCollectionAfterDeleteSuccess is a Collection proxy model hook of [OnModelAfterDeleteSuccess].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnCollectionAfterDeleteSuccess(tags ...string) *hook.TaggedHook[*CollectionEvent]
// OnCollectionAfterDeleteError is a proxy Collection model hook for [OnModelAfterDeleteError].
// OnCollectionAfterDeleteError is a Collection proxy model hook of [OnModelAfterDeleteError].
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
@ -1131,7 +1136,7 @@ type App interface {
// ---------------------------------------------------------------
// OnMailerSend hook is triggered every time when a new email is
// being send using the App.NewMailClient() instance.
// being send using the [App.NewMailClient()] instance.
//
// It allows intercepting the email message or to use a custom mailer client.
OnMailerSend() *hook.Hook[*MailerEvent]
@ -1187,7 +1192,7 @@ type App interface {
// OnRealtimeConnectRequest hook is triggered when establishing the SSE client connection.
//
// Any execution after [e.Next()] of a hook handler happens after the client disconnects.
// Any execution after e.Next() of a hook handler happens after the client disconnects.
OnRealtimeConnectRequest() *hook.Hook[*RealtimeConnectRequestEvent]
// OnRealtimeMessageSend hook is triggered when sending an SSE message to a client.
@ -1216,7 +1221,7 @@ type App interface {
// OnSettingsReload hook is triggered every time when the App.Settings()
// is being replaced with a new state.
//
// Calling App.Settings() after e.Next() should return the new state.
// Calling App.Settings() after e.Next() returns the new state.
OnSettingsReload() *hook.Hook[*SettingsReloadEvent]
// ---------------------------------------------------------------
@ -1229,8 +1234,12 @@ type App interface {
// returning it to the client.
OnFileDownloadRequest(tags ...string) *hook.TaggedHook[*FileDownloadRequestEvent]
// OnFileBeforeTokenRequest hook is triggered on each file token API request.
OnFileTokenRequest() *hook.Hook[*FileTokenRequestEvent]
// OnFileBeforeTokenRequest hook is triggered on each auth file token API request.
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
// triggered and called only if their event data origin matches the tags.
OnFileTokenRequest(tags ...string) *hook.TaggedHook[*FileTokenRequestEvent]
// ---------------------------------------------------------------
// Record Auth API event hooks
@ -1250,9 +1259,8 @@ type App interface {
// OnRecordAuthWithPasswordRequest hook is triggered on each
// Record auth with password API request.
//
// RecordAuthWithPasswordRequestEvent.Record could be nil if no
// matching identity is found, allowing you to manually locate a different
// Record model (by reassigning [RecordAuthWithPasswordRequestEvent.Record]).
// [RecordAuthWithPasswordRequestEvent.Record] could be nil if no matching identity is found, allowing
// you to manually locate a different Record model (by reassigning [RecordAuthWithPasswordRequestEvent.Record]).
//
// If the optional "tags" list (Collection ids or names) is specified,
// then all event handlers registered via the created hook will be
@ -1262,7 +1270,7 @@ type App interface {
// OnRecordAuthWithOAuth2Request hook is triggered on each Record
// OAuth2 sign-in/sign-up API request (after token exchange and before external provider linking).
//
// If the [RecordAuthWithOAuth2RequestEvent.Record] is not set, then the OAuth2
// If [RecordAuthWithOAuth2RequestEvent.Record] is not set, then the OAuth2
// request will try to create a new auth Record.
//
// To assign or link a different existing record model you can

View File

@ -981,8 +981,8 @@ func (app *BaseApp) OnFileDownloadRequest(tags ...string) *hook.TaggedHook[*File
return hook.NewTaggedHook(app.onFileDownloadRequest, tags...)
}
func (app *BaseApp) OnFileTokenRequest() *hook.Hook[*FileTokenRequestEvent] {
return app.onFileTokenRequest
func (app *BaseApp) OnFileTokenRequest(tags ...string) *hook.TaggedHook[*FileTokenRequestEvent] {
return hook.NewTaggedHook(app.onFileTokenRequest, tags...)
}
// -------------------------------------------------------------------

View File

@ -325,9 +325,12 @@ type baseCollection struct {
Type string `db:"type" json:"type" form:"type"`
Fields FieldsList `db:"fields" json:"fields" form:"fields"`
Indexes types.JSONArray[string] `db:"indexes" json:"indexes" form:"indexes"`
System bool `db:"system" json:"system" form:"system"`
Created types.DateTime `db:"created" json:"created"`
Updated types.DateTime `db:"updated" json:"updated"`
// System prevents the collection rename, deletion and rules change.
// It is used primarily for internal purposes for collections like "_superusers", "_externalAuths", etc.
System bool `db:"system" json:"system" form:"system"`
}
// Collection defines the table, fields and various options related to a set of records.

View File

@ -4,9 +4,11 @@ import (
"net/http"
validation "github.com/go-ozzo/ozzo-validation/v4"
"github.com/pocketbase/pocketbase/tools/hook"
)
type BatchRequestEvent struct {
hook.Event
*RequestEvent
Batch []*InternalRequest

View File

@ -323,6 +323,7 @@ func syncModelErrorEventWithCollectionErrorEvent(me *ModelErrorEvent, ce *Collec
type FileTokenRequestEvent struct {
hook.Event
*RequestEvent
baseRecordEventData
Token string
}

View File

@ -25,13 +25,27 @@ var (
// AutodateField defines an "autodate" type field, aka.
// field which datetime value could be auto set on record create/update.
//
// This field is usually used for defining timestamp fields like "created" and "updated".
//
// Requires either both or at least one of the OnCreate or OnUpdate options to be set.
type AutodateField struct {
Id string `form:"id" json:"id"`
Name string `form:"name" json:"name"`
System bool `form:"system" json:"system"`
Hidden bool `form:"hidden" json:"hidden"`
Presentable bool `form:"presentable" json:"presentable"`
// Name (required) is the unique name of the field.
Name string `form:"name" json:"name"`
// Id is the unique stable field identifier.
//
// It is automatically generated from the name when adding to a collection FieldsList.
Id string `form:"id" json:"id"`
// System prevents the renaming and removal of the field.
System bool `form:"system" json:"system"`
// Hidden hides the field from the API response.
Hidden bool `form:"hidden" json:"hidden"`
// Presentable hints the Dashboard UI to use the underlying
// field record value in the relation preview label.
Presentable bool `form:"presentable" json:"presentable"`
// ---

View File

@ -19,12 +19,26 @@ const FieldTypeBool = "bool"
var _ Field = (*BoolField)(nil)
// BoolField defines "bool" type field to store a single true/false value.
//
// The respective zero record field value is false.
type BoolField struct {
Id string `form:"id" json:"id"`
Name string `form:"name" json:"name"`
System bool `form:"system" json:"system"`
Hidden bool `form:"hidden" json:"hidden"`
Presentable bool `form:"presentable" json:"presentable"`
// Name (required) is the unique name of the field.
Name string `form:"name" json:"name"`
// Id is the unique stable field identifier.
//
// It is automatically generated from the name when adding to a collection FieldsList.
Id string `form:"id" json:"id"`
// System prevents the renaming and removal of the field.
System bool `form:"system" json:"system"`
// Hidden hides the field from the API response.
Hidden bool `form:"hidden" json:"hidden"`
// Presentable hints the Dashboard UI to use the underlying
// field record value in the relation preview label.
Presentable bool `form:"presentable" json:"presentable"`
// ---

View File

@ -19,12 +19,26 @@ const FieldTypeDate = "date"
var _ Field = (*DateField)(nil)
// DateField defines "date" type field to store a single [types.DateTime] value.
//
// The respective zero record field value is the zero [types.DateTime].
type DateField struct {
Id string `form:"id" json:"id"`
Name string `form:"name" json:"name"`
System bool `form:"system" json:"system"`
Hidden bool `form:"hidden" json:"hidden"`
Presentable bool `form:"presentable" json:"presentable"`
// Name (required) is the unique name of the field.
Name string `form:"name" json:"name"`
// Id is the unique stable field identifier.
//
// It is automatically generated from the name when adding to a collection FieldsList.
Id string `form:"id" json:"id"`
// System prevents the renaming and removal of the field.
System bool `form:"system" json:"system"`
// Hidden hides the field from the API response.
Hidden bool `form:"hidden" json:"hidden"`
// Presentable hints the Dashboard UI to use the underlying
// field record value in the relation preview label.
Presentable bool `form:"presentable" json:"presentable"`
// ---

View File

@ -25,12 +25,26 @@ var (
)
// EditorField defines "editor" type field to store HTML formatted text.
//
// The respective zero record field value is empty string.
type EditorField struct {
Id string `form:"id" json:"id"`
Name string `form:"name" json:"name"`
System bool `form:"system" json:"system"`
Hidden bool `form:"hidden" json:"hidden"`
Presentable bool `form:"presentable" json:"presentable"`
// Name (required) is the unique name of the field.
Name string `form:"name" json:"name"`
// Id is the unique stable field identifier.
//
// It is automatically generated from the name when adding to a collection FieldsList.
Id string `form:"id" json:"id"`
// System prevents the renaming and removal of the field.
System bool `form:"system" json:"system"`
// Hidden hides the field from the API response.
Hidden bool `form:"hidden" json:"hidden"`
// Presentable hints the Dashboard UI to use the underlying
// field record value in the relation preview label.
Presentable bool `form:"presentable" json:"presentable"`
// ---

View File

@ -22,12 +22,26 @@ const FieldTypeEmail = "email"
var _ Field = (*EmailField)(nil)
// EmailField defines "email" type field for storing single email string address.
//
// The respective zero record field value is empty string.
type EmailField struct {
Id string `form:"id" json:"id"`
Name string `form:"name" json:"name"`
System bool `form:"system" json:"system"`
Hidden bool `form:"hidden" json:"hidden"`
Presentable bool `form:"presentable" json:"presentable"`
// Name (required) is the unique name of the field.
Name string `form:"name" json:"name"`
// Id is the unique stable field identifier.
//
// It is automatically generated from the name when adding to a collection FieldsList.
Id string `form:"id" json:"id"`
// System prevents the renaming and removal of the field.
System bool `form:"system" json:"system"`
// Hidden hides the field from the API response.
Hidden bool `form:"hidden" json:"hidden"`
// Presentable hints the Dashboard UI to use the underlying
// field record value in the relation preview label.
Presentable bool `form:"presentable" json:"presentable"`
// ---

View File

@ -53,6 +53,8 @@ var (
//
// If MaxSelect is > 1, then the field value is expected to be a slice of record ids.
//
// The respective zero record field value is either empty string (single) or empty string slice (multiple).
//
// ---
//
// The following additional setter keys are available:
@ -72,11 +74,23 @@ var (
// // []string{"old2.txt",}
// record.Set("documents-", "old1.txt")
type FileField struct {
Id string `form:"id" json:"id"`
Name string `form:"name" json:"name"`
System bool `form:"system" json:"system"`
Hidden bool `form:"hidden" json:"hidden"`
Presentable bool `form:"presentable" json:"presentable"`
// Name (required) is the unique name of the field.
Name string `form:"name" json:"name"`
// Id is the unique stable field identifier.
//
// It is automatically generated from the name when adding to a collection FieldsList.
Id string `form:"id" json:"id"`
// System prevents the renaming and removal of the field.
System bool `form:"system" json:"system"`
// Hidden hides the field from the API response.
Hidden bool `form:"hidden" json:"hidden"`
// Presentable hints the Dashboard UI to use the underlying
// field record value in the relation preview label.
Presentable bool `form:"presentable" json:"presentable"`
// ---

View File

@ -29,12 +29,26 @@ var (
)
// JSONField defines "json" type field for storing any serialized JSON value.
//
// The respective zero record field value is the zero [types.JSONRaw].
type JSONField struct {
Id string `form:"id" json:"id"`
Name string `form:"name" json:"name"`
System bool `form:"system" json:"system"`
Hidden bool `form:"hidden" json:"hidden"`
Presentable bool `form:"presentable" json:"presentable"`
// Name (required) is the unique name of the field.
Name string `form:"name" json:"name"`
// Id is the unique stable field identifier.
//
// It is automatically generated from the name when adding to a collection FieldsList.
Id string `form:"id" json:"id"`
// System prevents the renaming and removal of the field.
System bool `form:"system" json:"system"`
// Hidden hides the field from the API response.
Hidden bool `form:"hidden" json:"hidden"`
// Presentable hints the Dashboard UI to use the underlying
// field record value in the relation preview label.
Presentable bool `form:"presentable" json:"presentable"`
// ---

View File

@ -25,6 +25,8 @@ var (
// NumberField defines "number" type field for storing numeric (float64) value.
//
// The respective zero record field value is 0.
//
// The following additional setter keys are available:
//
// - "fieldName+" - appends to the existing record value. For example:
@ -32,11 +34,23 @@ var (
// - "fieldName-" - subtracts from the existing record value. For example:
// record.Set("total-", 5)
type NumberField struct {
Id string `form:"id" json:"id"`
Name string `form:"name" json:"name"`
System bool `form:"system" json:"system"`
Hidden bool `form:"hidden" json:"hidden"`
Presentable bool `form:"presentable" json:"presentable"`
// Name (required) is the unique name of the field.
Name string `form:"name" json:"name"`
// Id is the unique stable field identifier.
//
// It is automatically generated from the name when adding to a collection FieldsList.
Id string `form:"id" json:"id"`
// System prevents the renaming and removal of the field.
System bool `form:"system" json:"system"`
// Hidden hides the field from the API response.
Hidden bool `form:"hidden" json:"hidden"`
// Presentable hints the Dashboard UI to use the underlying
// field record value in the relation preview label.
Presentable bool `form:"presentable" json:"presentable"`
// ---

View File

@ -47,11 +47,23 @@ var (
// - "fieldName:hash" - returns the bcrypt hash string of the record field value (if any). For example:
// record.GetString("password:hash")
type PasswordField struct {
Id string `form:"id" json:"id"`
Name string `form:"name" json:"name"`
System bool `form:"system" json:"system"`
Hidden bool `form:"hidden" json:"hidden"`
Presentable bool `form:"presentable" json:"presentable"`
// Name (required) is the unique name of the field.
Name string `form:"name" json:"name"`
// Id is the unique stable field identifier.
//
// It is automatically generated from the name when adding to a collection FieldsList.
Id string `form:"id" json:"id"`
// System prevents the renaming and removal of the field.
System bool `form:"system" json:"system"`
// Hidden hides the field from the API response.
Hidden bool `form:"hidden" json:"hidden"`
// Presentable hints the Dashboard UI to use the underlying
// field record value in the relation preview label.
Presentable bool `form:"presentable" json:"presentable"`
// ---

View File

@ -35,6 +35,8 @@ var (
//
// If MaxSelect is > 1, then the field value is expected to be a slice of record ids.
//
// The respective zero record field value is either empty string (single) or empty string slice (multiple).
//
// ---
//
// The following additional setter keys are available:
@ -51,11 +53,23 @@ var (
//
// record.Set("categories-", "old1") // []string{"old2"}
type RelationField struct {
Id string `form:"id" json:"id"`
Name string `form:"name" json:"name"`
System bool `form:"system" json:"system"`
Hidden bool `form:"hidden" json:"hidden"`
Presentable bool `form:"presentable" json:"presentable"`
// Name (required) is the unique name of the field.
Name string `form:"name" json:"name"`
// Id is the unique stable field identifier.
//
// It is automatically generated from the name when adding to a collection FieldsList.
Id string `form:"id" json:"id"`
// System prevents the renaming and removal of the field.
System bool `form:"system" json:"system"`
// Hidden hides the field from the API response.
Hidden bool `form:"hidden" json:"hidden"`
// Presentable hints the Dashboard UI to use the underlying
// field record value in the relation preview label.
Presentable bool `form:"presentable" json:"presentable"`
// ---

View File

@ -35,6 +35,8 @@ var (
//
// If MaxSelect is > 1, then the field value is expected to be a subset of Values slice.
//
// The respective zero record field value is either empty string (single) or empty string slice (multiple).
//
// ---
//
// The following additional setter keys are available:
@ -51,11 +53,23 @@ var (
//
// record.Set("roles-", "old1") // []string{"old2"}
type SelectField struct {
Id string `form:"id" json:"id"`
Name string `form:"name" json:"name"`
System bool `form:"system" json:"system"`
Hidden bool `form:"hidden" json:"hidden"`
Presentable bool `form:"presentable" json:"presentable"`
// Name (required) is the unique name of the field.
Name string `form:"name" json:"name"`
// Id is the unique stable field identifier.
//
// It is automatically generated from the name when adding to a collection FieldsList.
Id string `form:"id" json:"id"`
// System prevents the renaming and removal of the field.
System bool `form:"system" json:"system"`
// Hidden hides the field from the API response.
Hidden bool `form:"hidden" json:"hidden"`
// Presentable hints the Dashboard UI to use the underlying
// field record value in the relation preview label.
Presentable bool `form:"presentable" json:"presentable"`
// ---

View File

@ -29,6 +29,8 @@ var (
// TextField defines "text" type field for storing any string value.
//
// The respective zero record field value is empty string.
//
// The following additional setter keys are available:
//
// - "fieldName:autogenerate" - autogenerate field value if AutogeneratePattern is set. For example:
@ -36,11 +38,23 @@ var (
// record.Set("slug:autogenerate", "") // [random value]
// record.Set("slug:autogenerate", "abc-") // abc-[random value]
type TextField struct {
Id string `form:"id" json:"id"`
Name string `form:"name" json:"name"`
System bool `form:"system" json:"system"`
Hidden bool `form:"hidden" json:"hidden"`
Presentable bool `form:"presentable" json:"presentable"`
// Name (required) is the unique name of the field.
Name string `form:"name" json:"name"`
// Id is the unique stable field identifier.
//
// It is automatically generated from the name when adding to a collection FieldsList.
Id string `form:"id" json:"id"`
// System prevents the renaming and removal of the field.
System bool `form:"system" json:"system"`
// Hidden hides the field from the API response.
Hidden bool `form:"hidden" json:"hidden"`
// Presentable hints the Dashboard UI to use the underlying
// field record value in the relation preview label.
Presentable bool `form:"presentable" json:"presentable"`
// ---

View File

@ -22,12 +22,26 @@ const FieldTypeURL = "url"
var _ Field = (*URLField)(nil)
// URLField defines "url" type field for storing URL string value.
//
// The respective zero record field value is empty string.
type URLField struct {
Id string `form:"id" json:"id"`
Name string `form:"name" json:"name"`
System bool `form:"system" json:"system"`
Hidden bool `form:"hidden" json:"hidden"`
Presentable bool `form:"presentable" json:"presentable"`
// Name (required) is the unique name of the field.
Name string `form:"name" json:"name"`
// Id is the unique stable field identifier.
//
// It is automatically generated from the name when adding to a collection FieldsList.
Id string `form:"id" json:"id"`
// System prevents the renaming and removal of the field.
System bool `form:"system" json:"system"`
// Hidden hides the field from the API response.
Hidden bool `form:"hidden" json:"hidden"`
// Presentable hints the Dashboard UI to use the underlying
// field record value in the relation preview label.
Presentable bool `form:"presentable" json:"presentable"`
// ---

View File

@ -553,7 +553,7 @@ func (app *BaseApp) FindAuthRecordByEmail(collectionModelOrIdentifier any, email
// CanAccessRecord checks if a record is allowed to be accessed by the
// specified requestInfo and accessRule.
//
// Rule and db checks are ignored in case requestInfo.AuthRecord is a superuser.
// Rule and db checks are ignored in case requestInfo.Auth is a superuser.
//
// The returned error indicate that something unexpected happened during
// the check (eg. invalid rule or db query error).

File diff suppressed because it is too large Load Diff

View File

@ -436,7 +436,7 @@ declare class Field implements core.Field {
interface NumberField extends core.NumberField{} // merge
/**
* NumberField class defines a single "number" collection field.
* {@inheritDoc core.NumberField}
*
* @group PocketBase
*/
@ -446,7 +446,7 @@ declare class NumberField implements core.NumberField {
interface BoolField extends core.BoolField{} // merge
/**
* BoolField class defines a single "bool" collection field.
* {@inheritDoc core.BoolField}
*
* @group PocketBase
*/
@ -456,7 +456,7 @@ declare class BoolField implements core.BoolField {
interface TextField extends core.TextField{} // merge
/**
* TextField class defines a single "text" collection field.
* {@inheritDoc core.TextField}
*
* @group PocketBase
*/
@ -466,7 +466,7 @@ declare class TextField implements core.TextField {
interface URLField extends core.URLField{} // merge
/**
* URLField class defines a single "url" collection field.
* {@inheritDoc core.URLField}
*
* @group PocketBase
*/
@ -476,7 +476,7 @@ declare class URLField implements core.URLField {
interface EmailField extends core.EmailField{} // merge
/**
* EmailField class defines a single "email" collection field.
* {@inheritDoc core.EmailField}
*
* @group PocketBase
*/
@ -486,7 +486,7 @@ declare class EmailField implements core.EmailField {
interface EditorField extends core.EditorField{} // merge
/**
* EditorField class defines a single "editor" collection field.
* {@inheritDoc core.EditorField}
*
* @group PocketBase
*/
@ -496,7 +496,7 @@ declare class EditorField implements core.EditorField {
interface PasswordField extends core.PasswordField{} // merge
/**
* PasswordField class defines a single "password" collection field.
* {@inheritDoc core.PasswordField}
*
* @group PocketBase
*/
@ -506,7 +506,7 @@ declare class PasswordField implements core.PasswordField {
interface DateField extends core.DateField{} // merge
/**
* DateField class defines a single "date" collection field.
* {@inheritDoc core.DateField}
*
* @group PocketBase
*/
@ -516,7 +516,7 @@ declare class DateField implements core.DateField {
interface AutodateField extends core.AutodateField{} // merge
/**
* AutodateField class defines a single "autodate" collection field.
* {@inheritDoc core.AutodateField}
*
* @group PocketBase
*/
@ -526,7 +526,7 @@ declare class AutodateField implements core.AutodateField {
interface JSONField extends core.JSONField{} // merge
/**
* JSONField class defines a single "json" collection field.
* {@inheritDoc core.JSONField}
*
* @group PocketBase
*/
@ -536,7 +536,7 @@ declare class JSONField implements core.JSONField {
interface RelationField extends core.RelationField{} // merge
/**
* RelationField class defines a single "relation" collection field.
* {@inheritDoc core.RelationField}
*
* @group PocketBase
*/
@ -546,7 +546,7 @@ declare class RelationField implements core.RelationField {
interface SelectField extends core.SelectField{} // merge
/**
* SelectField class defines a single "select" collection field.
* {@inheritDoc core.SelectField}
*
* @group PocketBase
*/
@ -556,7 +556,7 @@ declare class SelectField implements core.SelectField {
interface FileField extends core.FileField{} // merge
/**
* FileField class defines a single "file" collection field.
* {@inheritDoc core.FileField}
*
* @group PocketBase
*/

View File

@ -60,13 +60,13 @@ type Config struct {
}
// New creates a new PocketBase instance with the default configuration.
// Use [NewWithConfig()] if you want to provide a custom configuration.
// Use [NewWithConfig] if you want to provide a custom configuration.
//
// Note that the application will not be initialized/bootstrapped yet,
// aka. DB connections, migrations, app settings, etc. will not be accessible.
// Everything will be initialized when [Start()] is executed.
// If you want to initialize the application before calling [Start()],
// then you'll have to manually call [Bootstrap()].
// Everything will be initialized when [PocketBase.Start()] is executed.
// If you want to initialize the application before calling [PocketBase.Start()],
// then you'll have to manually call [PocketBase.Bootstrap()].
func New() *PocketBase {
_, isUsingGoRun := inspectRuntime()
@ -79,9 +79,9 @@ func New() *PocketBase {
//
// Note that the application will not be initialized/bootstrapped yet,
// aka. DB connections, migrations, app settings, etc. will not be accessible.
// Everything will be initialized when [Start()] is executed.
// If you want to initialize the application before calling [Start()],
// then you'll have to manually call [Bootstrap()].
// Everything will be initialized when [PocketBase.Start()] is executed.
// If you want to initialize the application before calling [PocketBase..Start()],
// then you'll have to manually call [PocketBase.Bootstrap()].
func NewWithConfig(config Config) *PocketBase {
// initialize a default data directory based on the executable baseDir
if config.DefaultDataDir == "" {

View File

@ -345,12 +345,33 @@ func (e *Event) InternalServerError(message string, errData any) *ApiError {
const DefaultMaxMemory = 32 << 20 // 32mb
// Supports the following content-types:
// BindBody unmarshal the request body into the provided dst.
//
// dst must be either a struct pointer or map[string]any.
//
// The rules how the body will be scanned depends on the request Content-Type.
//
// Currently the following Content-Types are supported:
// - application/json
// - multipart/form-data
// - application/x-www-form-urlencoded
// - text/xml, application/xml
// - multipart/form-data, application/x-www-form-urlencoded
//
// Respectively the following struct tags are supported (again, which one will be used depends on the Content-Type):
// - "json" (json body)- uses the builtin Go json package for unmarshaling.
// - "xml" (xml body) - uses the builtin Go xml package for unmarshaling.
// - "form" (form data) - utilizes the custom [router.UnmarshalRequestData] method.
//
// NB! When dst is a struct make sure that it doesn't have public fields
// that shouldn't be bindable and it is advisible such fields to be unexported
// or have a separate struct just for the binding. For example:
//
// data := struct{
// somethingPrivate string
//
// Title string `json:"title" form:"title"`
// Total int `json:"total" form:"total"`
// }
// err := e.BindBody(&data)
func (e *Event) BindBody(dst any) error {
if e.Request.ContentLength == 0 {
return nil