feat(11.1-04): add the Database section and the core Services pages

- docs/database: models, migrations, queries and pagination, relations,
  casts and validation, attachments and transactions (lagoon.Transaction,
  lagoon.AfterCommit, nested savepoints, lagoon.OnDatabase)
- docs/services: configuration, events, routing with auth groups, rate
  limiting, authentication, the OAuth server, mail and localization
- runnable Examples for lagoon, attach, compass, surf, wire, bouncer,
  wristband, postcard, phrasebook and festival; lagoon TestDocs* regions
  run on the package's Postgres harness through DocsDB
- 15 new required pages
This commit is contained in:
Jakub Zych
2026-09-30 22:59:25 +02:00
parent 9d37d56486
commit efb35a2d35
28 changed files with 3138 additions and 0 deletions

View File

@@ -33,3 +33,60 @@ func ExampleBus_Fire() {
// notify subscribers of Hello
// index Hello
}
// PostFormExtended gathers extra fields other plugins add to the post form.
type PostFormExtended struct {
fields map[string]any
}
func (e *PostFormExtended) Collected() map[string]any { return e.fields }
func ExampleBus_Collect() {
bus := festival.New()
bus.Listen("acme.seo", func(ctx context.Context, e *PostFormExtended) error {
e.fields = map[string]any{"meta_title": "text"}
return nil
})
bus.Listen("acme.gallery", func(ctx context.Context, e *PostFormExtended) error {
e.fields = map[string]any{"cover": "fileupload"}
return nil
})
fields, err := bus.Collect(context.Background(), &PostFormExtended{})
fmt.Println(fields, err)
// Output: map[cover:fileupload meta_title:text] <nil>
}
// SlugResolving asks plugins to resolve a URL slug; the first one that
// knows it handles the event.
type SlugResolving struct {
Slug string
Found string
}
func (e *SlugResolving) IsHandled() bool { return e.Found != "" }
func ExampleBus_UntilHandled() {
bus := festival.New()
bus.ListenPriority("acme.pages", 10, func(ctx context.Context, e *SlugResolving) error {
if e.Slug == "about" {
e.Found = "page"
}
return nil
})
bus.Listen("acme.blog", func(ctx context.Context, e *SlugResolving) error {
fmt.Println("acme.blog asked for", e.Slug)
e.Found = "post"
return nil
})
for _, slug := range []string{"about", "hello-world"} {
e := &SlugResolving{Slug: slug}
handled, err := bus.UntilHandled(context.Background(), e)
fmt.Println(slug, handled, e.Found, err)
}
// Output:
// about true page <nil>
// acme.blog asked for hello-world
// hello-world true post <nil>
}