feat(12.2-01): add deferred:purge, its daily framework schedule and relation child hooks
- deferred:purge [--days] in lagoon.RuntimeCommands (purge_days, default 5)
- lagoon.FrameworkSchedule entry at purge_at (default 03:00, empty disables)
- conga prepends framework entries as summercms.lagoon[i]:<command>
- pact.Relation{Before,After}{Create,Update,Delete} optional hooks
- lagoon, conga and pact READMEs, scheduling and setup docs
This commit is contained in:
@@ -15,7 +15,7 @@ Capability interfaces that compiled plugins implement to contribute routes, conf
|
||||
- Backend registration data: `pact.Permission`, `pact.NavigationItem` and `pact.SettingsItem`, exposed through `pact.HasPermissions`, `pact.HasNavigation` and `pact.HasSettings`.
|
||||
- Admin controller contracts: `pact.AdminController`, `pact.HasAdminControllers`, `pact.AdminAssets` (embedded Winter-shaped admin YAML), `pact.AdminPermissioned` and `pact.AdminRecordSource`.
|
||||
- Admin extension contracts, so a plugin extends the compiled admin SPA without a Node build: `pact.AdminClientAssets` (per-controller JS and CSS from the plugin's embedded `assets/` tree, Winter's `addJs`/`addCss`), `pact.HasAdminActions` with `pact.AdminAction`, `pact.AdminActionInput` and `pact.AdminActionResult` (named toolbar and widget actions whose routes, CSRF check, permissions and record scoping the framework owns), and `pact.AdminPartialData` (the curated view model a partial template renders).
|
||||
- Optional admin hooks a controller or model can implement: list and form query scoping (`pact.ListExtendQuery`, `pact.FormExtendQuery`), create, update and delete hooks (`pact.FormBeforeCreate`, `pact.FormAfterUpdate`, `pact.FormBeforeDelete` and their siblings), relation hooks (`pact.RelationExtendManageQuery`, `pact.RelationExtendOptionsQuery`, `pact.RelationBeforeLink`), filter scopes (`pact.FilterScope`, `pact.FilterOptions`) and dropdown options (`pact.DropdownOptionsProvider`).
|
||||
- Optional admin hooks a controller or model can implement: list and form query scoping (`pact.ListExtendQuery`, `pact.FormExtendQuery`), create, update and delete hooks (`pact.FormBeforeCreate`, `pact.FormAfterUpdate`, `pact.FormBeforeDelete` and their siblings), relation hooks (`pact.RelationExtendManageQuery`, `pact.RelationExtendOptionsQuery`, `pact.RelationBeforeLink`), relation child hooks around creating, updating and deleting a related record (`pact.RelationBeforeCreate`, `pact.RelationAfterCreate`, `pact.RelationBeforeUpdate`, `pact.RelationAfterUpdate`, `pact.RelationBeforeDelete`, `pact.RelationAfterDelete`), filter scopes (`pact.FilterScope`, `pact.FilterOptions`) and dropdown options (`pact.DropdownOptionsProvider`).
|
||||
- A background job contract (`pact.Job`, `pact.JobArgs`) that does not depend on any queue library.
|
||||
- A schedule contract: `pact.HasSchedule` returns `pact.ScheduledCommand` entries (a registered command name, its arguments and a `pact.Cadence` built with `pact.Daily`, `pact.DailyAt` or `pact.Every`), the Go form of WinterCMS `registerSchedule`. It does not depend on any queue library either.
|
||||
- `pact.OptionalMessage`, a service an optional plugin can publish so others integrate with it without importing its package.
|
||||
@@ -111,6 +111,13 @@ func (p *Plugin) Schedule() []pact.ScheduledCommand {
|
||||
| `pact.HasAdminActions` | Registers a controller's actions for `toolbar.buttons` and `type: widget` fields. |
|
||||
| `pact.AdminPartialData` | Supplies the view model a controller partial template renders; never the GORM model. |
|
||||
| `pact.FilterScope` | Model scopes a list filter may call, limited to an exact allow list. |
|
||||
| `pact.RelationBeforeLink` | Optional controller hook that checks or fills pivot columns before a relation link is written. |
|
||||
| `pact.RelationBeforeCreate` | Optional controller hook run in the write transaction before a relation manager creates a related record. |
|
||||
| `pact.RelationAfterCreate` | Optional controller hook run after a relation manager creates a related record, before the commit. |
|
||||
| `pact.RelationBeforeUpdate` | Optional controller hook run in the write transaction before a relation manager updates a related record. |
|
||||
| `pact.RelationAfterUpdate` | Optional controller hook run after a relation manager updates a related record, before the commit. |
|
||||
| `pact.RelationBeforeDelete` | Optional controller hook run in the write transaction before a relation manager deletes a related record. |
|
||||
| `pact.RelationAfterDelete` | Optional controller hook run after a relation manager deletes a related record, before the commit. |
|
||||
| `pact.Option` | One dropdown choice (value and label). |
|
||||
|
||||
## Dependencies
|
||||
|
||||
@@ -391,6 +391,51 @@ type RelationBeforeLink interface {
|
||||
RelationBeforeLink(ctx context.Context, relation string, parent, related any, pivot map[string]any) error
|
||||
}
|
||||
|
||||
// The six relation child hooks below are optional admin-controller
|
||||
// capabilities for a relation manager that creates, updates or deletes
|
||||
// related records. Before hooks run inside the child write's transaction
|
||||
// before the row is written; After hooks run after the write and before the
|
||||
// commit. parent is the loaded parent record, or a fresh record with a zero
|
||||
// key while the parent is not saved yet (deferral). child is the related
|
||||
// record being written. An error rolls the write back and the admin API
|
||||
// answers its opaque lifecycle error.
|
||||
|
||||
// RelationBeforeCreate optionally runs before a related record is created
|
||||
// through a relation manager.
|
||||
type RelationBeforeCreate interface {
|
||||
RelationBeforeCreate(ctx context.Context, relation string, parent, child any) error
|
||||
}
|
||||
|
||||
// RelationAfterCreate optionally runs after a related record is created
|
||||
// through a relation manager, before the commit.
|
||||
type RelationAfterCreate interface {
|
||||
RelationAfterCreate(ctx context.Context, relation string, parent, child any) error
|
||||
}
|
||||
|
||||
// RelationBeforeUpdate optionally runs before a related record is updated
|
||||
// through a relation manager.
|
||||
type RelationBeforeUpdate interface {
|
||||
RelationBeforeUpdate(ctx context.Context, relation string, parent, child any) error
|
||||
}
|
||||
|
||||
// RelationAfterUpdate optionally runs after a related record is updated
|
||||
// through a relation manager, before the commit.
|
||||
type RelationAfterUpdate interface {
|
||||
RelationAfterUpdate(ctx context.Context, relation string, parent, child any) error
|
||||
}
|
||||
|
||||
// RelationBeforeDelete optionally runs before a related record is deleted
|
||||
// through a relation manager.
|
||||
type RelationBeforeDelete interface {
|
||||
RelationBeforeDelete(ctx context.Context, relation string, parent, child any) error
|
||||
}
|
||||
|
||||
// RelationAfterDelete optionally runs after a related record is deleted
|
||||
// through a relation manager, before the commit.
|
||||
type RelationAfterDelete interface {
|
||||
RelationAfterDelete(ctx context.Context, relation string, parent, child any) error
|
||||
}
|
||||
|
||||
// FilterScope is the model capability a config_filter scope name may call.
|
||||
// FilterScopes is the exact, case-sensitive set of names; request text never
|
||||
// selects a method outside that set.
|
||||
|
||||
Reference in New Issue
Block a user