Documentation
¶
Index ¶
- func DefineBuiltinActions(engine it.DynamicResourceEngine, only ...it.CrudAction) error
- func NewDynamicResourceEngine(param NewEngineParam) it.DynamicResourceEngine
- func NewDynamicResourceRepository(param NewRepositoryParam) it.DynamicResourceRepository
- func NewDynamicResourceService(param NewServiceParam) it.DynamicResourceService
- func NewDynamicRestApi(engine it.DynamicResourceEngine) it.DynamicRestApi
- func WithComputedFields(base it.DynamicResourceService, sourceSearch SourceSearchFn, ...) it.DynamicResourceService
- func WithdrawOrgScoping(engine it.DynamicResourceEngine) error
- type DynamicResourceEngineImpl
- func (this *DynamicResourceEngineImpl) Action(actionName string) (it.DynamicActionDefinition, bool)
- func (this *DynamicResourceEngineImpl) ActionNames() []string
- func (this *DynamicResourceEngineImpl) AssertComputedFunctionsDefined() error
- func (this *DynamicResourceEngineImpl) ComputedFieldFunction(name string) (it.ComputedFieldFn, bool)
- func (this *DynamicResourceEngineImpl) DefaultPermissionScope() requestguard.ResourceScope
- func (this *DynamicResourceEngineImpl) DefineAction(definition it.DynamicActionDefinition) error
- func (this *DynamicResourceEngineImpl) DefineComputedFieldFunction(name string, fn it.ComputedFieldFn) error
- func (this *DynamicResourceEngineImpl) ExecuteAction(ctx corectx.Context, actionName string, params dmodel.DynamicFields) (result *it.ActionResult, err error)
- func (this *DynamicResourceEngineImpl) ModifyAction(delta it.DynamicActionDelta) error
- func (this *DynamicResourceEngineImpl) ResourceName() string
- func (this *DynamicResourceEngineImpl) ResourceRepository() it.DynamicResourceRepository
- func (this *DynamicResourceEngineImpl) ResourceService() it.DynamicResourceService
- func (this *DynamicResourceEngineImpl) RestApi() it.DynamicRestApi
- func (this *DynamicResourceEngineImpl) RoutePath() string
- func (this *DynamicResourceEngineImpl) Schema() *dmodel.ModelSchema
- func (this *DynamicResourceEngineImpl) SetDefaultPermissionScope(scope requestguard.ResourceScope)
- func (this *DynamicResourceEngineImpl) SetResourceRepository(repository it.DynamicResourceRepository)
- func (this *DynamicResourceEngineImpl) SetResourceService(service it.DynamicResourceService)
- func (this *DynamicResourceEngineImpl) SetRestApi(restApi it.DynamicRestApi)
- func (this *DynamicResourceEngineImpl) SetRoutePath(path string)
- type DynamicResourceRepositoryImpl
- func (this *DynamicResourceRepositoryImpl) BeginTransaction(ctx corectx.Context) (database.DbTransaction, error)
- func (this *DynamicResourceRepositoryImpl) DeleteOne(ctx corectx.Context, keys dmodel.DynamicFields) (*dyn.OpResult[dyn.MutateResultData], error)
- func (this *DynamicResourceRepositoryImpl) Exists(ctx corectx.Context, keys []dmodel.DynamicFields) (*dyn.OpResult[dyn.RepoExistsResult], error)
- func (this *DynamicResourceRepositoryImpl) FindByKeys(ctx corectx.Context, keys dmodel.DynamicFields) (*dyn.OpResult[dmodel.DynamicFields], error)
- func (this *DynamicResourceRepositoryImpl) GetBaseRepo() dyn.BaseDynamicRepository
- func (this *DynamicResourceRepositoryImpl) GetOne(ctx corectx.Context, param dyn.RepoGetOneParam) (*dyn.OpResult[dmodel.DynamicFields], error)
- func (this *DynamicResourceRepositoryImpl) Insert(ctx corectx.Context, data dmodel.DynamicFields) (*dyn.OpResult[int], error)
- func (this *DynamicResourceRepositoryImpl) Search(ctx corectx.Context, param dyn.RepoSearchParam) (*dyn.OpResult[dyn.PagedResultData[dmodel.DynamicFields]], error)
- func (this *DynamicResourceRepositoryImpl) Update(ctx corectx.Context, data dmodel.DynamicFields) (*dyn.OpResult[dyn.MutateResultData], error)
- type DynamicResourceServiceImpl
- func (this *DynamicResourceServiceImpl) Create(ctx corectx.Context, params dmodel.DynamicFields) (*dyn.OpResult[dmodel.DynamicFields], error)
- func (this *DynamicResourceServiceImpl) Delete(ctx corectx.Context, params dmodel.DynamicFields) (*dyn.OpResult[dyn.MutateResultData], error)
- func (this *DynamicResourceServiceImpl) Exists(ctx corectx.Context, params dmodel.DynamicFields) (*dyn.OpResult[dyn.ExistsResultData], error)
- func (this *DynamicResourceServiceImpl) GetById(ctx corectx.Context, params dmodel.DynamicFields) (*dyn.OpResult[dyn.SingleResultData[dmodel.DynamicFields]], error)
- func (this *DynamicResourceServiceImpl) GetOne(ctx corectx.Context, params dmodel.DynamicFields) (*dyn.OpResult[dyn.SingleResultData[dmodel.DynamicFields]], error)
- func (this *DynamicResourceServiceImpl) Repository() it.DynamicResourceRepository
- func (this *DynamicResourceServiceImpl) Schema() *dmodel.ModelSchema
- func (this *DynamicResourceServiceImpl) Search(ctx corectx.Context, params dmodel.DynamicFields) (*dyn.OpResult[dyn.PagedResultData[dmodel.DynamicFields]], error)
- func (this *DynamicResourceServiceImpl) SetArchived(ctx corectx.Context, params dmodel.DynamicFields) (*dyn.OpResult[dyn.MutateResultData], error)
- func (this *DynamicResourceServiceImpl) Update(ctx corectx.Context, params dmodel.DynamicFields) (*dyn.OpResult[dyn.MutateResultData], error)
- type DynamicRestApiImpl
- type FunctionInvokeFn
- type NewEngineParam
- type NewRepositoryParam
- type NewServiceParam
- type SourceSearchFn
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DefineBuiltinActions ¶
func DefineBuiltinActions(engine it.DynamicResourceEngine, only ...it.CrudAction) error
DefineBuiltinActions registers the CRUD actions every resource gets for free. The registry calls it right after constructing an engine.
An empty `only` defines all of them; a non-empty list defines just those, so that an engine can be created without the actions its resource has no business exposing. An action left out has no REST route and is refused by the resource service.
They declare no ParamSchema: the crud helpers the service delegates to already validate the params against the resource schema, inject the service fields, check the unique constraints and enforce the etag on update. Declaring a schema here would validate twice. A module that needs a pipeline-level schema on a built-in can still add one with ModifyAction; the second validation is idempotent on already-sanitized params.
func NewDynamicResourceEngine ¶
func NewDynamicResourceEngine(param NewEngineParam) it.DynamicResourceEngine
func NewDynamicResourceRepository ¶
func NewDynamicResourceRepository(param NewRepositoryParam) it.DynamicResourceRepository
func NewDynamicResourceService ¶
func NewDynamicResourceService(param NewServiceParam) it.DynamicResourceService
func NewDynamicRestApi ¶
func NewDynamicRestApi(engine it.DynamicResourceEngine) it.DynamicRestApi
func WithComputedFields ¶
func WithComputedFields( base it.DynamicResourceService, sourceSearch SourceSearchFn, invokeFunction FunctionInvokeFn, defaultSearchFields []string, ) it.DynamicResourceService
WithComputedFields decorates a resource service so declared computed fields evaluate on every read and reject every write — the generic replacement for the per-module Search/GetById/GetOne overrides modules used to hand-roll for virtual fields. Wrapping is unconditional and costs nothing for a schema without computed fields: the eval planner returns nil and every call passes straight through.
defaultSearchFields must be the same list the wrapped service falls back to when a search names no fields — otherwise a defaulted listing evaluates the wrong set of computed fields and reads operands the projection never selected.
func WithdrawOrgScoping ¶
func WithdrawOrgScoping(engine it.DynamicResourceEngine) error
WithdrawOrgScoping opts every action currently defined on the engine out of org scoping.
It exists for a resource whose org_id is *optional*, where NULL means "global" or "domain-scoped" rather than "belongs to no org" - iam_role and iam_entitlement are the two in the tree. Requiring ?org_id= on those would make every domain-scoped row unreachable, which is a silent under-grant rather than a visible error.
Call it after the module has defined its own actions, so that those are covered too. It is deliberately all-or-nothing: a resource that needs scoping on some actions and not others should say so per action, where the reason can be written down next to the exception.
Types ¶
type DynamicResourceEngineImpl ¶
type DynamicResourceEngineImpl struct {
// contains filtered or unexported fields
}
DynamicResourceEngineImpl is the generic CRUD machinery of one resource. It owns the action definitions and the three subengines that carry them out.
func (*DynamicResourceEngineImpl) Action ¶
func (this *DynamicResourceEngineImpl) Action(actionName string) (it.DynamicActionDefinition, bool)
func (*DynamicResourceEngineImpl) ActionNames ¶
func (this *DynamicResourceEngineImpl) ActionNames() []string
func (*DynamicResourceEngineImpl) AssertComputedFunctionsDefined ¶
func (this *DynamicResourceEngineImpl) AssertComputedFunctionsDefined() error
AssertComputedFunctionsDefined matches the schema's declarations against what was registered.
It reports every missing function at once rather than the first, so a module adding several fields fixes them in one pass instead of rediscovering them one boot at a time.
func (*DynamicResourceEngineImpl) ComputedFieldFunction ¶
func (this *DynamicResourceEngineImpl) ComputedFieldFunction(name string) (it.ComputedFieldFn, bool)
func (*DynamicResourceEngineImpl) DefaultPermissionScope ¶
func (this *DynamicResourceEngineImpl) DefaultPermissionScope() requestguard.ResourceScope
func (*DynamicResourceEngineImpl) DefineAction ¶
func (this *DynamicResourceEngineImpl) DefineAction(definition it.DynamicActionDefinition) error
DefineAction registers a new action, rejecting duplicates so that two modules cannot silently overwrite each other's behavior. Use ModifyAction to change an existing one.
func (*DynamicResourceEngineImpl) DefineComputedFieldFunction ¶
func (this *DynamicResourceEngineImpl) DefineComputedFieldFunction( name string, fn it.ComputedFieldFn, ) error
DefineComputedFieldFunction registers the implementation of a "function"-kind computed field, rejecting duplicates for the same reason DefineAction does: two modules must not silently overwrite each other's behaviour.
func (*DynamicResourceEngineImpl) ExecuteAction ¶
func (this *DynamicResourceEngineImpl) ExecuteAction( ctx corectx.Context, actionName string, params dmodel.DynamicFields, ) (result *it.ActionResult, err error)
ExecuteAction runs the full pipeline of the named action.
A violation the caller can fix (missing permission, invalid params, missing record) comes back as ClientErrors inside the result, never as a Go error, so that the REST layer answers 400 rather than 500. A Go error means the request could not be processed.
func (*DynamicResourceEngineImpl) ModifyAction ¶
func (this *DynamicResourceEngineImpl) ModifyAction(delta it.DynamicActionDelta) error
ModifyAction overrides the provided fields of an existing action, leaving the rest intact.
func (*DynamicResourceEngineImpl) ResourceName ¶
func (this *DynamicResourceEngineImpl) ResourceName() string
func (*DynamicResourceEngineImpl) ResourceRepository ¶
func (this *DynamicResourceEngineImpl) ResourceRepository() it.DynamicResourceRepository
func (*DynamicResourceEngineImpl) ResourceService ¶
func (this *DynamicResourceEngineImpl) ResourceService() it.DynamicResourceService
func (*DynamicResourceEngineImpl) RestApi ¶
func (this *DynamicResourceEngineImpl) RestApi() it.DynamicRestApi
func (*DynamicResourceEngineImpl) RoutePath ¶
func (this *DynamicResourceEngineImpl) RoutePath() string
func (*DynamicResourceEngineImpl) Schema ¶
func (this *DynamicResourceEngineImpl) Schema() *dmodel.ModelSchema
func (*DynamicResourceEngineImpl) SetDefaultPermissionScope ¶
func (this *DynamicResourceEngineImpl) SetDefaultPermissionScope(scope requestguard.ResourceScope)
func (*DynamicResourceEngineImpl) SetResourceRepository ¶
func (this *DynamicResourceEngineImpl) SetResourceRepository(repository it.DynamicResourceRepository)
func (*DynamicResourceEngineImpl) SetResourceService ¶
func (this *DynamicResourceEngineImpl) SetResourceService(service it.DynamicResourceService)
func (*DynamicResourceEngineImpl) SetRestApi ¶
func (this *DynamicResourceEngineImpl) SetRestApi(restApi it.DynamicRestApi)
func (*DynamicResourceEngineImpl) SetRoutePath ¶
func (this *DynamicResourceEngineImpl) SetRoutePath(path string)
type DynamicResourceRepositoryImpl ¶
type DynamicResourceRepositoryImpl struct {
// contains filtered or unexported fields
}
DynamicResourceRepositoryImpl is the schema-agnostic counterpart of the hand-written repositories such as iam's UserDynamicRepository: it delegates to the same baserepo helpers, but speaks DynamicFields instead of a typed domain model.
func (*DynamicResourceRepositoryImpl) BeginTransaction ¶
func (this *DynamicResourceRepositoryImpl) BeginTransaction(ctx corectx.Context) (database.DbTransaction, error)
func (*DynamicResourceRepositoryImpl) DeleteOne ¶
func (this *DynamicResourceRepositoryImpl) DeleteOne( ctx corectx.Context, keys dmodel.DynamicFields, ) (*dyn.OpResult[dyn.MutateResultData], error)
func (*DynamicResourceRepositoryImpl) Exists ¶
func (this *DynamicResourceRepositoryImpl) Exists( ctx corectx.Context, keys []dmodel.DynamicFields, ) (*dyn.OpResult[dyn.RepoExistsResult], error)
func (*DynamicResourceRepositoryImpl) FindByKeys ¶
func (this *DynamicResourceRepositoryImpl) FindByKeys( ctx corectx.Context, keys dmodel.DynamicFields, ) (*dyn.OpResult[dmodel.DynamicFields], error)
FindByKeys fetches the single record identified by the given keys, reading every column of the schema.
func (*DynamicResourceRepositoryImpl) GetBaseRepo ¶
func (this *DynamicResourceRepositoryImpl) GetBaseRepo() dyn.BaseDynamicRepository
func (*DynamicResourceRepositoryImpl) GetOne ¶
func (this *DynamicResourceRepositoryImpl) GetOne( ctx corectx.Context, param dyn.RepoGetOneParam, ) (*dyn.OpResult[dmodel.DynamicFields], error)
func (*DynamicResourceRepositoryImpl) Insert ¶
func (this *DynamicResourceRepositoryImpl) Insert( ctx corectx.Context, data dmodel.DynamicFields, ) (*dyn.OpResult[int], error)
func (*DynamicResourceRepositoryImpl) Search ¶
func (this *DynamicResourceRepositoryImpl) Search( ctx corectx.Context, param dyn.RepoSearchParam, ) (*dyn.OpResult[dyn.PagedResultData[dmodel.DynamicFields]], error)
func (*DynamicResourceRepositoryImpl) Update ¶
func (this *DynamicResourceRepositoryImpl) Update( ctx corectx.Context, data dmodel.DynamicFields, ) (*dyn.OpResult[dyn.MutateResultData], error)
type DynamicResourceServiceImpl ¶
type DynamicResourceServiceImpl struct {
// contains filtered or unexported fields
}
DynamicResourceServiceImpl is the schema-agnostic merge of what a feature module splits between its application service and its domain service, minus the permission checks, which the engine pipeline performs before calling in here.
A module extends it by embedding it in its own service struct and installing that struct with Engine.SetResourceService.
func (*DynamicResourceServiceImpl) Create ¶
func (this *DynamicResourceServiceImpl) Create( ctx corectx.Context, params dmodel.DynamicFields, ) (*dyn.OpResult[dmodel.DynamicFields], error)
func (*DynamicResourceServiceImpl) Delete ¶
func (this *DynamicResourceServiceImpl) Delete( ctx corectx.Context, params dmodel.DynamicFields, ) (*dyn.OpResult[dyn.MutateResultData], error)
func (*DynamicResourceServiceImpl) Exists ¶
func (this *DynamicResourceServiceImpl) Exists( ctx corectx.Context, params dmodel.DynamicFields, ) (*dyn.OpResult[dyn.ExistsResultData], error)
func (*DynamicResourceServiceImpl) GetById ¶
func (this *DynamicResourceServiceImpl) GetById( ctx corectx.Context, params dmodel.DynamicFields, ) (*dyn.OpResult[dyn.SingleResultData[dmodel.DynamicFields]], error)
func (*DynamicResourceServiceImpl) GetOne ¶
func (this *DynamicResourceServiceImpl) GetOne( ctx corectx.Context, params dmodel.DynamicFields, ) (*dyn.OpResult[dyn.SingleResultData[dmodel.DynamicFields]], error)
GetOne fetches one record by any unique key present in params. Every param that names a schema column is used as an equality condition, so callers must pass only key fields.
func (*DynamicResourceServiceImpl) Repository ¶
func (this *DynamicResourceServiceImpl) Repository() it.DynamicResourceRepository
Repository exposes the repository to embedding services.
func (*DynamicResourceServiceImpl) Schema ¶
func (this *DynamicResourceServiceImpl) Schema() *dmodel.ModelSchema
func (*DynamicResourceServiceImpl) Search ¶
func (this *DynamicResourceServiceImpl) Search( ctx corectx.Context, params dmodel.DynamicFields, ) (*dyn.OpResult[dyn.PagedResultData[dmodel.DynamicFields]], error)
func (*DynamicResourceServiceImpl) SetArchived ¶
func (this *DynamicResourceServiceImpl) SetArchived( ctx corectx.Context, params dmodel.DynamicFields, ) (*dyn.OpResult[dyn.MutateResultData], error)
func (*DynamicResourceServiceImpl) Update ¶
func (this *DynamicResourceServiceImpl) Update( ctx corectx.Context, params dmodel.DynamicFields, ) (*dyn.OpResult[dyn.MutateResultData], error)
type DynamicRestApiImpl ¶
type DynamicRestApiImpl struct {
// contains filtered or unexported fields
}
DynamicRestApiImpl exposes one resource over HTTP. Every endpoint goes through Engine.ExecuteAction rather than calling the service directly, so that a permission check always runs and a ModifyAction override takes effect on the REST surface too.
func (*DynamicRestApiImpl) RegisterRoutes ¶
func (this *DynamicRestApiImpl) RegisterRoutes(route *echo.Group, middlewares ...echo.MiddlewareFunc)
RegisterRoutes adds every REST-exposed action of the resource to the given group. An action opts in by declaring an ActionType, which decides the HTTP method, and a RestPath relative to the resource base.
The order matters: echo matches in registration order, so the literal "meta/schema" and "exists" paths must be registered before the ":id" patterns that would swallow them. routableActions sorts by specificity so that holds without hand-written ordering.
type FunctionInvokeFn ¶
type FunctionInvokeFn func( ctx corectx.Context, schemaName string, functionName string, fieldName string, rows []dmodel.DynamicFields, ) ([]any, error)
FunctionInvokeFn runs a registered computed-field function over a page of rows. Supplied by the registry, which knows how to reach the engine holding the function registry — the same indirection SourceSearchFn uses to reach another engine's repository.
type NewEngineParam ¶
type NewEngineParam struct {
Schema *dmodel.ModelSchema
Repository it.DynamicResourceRepository
Service it.DynamicResourceService
}
NewEngineParam carries what an engine needs at construction time.
type NewRepositoryParam ¶
type NewRepositoryParam struct {
Client orm.DbClient
ConfigSvc config.ConfigService
QueryBuilder orm.QueryBuilder
Logger logging.LoggerService
NewBaseRepoFn dyn.NewBaseDynamicRepositoryFn
Schema *dmodel.ModelSchema
}
NewRepositoryParam carries the core services a repository needs. The registry fills it once and reuses it for every engine it builds.
type NewServiceParam ¶
type NewServiceParam struct {
Schema *dmodel.ModelSchema
Repository it.DynamicResourceRepository
// DefaultFields is returned by a search that specifies neither fields nor a resolvable
// view. When empty, every column of the schema is returned.
DefaultFields []string
// CrudActions is the engine's action allow-list. Empty means every action is supported.
CrudActions []it.CrudAction
// ActionLookup resolves an action definition at call time, which is how the service
// reaches the validator hooks a module attached with ModifyAction. The service is built
// before the engine that will own it exists, so the lookup has to be deferred - the same
// reason invokeComputedFunction defers its own.
ActionLookup func(actionName string) (it.DynamicActionDefinition, bool)
}
NewServiceParam carries what a resource service needs to work.
type SourceSearchFn ¶
type SourceSearchFn func( ctx corectx.Context, schemaName string, keyColumn string, keys []any, fields []string, ) ([]dmodel.DynamicFields, error)
SourceSearchFn fetches rows of another resource for a batched related-field read. Supplied by the registry, which knows how to reach every engine's repository.