Documentation
¶
Overview ¶
Package fetch provides data loading utilities for GoWebComponents.
The package exposes these public hook styles:
- UseResource for typed, context-aware async loading in non-trivial components
- UseCachedResource for shared cached async state with deduplication and invalidation
- UseQuery and UseInfiniteQuery for tag-aware cache invalidation, paginated data, and optimistic rollback helpers
- UseWebSocket and UseEventSource for bounded browser realtime streams
- OpenMutationQueue for durable offline write replay in browser storage
- UseFetch (deprecated) for low-level raw fetch state around a URL
UseResource is the preferred choice in nearly all cases: it gives typed results, cancellation, dependency-driven reloads, and loader logic beyond a single raw fetch call. UseFetch is deprecated — prefer UseResource (or ui.UseQuery for cached, tag-invalidated data); it remains only for legacy callers.
Basic usage:
import (
"context"
"github.com/monstercameron/GoWebComponents/v4/fetch"
)
func UserList() ui.Node {
resource := fetch.UseResource(func(ctx context.Context) (string, error) {
return fetchUsers(ctx) // your typed loader
})
state := resource.Get()
if state.Loading {
return html.Div(html.Props{}, html.P(html.Props{}, html.Text("Loading...")))
}
if state.Err != nil {
return html.Div(html.Props{}, html.P(html.Props{}, html.Text("Error: "+state.Err.Error())))
}
refresh := ui.UseEvent(func() {
resource.Reload()
})
return html.Div(html.Props{},
html.H1(html.Props{}, html.Text("Users")),
html.Pre(html.Props{}, html.Text(state.Data)),
html.Button(html.Props{OnClick: refresh}, html.Text("Refresh")),
)
}
Available functions:
- UseResource: Typed async resource hook for context-aware loaders
- UseCachedResource: Shared typed cache hook with stale-while-revalidate behavior
- UseQuery: Tag-aware cached query hook with optimistic rollback helpers
- UseInfiniteQuery: Cached paginated query hook for load-more and infinite-scroll views
- InvalidateQueryTag / InvalidateQueryTags: Mark related cached queries stale by tag
- UseWebSocket: Bounded WebSocket hook with reconnect, backoff, and optional heartbeat
- UseEventSource: Bounded EventSource hook with reconnect, backoff, and heartbeat timeout tracking
- OpenMutationQueue: Durable queued write storage plus replay helpers for offline workflows
- Fetch: Low-level fetch function returning a channel for manual control
- UseFetch (deprecated): Raw fetch state hook — prefer UseResource
The UseFetch hook (deprecated — prefer UseResource):
- Manages loading, error, and raw response data states
- Returns a handle with Get and Refetch methods
- Leaves response parsing and higher-level orchestration under caller control
The UseResource hook:
- Accepts a loader of type func(context.Context) (T, error)
- Returns a typed handle with Get, Reload, and Cancel methods
- Cancels in-flight work when the component unmounts or dependencies change
The UseCachedResource hook:
- Accepts a stable cache key plus a loader of type func(context.Context) (T, error)
- Returns a typed handle with Get, Reload, Cancel, Invalidate, Set, and Update methods
- Reuses cached values across components, deduplicates in-flight reloads, and keeps ready data visible during background refreshes
UseQuery is the higher-level cache API for application data. It keeps the same typed state shape as UseCachedResource, adds normalized tags for invalidating related queries together, and exposes OptimisticUpdate rollback handles for mutation flows. UseInfiniteQuery stores pages under one cache key and appends additional pages with LoadNext while preserving the same tag and optimistic-update behavior.
The realtime hooks:
- Return handles with bounded RealtimeState snapshots
- Keep only the newest MaxMessages and MaxErrors entries
- Reconnect with capped exponential backoff
- Compile on non-browser targets with RealtimeUnsupported state
For more control, use the Fetch function directly:
ch := fetch.Fetch("/api/data", fetch.Options{
Method: "POST",
Headers: map[string]interface{}{"Content-Type": "application/json"},
Body: `{"key": "value"}`,
})
result := <-ch
if result.Err != nil {
// Handle error
}
// Use result.Data
Index ¶
- Constants
- Variables
- func BuildFetchService() pluginruntime.FetchService
- func ConfigurePersistentCache(parseOptions PersistentCacheOptions)
- func DisposeQueryTag(parseTag string) int
- func DisposeResource(parseKey string)
- func ExecuteWithPolicy[T any](parseCtx context.Context, parsePolicy ResiliencePolicy, ...) (T, error)
- func Fetch(parseUrl string, parseOptions Options) <-chan Result
- func InvalidateQueryTag(parseTag string) int
- func InvalidateQueryTags(parseTags ...string) int
- func InvalidateResource(parseKey string)
- func IsMutationConflict(parseErr error) bool
- func LoadCached[T any](parseCtx context.Context, parseKey string, ...) (T, error)
- func LoadQuery[T any](parseCtx context.Context, parseKey string, ...) (T, error)
- func NewMutationConflict(parseErr error, parseConflict MutationConflict) error
- func QueryKeysForTag(parseTag string) []string
- func QueryTagsForKey(parseKey string) []string
- func RestoreCacheBootstrap(parsePayload ui.SSRBootstrap) error
- func ReturnChannel(parseCh <-chan Result)deprecated
- func ScopeCacheKey(parseSegments ...string) string
- func SweepCachedResources() int
- func Upload(parseCtx context.Context, parseUrl string, parseOptions Options) <-chan UploadUpdate
- type AsyncResource
- type BreakerConfig
- type BreakerState
- type CacheBootstrap
- type CacheBootstrapEntry
- type CacheOptions
- type CacheResumePolicy
- type CachedResource
- func (parseR CachedResource[T]) Cancel()
- func (parseR CachedResource[T]) Dispose()
- func (parseR CachedResource[T]) Get() CachedResourceState[T]
- func (parseR CachedResource[T]) Invalidate()
- func (parseR CachedResource[T]) OptimisticUpdate(parseFn func(T) T) OptimisticUpdate[T]
- func (parseR CachedResource[T]) Reload()
- func (parseR CachedResource[T]) Set(parseValue T)
- func (parseR CachedResource[T]) Update(parseFn func(T) T)
- type CachedResourceInspection
- type CachedResourceState
- type CircuitBreaker
- type DurableMutationRunner
- type EventSource
- type EventSourceOptions
- type HTTPError
- type InfiniteQuery
- func (parseQ InfiniteQuery[T, C]) CacheKey() string
- func (parseQ InfiniteQuery[T, C]) Cancel()
- func (parseQ InfiniteQuery[T, C]) Dispose()
- func (parseQ InfiniteQuery[T, C]) Get() InfiniteQueryState[T, C]
- func (parseQ InfiniteQuery[T, C]) Invalidate()
- func (parseQ InfiniteQuery[T, C]) LoadNext()
- func (parseQ InfiniteQuery[T, C]) OptimisticUpdate(parseFn func(InfiniteQueryData[T, C]) InfiniteQueryData[T, C]) OptimisticUpdate[InfiniteQueryData[T, C]]
- func (parseQ InfiniteQuery[T, C]) Reload()
- func (parseQ InfiniteQuery[T, C]) Set(parseValue InfiniteQueryData[T, C])
- func (parseQ InfiniteQuery[T, C]) Tags() []string
- func (parseQ InfiniteQuery[T, C]) Update(parseFn func(InfiniteQueryData[T, C]) InfiniteQueryData[T, C])
- type InfiniteQueryData
- type InfiniteQueryOptions
- type InfiniteQueryState
- type MultipartBody
- type MultipartFile
- type MutationConflict
- type MutationConflictError
- type MutationConflictHandler
- type MutationConflictResolution
- type MutationDraft
- type MutationExecutor
- type MutationQueue
- func (parseQ MutationQueue) Clear() error
- func (parseQ MutationQueue) Enqueue(parseDraft MutationDraft) (QueuedMutation, error)
- func (parseQ MutationQueue) List() ([]QueuedMutation, error)
- func (parseQ MutationQueue) Remove(parseId string) error
- func (parseQ MutationQueue) Replay(parseCtx context.Context, parseExecutor MutationExecutor) (MutationReplayReport, error)
- func (parseQ MutationQueue) ReplayWithOptions(parseCtx context.Context, parseExecutor MutationExecutor, ...) (MutationReplayReport, error)
- type MutationQueueOptions
- type MutationReplayOptions
- type MutationReplayReport
- type MutationResolutionAction
- type MutationState
- type OptimisticUpdate
- type Options
- type PersistentCacheOptions
- type Query
- func (parseQ Query[T]) CacheKey() string
- func (parseQ Query[T]) Cancel()
- func (parseQ Query[T]) Dispose()
- func (parseQ Query[T]) Get() CachedResourceState[T]
- func (parseQ Query[T]) Invalidate()
- func (parseQ Query[T]) OptimisticUpdate(parseFn func(T) T) OptimisticUpdate[T]
- func (parseQ Query[T]) Reload()
- func (parseQ Query[T]) Set(parseValue T)
- func (parseQ Query[T]) Tags() []string
- func (parseQ Query[T]) Update(parseFn func(T) T)
- type QueryOptions
- type QueryPage
- type QueryPageRequest
- type QueuedMutation
- type RealtimeError
- type RealtimeMessage
- type RealtimeState
- type RealtimeStatus
- type ResiliencePolicy
- type Resource
- type ResourceState
- type Result
- type RetryPolicy
- type State
- type UploadUpdate
- type WebSocket
- type WebSocketOptions
Constants ¶
const CacheBootstrapDataKey = "fetchCache"
Variables ¶
var ErrCircuitOpen = errors.New("fetch: circuit breaker is open")
ErrCircuitOpen is returned by ExecuteWithPolicy when the circuit breaker is in the open state and is not yet eligible to transition to half-open.
Functions ¶
func BuildFetchService ¶
func BuildFetchService() pluginruntime.FetchService
BuildFetchService returns one fetch-cache interposer service.
func ConfigurePersistentCache ¶
func ConfigurePersistentCache(parseOptions PersistentCacheOptions)
ConfigurePersistentCache sets the options for the persistent cache store, closing any existing store.
func DisposeQueryTag ¶
DisposeQueryTag clears all live cache entries registered for tag.
func DisposeResource ¶
func DisposeResource(parseKey string)
DisposeResource clears the named cached resource and drops its registry entry.
func ExecuteWithPolicy ¶
func ExecuteWithPolicy[T any](parseCtx context.Context, parsePolicy ResiliencePolicy, parseOp func(context.Context) (T, error)) (T, error)
ExecuteWithPolicy runs parseOp under the retry and circuit-breaker rules described by parsePolicy. It is generic so the caller keeps type safety without casting the result.
Execution order:
- If the circuit breaker is open, return immediately with ErrCircuitOpen.
- Call parseOp. On success, record success and return.
- On error, consult RetryIf; if it returns false, record failure and return.
- Record the failure, then sleep (respecting context cancellation).
- Repeat up to RetryPolicy.MaxAttempts times, then return the last error.
func InvalidateQueryTag ¶
InvalidateQueryTag marks all live queries with tag stale.
func InvalidateQueryTags ¶
InvalidateQueryTags marks all live queries with any supplied tag stale.
func InvalidateResource ¶
func InvalidateResource(parseKey string)
InvalidateResource marks the named cached resource stale.
func IsMutationConflict ¶
IsMutationConflict reports whether err unwraps to a MutationConflictError.
func LoadCached ¶
func LoadCached[T any](parseCtx context.Context, parseKey string, parseLoader func(context.Context) (T, error), parseOptions ...CacheOptions) (T, error)
LoadCached reuses the shared cache from imperative code such as route loaders.
func LoadQuery ¶
func LoadQuery[T any](parseCtx context.Context, parseKey string, parseLoader func(context.Context) (T, error), parseOptions ...QueryOptions) (T, error)
LoadQuery reuses the shared cache from imperative code and registers query tags.
func NewMutationConflict ¶
func NewMutationConflict(parseErr error, parseConflict MutationConflict) error
NewMutationConflict wraps err with structured conflict metadata, returning a *MutationConflictError.
func QueryKeysForTag ¶
QueryKeysForTag returns sorted cache keys registered for a tag.
func QueryTagsForKey ¶
QueryTagsForKey returns sorted tags registered for one cache key.
func RestoreCacheBootstrap ¶
func RestoreCacheBootstrap(parsePayload ui.SSRBootstrap) error
RestoreCacheBootstrap seeds shared cached resources from a UI bootstrap payload.
func ReturnChannel
deprecated
func ReturnChannel(parseCh <-chan Result)
ReturnChannel returns a fetch result channel to the pool for reuse. With the new implementation channels are one-shot, so this is a no-op kept for API compatibility.
Deprecated: channels are now one-shot and do not need to be returned. This function is a no-op and will be removed in a future release.
func ScopeCacheKey ¶
ScopeCacheKey builds a cache key namespaced under a module or feature prefix, the recommended convention for avoiding accidental cross-component sharing in the app-global cache namespace (see UseCachedResource). Empty segments are dropped, so ScopeCacheKey("billing", "invoices") returns "billing:invoices".
res := fetch.UseCachedResource(fetch.ScopeCacheKey("billing", "invoices"), loadInvoices)
Two unrelated components that both pick the bare key "list" would share one cache entry; scoping each under its own module prefix keeps them independent.
func SweepCachedResources ¶
func SweepCachedResources() int
SweepCachedResources clears expired or idle cache entries and returns the number removed.
Types ¶
type AsyncResource ¶
type AsyncResource[T any] struct { // contains filtered or unexported fields }
AsyncResource exposes the current typed resource state and lifecycle controls.
func UseResource ¶
func UseResource[T any](parseLoader func(context.Context) (T, error), parseDeps ...any) AsyncResource[T]
UseResource provides a typed async resource hook driven by a Go loader.
The loader runs on mount and whenever deps or the reload token change. It receives a context that is cancelled when the component unmounts, the dependency list changes, or Cancel is called on the returned handle.
func (AsyncResource[T]) Cancel ¶
func (parseR AsyncResource[T]) Cancel()
Cancel cancels the active resource load, if any.
func (AsyncResource[T]) Get ¶
func (parseR AsyncResource[T]) Get() ResourceState[T]
Get returns the current typed resource state.
func (AsyncResource[T]) Reload ¶
func (parseR AsyncResource[T]) Reload()
Reload starts a new resource load.
type BreakerConfig ¶
type BreakerConfig struct {
// FailureThreshold is the consecutive-failure count that trips the breaker.
FailureThreshold int
// OpenDuration is how long the breaker stays open before probing with
// half-open calls.
OpenDuration time.Duration
// HalfOpenMaxCalls is the maximum number of calls allowed in the half-open
// state before the breaker re-opens (if all half-open calls succeed, it
// instead resets to closed). Zero or negative values allow unlimited
// half-open probes until a probe records success or failure.
HalfOpenMaxCalls int
}
BreakerConfig holds the tuning parameters for a CircuitBreaker.
type BreakerState ¶
type BreakerState int
BreakerState represents the operational state of a CircuitBreaker.
const ( // StateClosed means the circuit breaker is healthy and allows all calls. StateClosed BreakerState = iota // StateOpen means the circuit breaker has tripped and fast-fails all calls. StateOpen // StateHalfOpen means the circuit breaker is probing whether the downstream // is healthy again, allowing a limited number of calls through. StateHalfOpen )
func (BreakerState) String ¶
func (parseState BreakerState) String() string
String returns the breaker state name ("closed", "open", "half-open") so the state reads cleanly in logs and %v formatting instead of as a bare integer.
type CacheBootstrap ¶
type CacheBootstrap struct {
Entries []CacheBootstrapEntry `json:"entries,omitempty"`
}
type CacheBootstrapEntry ¶
type CacheOptions ¶
type CacheResumePolicy ¶
type CacheResumePolicy string
const ( CacheResumeTrustOnce CacheResumePolicy = "trust-once" CacheResumeStaleWhileRevalidate CacheResumePolicy = "stale-while-revalidate" CacheResumeAlwaysRefetch CacheResumePolicy = "always-refetch" )
type CachedResource ¶
type CachedResource[T any] struct { // contains filtered or unexported fields }
CachedResource exposes shared cached resource state and mutation helpers.
func UseCachedResource ¶
func UseCachedResource[T any](parseKey string, parseLoader func(context.Context) (T, error), parseOptions ...CacheOptions) CachedResource[T]
UseCachedResource binds a component to an app-global cached resource keyed by parseKey, loading it through parseLoader on first use and sharing the result across every caller of the same key.
Global-namespace contract: cache keys live in one process-wide registry, not a per-component or per-module scope. Two unrelated components that choose the same key string therefore share the same cache entry, loader lifecycle, and value. This is intentional - it is how distant components share one fetch - but it means key strings are effectively global identifiers. Requesting one key with two different value types is reported as a diagnostic warning rather than silently corrupting state, so a type mismatch is visible.
Recommended convention: prefix keys with a stable module or feature name so unrelated features cannot collide. Use ScopeCacheKey to build them, for example ScopeCacheKey("billing", "invoices") instead of a bare "invoices".
func (CachedResource[T]) Cancel ¶
func (parseR CachedResource[T]) Cancel()
Cancel cancels the active cached resource load, if any.
func (CachedResource[T]) Dispose ¶
func (parseR CachedResource[T]) Dispose()
Dispose clears the cached value and removes the keyed entry from the shared registry.
func (CachedResource[T]) Get ¶
func (parseR CachedResource[T]) Get() CachedResourceState[T]
Get returns the current cached resource state.
func (CachedResource[T]) Invalidate ¶
func (parseR CachedResource[T]) Invalidate()
Invalidate marks the cached value stale and eligible for revalidation.
func (CachedResource[T]) OptimisticUpdate ¶
func (parseR CachedResource[T]) OptimisticUpdate(parseFn func(T) T) OptimisticUpdate[T]
OptimisticUpdate applies an optimistic resource update and returns a rollback handle.
func (CachedResource[T]) Reload ¶
func (parseR CachedResource[T]) Reload()
Reload starts a new cached resource load.
func (CachedResource[T]) Set ¶
func (parseR CachedResource[T]) Set(parseValue T)
Set replaces the cached value optimistically.
func (CachedResource[T]) Update ¶
func (parseR CachedResource[T]) Update(parseFn func(T) T)
Update replaces the cached value using the previous value.
type CachedResourceInspection ¶
type CachedResourceInspection struct {
Key string
Tags []string
Loading bool
Ready bool
Stale bool
LastError string
UpdatedAt time.Time
LastLoaded time.Time
SubscriberCount int
OwnerPaths []string
ResumePolicy CacheResumePolicy
}
func InspectCachedResources ¶
func InspectCachedResources() []CachedResourceInspection
InspectCachedResources returns a stable snapshot of shared cache state for diagnostics and devtools.
type CachedResourceState ¶
type CachedResourceState[T any] struct { Value T Loading bool Error error Ready bool Stale bool UpdatedAt time.Time }
CachedResourceState describes the current state of a shared cached resource.
type CircuitBreaker ¶
type CircuitBreaker struct {
// contains filtered or unexported fields
}
CircuitBreaker protects a downstream dependency by tracking consecutive failures and temporarily refusing calls once a failure threshold is crossed. The zero value is not valid; use NewCircuitBreaker.
func NewCircuitBreaker ¶
func NewCircuitBreaker(parseConfig BreakerConfig) *CircuitBreaker
NewCircuitBreaker constructs a CircuitBreaker with the supplied configuration and a real wall-clock source. Inject a synthetic clock via setNow for tests.
func (*CircuitBreaker) State ¶
func (parseB *CircuitBreaker) State() BreakerState
State returns the current BreakerState without modifying any internal fields.
type DurableMutationRunner ¶
type DurableMutationRunner[T any] func(parseOptimistic T, parseDraft MutationDraft, parseCommit func(context.Context, QueuedMutation) (T, error)) (QueuedMutation, error)
DurableMutationRunner applies a mutation that is BOTH optimistic and durable: it updates the query cache immediately (so the UI reacts now) and enqueues the write to the persistent MutationQueue (so it survives a reload or offline gap). It returns the queued entry and any enqueue error.
func UseDurableMutation ¶
func UseDurableMutation[T any](parseCache *query.Cache, parseKey string, parseQueue MutationQueue) DurableMutationRunner[T]
UseDurableMutation bridges the optimistic query cache and the durable offline MutationQueue, which previously lived in separate packages with no link (the audit's FA2 gap). The returned runner: (1) durably enqueues the draft so the write is never lost; (2) applies the optimistic value to the cache and re-renders; (3) runs commit in the background — on success it clears the queue entry and commits the authoritative value, on failure it rolls the cache back and LEAVES the entry queued for later replay via MutationQueue.Replay. One call gives you optimistic UI, offline durability, and automatic reconciliation.
run := fetch.UseDurableMutation[int](appCache, "post/"+id+"/likes", queue)
onClick := func() {
run(current+1, fetch.MutationDraft{Method: "POST", URL: "/api/like", Body: id},
func(ctx context.Context, m fetch.QueuedMutation) (int, error) { return serverfn.Call(...) })
}
type EventSource ¶
type EventSource struct {
// contains filtered or unexported fields
}
EventSource exposes a UseEventSource connection handle.
func UseEventSource ¶
func UseEventSource(parseURL string, parseOptions ...EventSourceOptions) EventSource
UseEventSource opens a bounded browser EventSource connection for a component.
func (EventSource) Close ¶
func (parseE EventSource) Close()
Close closes the EventSource connection and suppresses reconnects.
func (EventSource) Get ¶
func (parseE EventSource) Get() RealtimeState
Get returns the current EventSource state snapshot.
func (EventSource) Open ¶
func (parseE EventSource) Open()
Open starts or restarts the EventSource connection.
type EventSourceOptions ¶
type EventSourceOptions struct {
WithCredentials bool
Manual bool
DisableReconnect bool
MaxReconnects int
InitialBackoff time.Duration
MaxBackoff time.Duration
BackoffFactor float64
HeartbeatInterval time.Duration
HeartbeatTimeout time.Duration
MaxMessages int
MaxErrors int
Now func() time.Time
}
EventSourceOptions configures UseEventSource.
type HTTPError ¶
HTTPError reports a non-success HTTP status while preserving the response metadata on Result.
type InfiniteQuery ¶
InfiniteQuery wraps cached paginated data and page-loading helpers.
func UseInfiniteQuery ¶
func UseInfiniteQuery[T any, C any](parseKey string, parseLoader func(context.Context, QueryPageRequest[C]) (QueryPage[T, C], error), parseOptions ...InfiniteQueryOptions[C]) InfiniteQuery[T, C]
UseInfiniteQuery caches the first page and exposes LoadNext for pagination.
func (InfiniteQuery[T, C]) CacheKey ¶
func (parseQ InfiniteQuery[T, C]) CacheKey() string
CacheKey returns the stable cache key behind this infinite query.
func (InfiniteQuery[T, C]) Cancel ¶
func (parseQ InfiniteQuery[T, C]) Cancel()
Cancel cancels the active first-page query load, if any.
func (InfiniteQuery[T, C]) Dispose ¶
func (parseQ InfiniteQuery[T, C]) Dispose()
Dispose clears the infinite query cache entry.
func (InfiniteQuery[T, C]) Get ¶
func (parseQ InfiniteQuery[T, C]) Get() InfiniteQueryState[T, C]
Get returns the current infinite query state.
func (InfiniteQuery[T, C]) Invalidate ¶
func (parseQ InfiniteQuery[T, C]) Invalidate()
Invalidate marks the infinite query stale and eligible for first-page revalidation.
func (InfiniteQuery[T, C]) LoadNext ¶
func (parseQ InfiniteQuery[T, C]) LoadNext()
LoadNext loads and appends the next page when HasNext is true.
func (InfiniteQuery[T, C]) OptimisticUpdate ¶
func (parseQ InfiniteQuery[T, C]) OptimisticUpdate(parseFn func(InfiniteQueryData[T, C]) InfiniteQueryData[T, C]) OptimisticUpdate[InfiniteQueryData[T, C]]
OptimisticUpdate applies an optimistic infinite-query update and returns a rollback handle.
func (InfiniteQuery[T, C]) Reload ¶
func (parseQ InfiniteQuery[T, C]) Reload()
Reload reloads the first page and replaces currently cached pages.
func (InfiniteQuery[T, C]) Set ¶
func (parseQ InfiniteQuery[T, C]) Set(parseValue InfiniteQueryData[T, C])
Set replaces the complete infinite query data optimistically.
func (InfiniteQuery[T, C]) Tags ¶
func (parseQ InfiniteQuery[T, C]) Tags() []string
Tags returns the normalized tags registered for this infinite query.
func (InfiniteQuery[T, C]) Update ¶
func (parseQ InfiniteQuery[T, C]) Update(parseFn func(InfiniteQueryData[T, C]) InfiniteQueryData[T, C])
Update replaces the complete infinite query data using the previous value.
type InfiniteQueryData ¶
type InfiniteQueryData[T any, C any] struct { Pages []QueryPage[T, C] Items []T NextCursor C HasNext bool }
InfiniteQueryData is the cached value stored for an infinite query.
type InfiniteQueryOptions ¶
type InfiniteQueryOptions[C any] struct { Cache CacheOptions Tags []string InitialCursor C }
InfiniteQueryOptions configures UseInfiniteQuery.
type InfiniteQueryState ¶
type InfiniteQueryState[T any, C any] struct { InfiniteQueryData[T, C] Loading bool Error error Ready bool Stale bool UpdatedAt time.Time }
InfiniteQueryState describes the current state of a paginated query.
type MultipartBody ¶
type MultipartBody struct {
Fields map[string]string
Files []MultipartFile
}
MultipartBody describes a multipart form-data payload with text fields and browser files.
type MultipartFile ¶
MultipartFile describes one browser file to append to a multipart form-data body.
type MutationConflict ¶
type MutationConflict struct {
Code string `json:"code,omitempty"`
Message string `json:"message,omitempty"`
LocalVersion string `json:"localVersion,omitempty"`
RemoteVersion string `json:"remoteVersion,omitempty"`
Fields map[string]string `json:"fields,omitempty"`
}
func GetMutationConflict ¶
func GetMutationConflict(parseErr error) (MutationConflict, bool)
GetMutationConflict returns the structured conflict details carried by err.
type MutationConflictError ¶
type MutationConflictError struct {
Conflict MutationConflict
Err error
}
func AsMutationConflictError ¶
func AsMutationConflictError(parseErr error) (*MutationConflictError, bool)
AsMutationConflictError unwraps err into the structured MutationConflictError form.
func (*MutationConflictError) Error ¶
func (parseE *MutationConflictError) Error() string
Error is a core package helper.
func (*MutationConflictError) Unwrap ¶
func (parseE *MutationConflictError) Unwrap() error
Unwrap is a core package helper.
type MutationConflictHandler ¶
type MutationConflictHandler func(context.Context, QueuedMutation, MutationConflict) (MutationConflictResolution, error)
type MutationConflictResolution ¶
type MutationConflictResolution struct {
Action MutationResolutionAction
Draft MutationDraft
Message string
}
type MutationDraft ¶
type MutationDraft struct {
ID string `json:"id,omitempty"`
Kind string `json:"kind,omitempty"`
DedupKey string `json:"dedupKey,omitempty"`
Method string `json:"method,omitempty"`
URL string `json:"url,omitempty"`
Headers map[string]string `json:"headers,omitempty"`
Body any `json:"body,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}
MutationDraft describes one app-owned write to persist for later replay.
type MutationExecutor ¶
type MutationExecutor func(context.Context, QueuedMutation) error
MutationExecutor performs the authoritative replay for one queued mutation.
type MutationQueue ¶
type MutationQueue struct {
// contains filtered or unexported fields
}
MutationQueue persists writes locally and replays them later through an app-owned executor.
func OpenMutationQueue ¶
func OpenMutationQueue(parseOptions ...MutationQueueOptions) (MutationQueue, error)
OpenMutationQueue opens the persistent mutation queue backed by browser storage.
func (MutationQueue) Clear ¶
func (parseQ MutationQueue) Clear() error
Clear removes every persisted queue entry.
func (MutationQueue) Enqueue ¶
func (parseQ MutationQueue) Enqueue(parseDraft MutationDraft) (QueuedMutation, error)
Enqueue stores a write for later replay, suppressing duplicates that share the same dedup key.
func (MutationQueue) List ¶
func (parseQ MutationQueue) List() ([]QueuedMutation, error)
List returns all currently persisted queue entries in creation order.
func (MutationQueue) Remove ¶
func (parseQ MutationQueue) Remove(parseId string) error
Remove deletes one queue entry by id.
func (MutationQueue) Replay ¶
func (parseQ MutationQueue) Replay(parseCtx context.Context, parseExecutor MutationExecutor) (MutationReplayReport, error)
Replay replays due entries through the provided executor and persists the updated queue state.
func (MutationQueue) ReplayWithOptions ¶
func (parseQ MutationQueue) ReplayWithOptions(parseCtx context.Context, parseExecutor MutationExecutor, parseOptions ...MutationReplayOptions) (MutationReplayReport, error)
ReplayWithOptions replays due entries and applies optional conflict-resolution policy.
type MutationQueueOptions ¶
type MutationQueueOptions struct {
StorageKey string
MaxAttempts int
BaseDelay time.Duration
MaxDelay time.Duration
DeleteOnCorruption bool
StoreResolver func(context.Context) (interop.PersistentStore, error)
StorageResolver func() (interop.Storage, error)
Now func() time.Time
}
MutationQueueOptions configures persistent queue behavior.
type MutationReplayOptions ¶
type MutationReplayOptions struct {
ConflictHandler MutationConflictHandler
}
type MutationReplayReport ¶
type MutationReplayReport struct {
Succeeded int
Deferred int
Retried int
DeadLetters int
Conflicts int
Resolved int
Remaining int
}
MutationReplayReport summarizes one replay pass across queued entries.
type MutationResolutionAction ¶
type MutationResolutionAction string
const ( MutationResolutionRetry MutationResolutionAction = "retry" MutationResolutionDead MutationResolutionAction = "dead" MutationResolutionRemove MutationResolutionAction = "remove" MutationResolutionReplace MutationResolutionAction = "replace" )
type MutationState ¶
type MutationState string
const ( MutationQueued MutationState = "queued" MutationRetrying MutationState = "retrying" MutationDead MutationState = "dead" )
type OptimisticUpdate ¶
type OptimisticUpdate[T any] struct { // contains filtered or unexported fields }
OptimisticUpdate can roll back one optimistic cache write.
func ApplyOptimisticUpdate ¶
func ApplyOptimisticUpdate[T any](parseKey string, parseFn func(T) T) OptimisticUpdate[T]
ApplyOptimisticUpdate updates a cache entry and returns a rollback handle.
func (OptimisticUpdate[T]) Active ¶
func (parseU OptimisticUpdate[T]) Active() bool
Active reports whether the optimistic update can still be committed or rolled back.
func (*OptimisticUpdate[T]) Commit ¶
func (parseU *OptimisticUpdate[T]) Commit()
Commit makes the optimistic update final and disables rollback.
func (*OptimisticUpdate[T]) Rollback ¶
func (parseU *OptimisticUpdate[T]) Rollback()
Rollback restores the cache snapshot captured before the optimistic update.
type Options ¶
type Options struct {
Method string
// Headers are request headers. Values are typed any (not string) so callers can pass
// non-string values that are stringified at send time; response headers in Result are
// always plain strings.
Headers map[string]any
Body any
}
Options represents configuration for HTTP fetch operations.
type PersistentCacheOptions ¶
type Query ¶
type Query[T any] struct { // contains filtered or unexported fields }
Query wraps a cached resource with query metadata such as tags.
func UseQuery ¶
func UseQuery[T any](parseKey string, parseLoader func(context.Context) (T, error), parseOptions ...QueryOptions) Query[T]
UseQuery is a tag-aware wrapper around UseCachedResource.
func (Query[T]) Cancel ¶
func (parseQ Query[T]) Cancel()
Cancel cancels the active query load, if any.
func (Query[T]) Get ¶
func (parseQ Query[T]) Get() CachedResourceState[T]
Get returns the current query state.
func (Query[T]) Invalidate ¶
func (parseQ Query[T]) Invalidate()
Invalidate marks the query stale and eligible for revalidation.
func (Query[T]) OptimisticUpdate ¶
func (parseQ Query[T]) OptimisticUpdate(parseFn func(T) T) OptimisticUpdate[T]
OptimisticUpdate applies an optimistic query update and returns a rollback handle.
func (Query[T]) Set ¶
func (parseQ Query[T]) Set(parseValue T)
Set replaces the query value optimistically.
type QueryOptions ¶
type QueryOptions struct {
Cache CacheOptions
Tags []string
}
QueryOptions configures the ergonomic query wrapper around UseCachedResource.
type QueryPageRequest ¶
QueryPageRequest describes one page load for UseInfiniteQuery.
type QueuedMutation ¶
type QueuedMutation struct {
ID string `json:"id,omitempty"`
Kind string `json:"kind,omitempty"`
DedupKey string `json:"dedupKey,omitempty"`
Method string `json:"method,omitempty"`
URL string `json:"url,omitempty"`
Headers map[string]string `json:"headers,omitempty"`
Body any `json:"body,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
State MutationState `json:"state,omitempty"`
Attempts int `json:"attempts,omitempty"`
MaxAttempts int `json:"maxAttempts,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
NextAttemptAt time.Time `json:"nextAttemptAt"`
LastError string `json:"lastError,omitempty"`
}
QueuedMutation is the persisted replay record stored in the mutation queue.
type RealtimeError ¶
RealtimeError stores one recent realtime transport error.
type RealtimeMessage ¶
RealtimeMessage stores one received WebSocket or EventSource message.
type RealtimeState ¶
type RealtimeState struct {
Status RealtimeStatus
Supported bool
Connecting bool
Open bool
Closed bool
Messages []RealtimeMessage
LastMessage RealtimeMessage
Errors []RealtimeError
Error error
ConnectAttempts int
ReconnectAttempts int
Reconnects int
NextReconnectAt time.Time
LastOpenAt time.Time
LastCloseAt time.Time
LastHeartbeatAt time.Time
HeartbeatMisses int
}
RealtimeState is the bounded state snapshot returned by realtime hooks.
type RealtimeStatus ¶
type RealtimeStatus string
RealtimeStatus describes the current lifecycle phase for a realtime hook.
const ( // RealtimeIdle means the hook has not opened a browser transport yet. RealtimeIdle RealtimeStatus = "idle" // RealtimeConnecting means a browser transport is being opened. RealtimeConnecting RealtimeStatus = "connecting" // RealtimeOpen means the browser transport is currently open. RealtimeOpen RealtimeStatus = "open" // RealtimeReconnecting means the hook is waiting for a bounded reconnect attempt. RealtimeReconnecting RealtimeStatus = "reconnecting" // RealtimeClosed means the transport is closed and no reconnect is pending. RealtimeClosed RealtimeStatus = "closed" // RealtimeUnsupported means the browser API is unavailable on this target. RealtimeUnsupported RealtimeStatus = "unsupported" )
type ResiliencePolicy ¶
type ResiliencePolicy struct {
// Retry controls backoff and attempt limits.
Retry RetryPolicy
// Breaker, when non-nil, gates every call through circuit-breaker logic.
Breaker *CircuitBreaker
// contains filtered or unexported fields
}
ResiliencePolicy bundles a RetryPolicy and an optional CircuitBreaker into a single unit that ExecuteWithPolicy uses to drive resilient operation calls. Construct one with NewResiliencePolicy.
func NewResiliencePolicy ¶
func NewResiliencePolicy(parseRetry RetryPolicy, parseBreaker *CircuitBreaker) ResiliencePolicy
NewResiliencePolicy constructs a ResiliencePolicy wired to real-time sleep and real random jitter. Pass the result to ExecuteWithPolicy.
type Resource ¶
type Resource struct {
// contains filtered or unexported fields
}
Resource exposes the current low-level fetch state and a refetch helper.
func UseFetch
deprecated
UseFetch is a hook that simplifies data fetching within a component. It uses the runtime fetch hook directly.
Deprecated: prefer the typed UseResource[T] (a Go loader returning a typed value) or ui.UseQuery (cache + dedupe + stale-while-revalidate). UseFetch remains for a quick untyped URL GET.
type ResourceState ¶
ResourceState describes the state of a typed async resource.
type Result ¶
type Result struct {
Data any
Status int
// Headers are response headers, always plain strings (unlike Options.Headers, whose
// values are typed any for request-side flexibility).
Headers map[string]string
Err error
}
Result represents the result of a manual Fetch operation.
func (Result) DecodeJSON ¶
DecodeJSON decodes a string-backed response body into target.
type RetryPolicy ¶
type RetryPolicy struct {
// MaxAttempts is the total number of times the operation may be called,
// including the first attempt. Zero or negative values disable retries.
MaxAttempts int
// BaseDelay is the wait time before the second attempt.
BaseDelay time.Duration
// MaxDelay caps the computed backoff delay so it never grows unboundedly.
MaxDelay time.Duration
// Multiplier scales the delay between successive retries. A value of 2.0
// doubles the delay after each failure. A zero multiplier is honored as
// zero, so attempts after the second compute a zero delay; prefer
// DefaultRetryPolicy or an explicit positive multiplier for real backoff.
Multiplier float64
// Jitter is a fractional spread added to each delay to prevent thundering
// herds. A value of 0.1 allows a ±10 % random spread around the base delay.
Jitter float64
// RetryIf, when non-nil, is called with each error to decide whether the
// operation should be retried. Returning false stops retrying immediately
// and surfaces the error to the caller. When nil, all errors are retried.
RetryIf func(error) bool
}
RetryPolicy describes how ExecuteWithPolicy retries a failing operation, using exponential backoff with optional jitter.
func DefaultRetryPolicy ¶
func DefaultRetryPolicy() RetryPolicy
DefaultRetryPolicy returns a RetryPolicy suitable for most HTTP operations: three attempts, 100 ms base delay doubling up to 5 s, with 10 % jitter and no error filter (all errors are retried).
type State ¶
type State = runtime.FetchState
State represents the state of a fetch operation managed by UseFetch.
type UploadUpdate ¶
UploadUpdate reports upload progress and the final upload result.
type WebSocket ¶
type WebSocket struct {
// contains filtered or unexported fields
}
WebSocket exposes a UseWebSocket connection handle.
func UseWebSocket ¶
func UseWebSocket(parseURL string, parseOptions ...WebSocketOptions) WebSocket
UseWebSocket opens a bounded browser WebSocket connection for a component.
func (WebSocket) Close ¶
func (parseW WebSocket) Close()
Close closes the WebSocket connection and suppresses reconnects.
func (WebSocket) Get ¶
func (parseW WebSocket) Get() RealtimeState
Get returns the current WebSocket state snapshot.
type WebSocketOptions ¶
type WebSocketOptions struct {
Protocols []string
Manual bool
DisableReconnect bool
MaxReconnects int
InitialBackoff time.Duration
MaxBackoff time.Duration
BackoffFactor float64
HeartbeatInterval time.Duration
HeartbeatTimeout time.Duration
HeartbeatMessage string
MaxMessages int
MaxErrors int
Now func() time.Time
}
WebSocketOptions configures UseWebSocket.