vango

package
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2026 License: MIT Imports: 34 Imported by: 0

Documentation

Overview

Package vango provides the reactive core for the Vango framework.

The reactive system provides fine-grained reactivity similar to SolidJS, where dependencies are tracked automatically at runtime. Reading a signal during component render automatically subscribes the component to that signal's changes.

Core Types

Signal[T] is a reactive value container:

count := setup.Signal(&s, 0)
value := count.Get()  // Read (subscribes current listener)
count.Set(5)          // Write (notifies subscribers)
count.Update(func(n int) int { return n + 1 })

Memo[T] is a cached derived computation:

doubled := newMemo(func() int { return count.Get() * 2 })
value := doubled.Get()  // Recomputes only if dependencies changed

Effect runs side effects when dependencies change:

Effect(func() Cleanup {
    fmt.Println("Count is:", count.Get())
    return func() { /* cleanup */ }
})

Batching

Multiple signal updates can be batched to trigger a single notification:

Batch(func() {
    a.Set(1)
    b.Set(2)
    c.Set(3)
})  // Single notification after all updates

Thread Safety

All reactive primitives are thread-safe and can be accessed from multiple goroutines. The tracking context is per-goroutine, so spawning goroutines requires explicit context propagation via WithOwner.

Index

Constants

View Source
const (
	DefaultPerPrimitiveBytes int64 = 64 * 1024  // 64KB
	DefaultPerSessionBytes   int64 = 512 * 1024 // 512KB
)

Default budget limits for persisted state.

View Source
const (
	KindElement   = vdom.KindElement
	KindText      = vdom.KindText
	KindFragment  = vdom.KindFragment
	KindComponent = vdom.KindComponent
	KindRaw       = vdom.KindRaw
)

Re-export VKind constants

View Source
const (
	// Control keys
	KeyEnter     = "Enter"
	KeyEscape    = "Escape"
	KeySpace     = " "
	KeyTab       = "Tab"
	KeyBackspace = "Backspace"
	KeyDelete    = "Delete"

	// Arrow keys
	KeyArrowUp    = "ArrowUp"
	KeyArrowDown  = "ArrowDown"
	KeyArrowLeft  = "ArrowLeft"
	KeyArrowRight = "ArrowRight"

	// Navigation keys
	KeyHome     = "Home"
	KeyEnd      = "End"
	KeyPageUp   = "PageUp"
	KeyPageDown = "PageDown"

	// Function keys
	KeyF1  = "F1"
	KeyF2  = "F2"
	KeyF3  = "F3"
	KeyF4  = "F4"
	KeyF5  = "F5"
	KeyF6  = "F6"
	KeyF7  = "F7"
	KeyF8  = "F8"
	KeyF9  = "F9"
	KeyF10 = "F10"
	KeyF11 = "F11"
	KeyF12 = "F12"

	// Modifier keys (for reference, usually checked via event flags)
	KeyControl = "Control"
	KeyShift   = "Shift"
	KeyAlt     = "Alt"
	KeyMeta    = "Meta"

	// Other common keys
	KeyInsert      = "Insert"
	KeyPrintScreen = "PrintScreen"
	KeyScrollLock  = "ScrollLock"
	KeyPause       = "Pause"
	KeyCapsLock    = "CapsLock"
	KeyNumLock     = "NumLock"
	KeyContextMenu = "ContextMenu"
)

Common key constants matching JavaScript KeyboardEvent.key values.

View Source
const DefaultPersistBannerCSS = `` /* 527-byte string literal not displayed */

DefaultPersistBannerCSS provides CSS for the default banner.

View Source
const GlobalSignalPrefix = "vango:global:{global}:"

GlobalSignalPrefix is the persistence key prefix for global signals.

The constant hash tag "{global}" ensures Redis Cluster co-location for all global signal keys so multi-key atomic operations (MULTI/EXEC) can be used safely for Tx-level all-or-nothing durability.

View Source
const LintIgnoreDirective = "vango:lint-ignore"

LintIgnoreDirective documents the lint ignore directive for Vango tooling. Usage: //vango:lint-ignore VANGO.SETUP.CONDITIONAL_ALLOC

View Source
const RuntimeMetricsCatalogSchemaVersion = "vango.runtime_metrics.v1"

RuntimeMetricsCatalogSchemaVersion is the schema version for RuntimeMetricCatalog.

View Source
const SessionKeyInternalPrefix = "vango:sessionkey:"

SessionKeyInternalPrefix is the in-memory prefix for typed session keys.

Variables

Debug is the global debug configuration. Modify this at application startup to enable debugging features.

View Source
var DebugMode bool

DebugMode enables debug logging throughout the vango package. When true, operations like TxNamed will log transaction boundaries. This should be set at startup and not changed during runtime.

View Source
var DevMode = false

DevMode enables development-time checks and panics for invalid operations. When true:

  • Signal writes outside session loop panic with descriptive messages
  • Signal writes in prefetch mode panic
  • Signal writes during render/setup panic
  • Effect/Interval/Timeout in prefetch mode panic
  • More verbose logging and error messages

When false (production):

  • Invalid writes are dropped and logged (no crash)
  • Minimal overhead

DevMode is automatically enabled when running tests (*.test binaries). For production, set explicitly at application startup:

func main() {
    vango.DevMode = os.Getenv("VANGO_DEV") == "1"
    // ...
}
View Source
var EffectStrictMode = StrictEffectOff

EffectStrictMode controls global effect-time write detection. Set this in your application initialization based on build mode.

Example:

func init() {
    if os.Getenv("VANGO_DEV") == "1" {
        vango.EffectStrictMode = vango.StrictEffectWarn
    }
}
View Source
var ErrActionPanicked = errors.New("vango: action work panicked")

ErrActionPanicked is returned when Action work panics.

The Action runtime recovers panics from user work functions and surfaces them as ActionError state so one faulty action invocation cannot crash the process.

View Source
var ErrActionRunning = errors.New("vango: action already running")

ErrActionRunning is returned when attempting to run an Action that is already in the Running state and the concurrency policy is DropWhileRunning.

Applications can safely ignore this error as it's expected behavior for de-duplicating rapid user actions.

View Source
var ErrBudgetExceeded = errors.New("vango: storm budget exceeded")

ErrBudgetExceeded is returned when a storm budget limit is exceeded. This happens when too many operations (Resource fetches, Action runs, etc.) occur within the configured time window.

Applications should handle this by: - Logging the event for debugging - Optionally showing user feedback about rate limiting - Reducing the frequency of operations if possible

See SPEC_ADDENDUM.md §A.4 for storm budget configuration.

View Source
var ErrEffectContext = errors.New("vango: effect helper called outside effect/render context")

ErrEffectContext is returned when an effect helper (Interval, Subscribe, GoLatest) is called outside of an effect body or render context.

These helpers require access to the runtime context (Ctx) and must be called within createEffect or during component render.

View Source
var ErrGoLatestContext = errors.New("vango: GoLatest must be called inside an Effect")

ErrGoLatestContext is returned when GoLatest is called outside an effect body. GoLatest requires effect-local storage and must be called from within createEffect.

View Source
var ErrNoSession = errors.New("vango: no active session")

ErrNoSession is returned when a session-backed operation is invoked without an active session.

View Source
var ErrQueueFull = errors.New("vango: action queue full")

ErrQueueFull is an admission-control sentinel used when an Action's queue is full and cannot accept more work items (ConcurrencyQueue policy).

IMPORTANT: The runtime does not set ErrQueueFull as Action.Error(); a full queue is not a work failure. Instead, Action.Run returns false and, if configured, OnActionRejected is invoked.

Applications should handle this by: - Informing the user their action was not queued - Waiting before retrying - Using a different concurrency policy if appropriate

See SPEC_ADDENDUM.md §A.1.5 for concurrency policies.

View Source
var ErrSessionKeyUnbound = errors.New("vango: session key missing bindings; run 'vango gen bindings'")

ErrSessionKeyUnbound is returned when a SessionKey has no binding.

View Source
var ErrTransactionAborted = errors.New("vango: transaction aborted")

ErrTransactionAborted is returned when a write occurs after a transaction abort.

View Source
var ErrUnknownPersistedSignal = errors.New("vango: persisted signal not found")

ErrUnknownPersistedSignal indicates a missing persisted signal entry.

View Source
var ErrWriteForbidden = errors.New("vango: write must occur on the session loop")

ErrWriteForbidden is returned when a write is attempted outside the session loop.

View Source
var GlobalSignalStoreKey = &struct{ name string }{"GlobalSignalStore"}

GlobalSignalStoreKey is the context key for global persisted signals.

View Source
var LoggerKey = &struct{ name string }{"Logger"}

LoggerKey stores the structured logger in the owner context.

View Source
var MetricsKey = &struct{ name string }{"Metrics"}

MetricsKey stores a metrics sink in the owner context.

View Source
var ObservabilityConfigKey = &struct{ name string }{"ObservabilityConfig"}

ObservabilityConfigKey stores observability settings in the owner context.

View Source
var PageActionBindingContextKey any = pageActionBindingContextKey{}

PageActionBindingContextKey stores the current page action binding on the request context.

View Source
var PersistBannerDisabledKey = &struct{ name string }{"PersistBannerDisabled"}

PersistBannerDisabledKey stores a bool indicating default banner suppression.

View Source
var PersistBannerSignalKey = &struct{ name string }{"PersistBannerSignal"}

PersistBannerSignalKey stores the banner visibility signal in context.

View Source
var PersistedSignalStoreKey = &struct{ name string }{"PersistedSignalStore"}

PersistedSignalStoreKey is the context key for session-scoped persisted signals.

View Source
var RouteFormStateContextKey any = routeFormStateContextKey{}

RouteFormStateContextKey stores submitted route-form state on the request context.

View Source
var SessionPersistBannerKey = &struct{ name string }{"SessionPersistBanner"}

SessionPersistBannerKey stores PersistBannerState in session context.

View Source
var SessionSignalStoreKey = &struct{ name string }{"SessionSignalStore"}

SessionSignalStoreKey is the context key for the session signal store. The server package should set this during session initialization.

View Source
var StrictConcurrency = false

StrictConcurrency forces session-loop-only write enforcement to panic even when DevMode is false.

Default: false (production-safe: drop + warn + metric).

This is useful for staging/canary environments where you want concurrency violations to crash loudly before reaching production.

Functions

func AsCircularDependencyPanic

func AsCircularDependencyPanic(v any) (cycle []MemoRef, current MemoRef, reentryIdx int, ok bool)

AsCircularDependencyPanic extracts structured cycle information from a panic value. This is intended for session containment and tests.

func AssertNoPanic

func AssertNoPanic(t *testing.T, fn func())

AssertNoPanic asserts that fn does not panic. If fn panics, the test fails with the panic message.

Example:

func TestValidOperation(t *testing.T) {
    AssertNoPanic(t, func() {
        // Code that should not panic
    })
}

func AssertPanics

func AssertPanics(t *testing.T, fn func()) (panicValue any)

AssertPanics asserts that fn panics. If fn does not panic, the test fails. If fn panics, the panic value is returned for further inspection.

Example:

func TestInvalidOperation(t *testing.T) {
    msg := AssertPanics(t, func() {
        // Code that should panic
    })
    if !strings.Contains(fmt.Sprint(msg), "forbidden") {
        t.Fatalf("unexpected panic message: %v", msg)
    }
}

func Batch

func Batch(fn func())

Batch groups multiple signal updates into a single notification phase. All signal updates within the batch function are collected, deduplicated, and then all affected listeners are notified once when the batch completes.

This is useful for updating multiple related signals without triggering intermediate re-renders.

Batches can be nested. Notifications only fire when the outermost batch completes.

Example:

Batch(func() {
    firstName.Set("John")
    lastName.Set("Doe")
    age.Set(30)
})
// Component re-renders once with all three changes

func CSRFCtxToken added in v0.1.0

func CSRFCtxToken(ctx interface{ Value(key any) any }) string

CSRFCtxToken retrieves a CSRF token from request-scoped context values.

func ClearSessionKeyRegistry

func ClearSessionKeyRegistry()

ClearSessionKeyRegistry clears the registry (for tests).

func DecodeHookPayload

func DecodeHookPayload[T any](event HookEvent) (T, error)

DecodeHookPayload decodes hook payload data into a typed schema. Unknown fields and trailing JSON content are rejected.

func DecodeIslandPayload

func DecodeIslandPayload[T any](msg IslandMessage) (T, error)

DecodeIslandPayload decodes an island message payload into a typed schema. Unknown fields and trailing JSON content are rejected.

func DecodeWasmPayload

func DecodeWasmPayload[T any](msg WasmMessage) (T, error)

DecodeWasmPayload decodes a WASM message payload into a typed schema. Unknown fields and trailing JSON content are rejected.

func DisallowedLogKeyFragments

func DisallowedLogKeyFragments() []string

DisallowedLogKeyFragments returns fragments that are redacted by RedactPII.

func FormatMemoCycle

func FormatMemoCycle(cycle []MemoRef) string

FormatMemoCycle formats a cycle chain as a deterministic string suitable for logs.

func Func

func Func(render func() *vdom.VNode) vdom.Component

Func wraps a render function as a Component. Deprecated: Use vango.Setup for all stateful components.

Example:

func Counter(initial int) vango.Component {
    return vango.Setup(vango.NoProps{}, func(s vango.SetupCtx[vango.NoProps]) vango.RenderFn {
        count := setup.Signal(&s, initial)
        return func() *vango.VNode {
            return Div(
                H1(Textf("Count: %d", count.Get())),
                Button(OnClick(count.Inc), Text("+")),
            )
        }
    })
}

func GetContext

func GetContext(key any) any

GetContext retrieves a context value from the nearest provider in the hierarchy. Returns nil if no value is found.

func GetEffectCallSiteState

func GetEffectCallSiteState[T any](factory func() *T) *T

GetEffectCallSiteState retrieves or creates typed state for the current call-site within the currently executing Effect. This is the primary API for effect helpers like GoLatest that need to maintain state across effect reruns.

The factory function is called only on first invocation for this call-site. Subsequent calls (in effect reruns) return the previously created state.

Returns nil if called outside an effect body.

Usage pattern in effect helpers:

func GoLatest[K, R any](...) Cleanup {
    state := GetEffectCallSiteState(func() *goLatestState[K] {
        return &goLatestState[K]{}
    })
    if state == nil {
        panic("GoLatest must be called inside an Effect")
    }
    // Use state...
}

func GetSessionKeyRegistry

func GetSessionKeyRegistry() map[string]SessionKeyInfo

GetSessionKeyRegistry returns all registered session keys by name.

func GetSessionRefreshBanner

func GetSessionRefreshBanner() func(Ctx) BannerSpec

GetSessionRefreshBanner returns the current banner handler, if any.

func InRender

func InRender() bool

InRender reports whether the current goroutine is inside a render phase. This is intended for framework-internal use.

func InSessionLoop

func InSessionLoop() bool

InSessionLoop reports whether the current goroutine is executing on the session loop (single-writer context). This is primarily used by the server runtime to enforce correctness contracts around Dispatch and state writes.

func InSetup

func InSetup() bool

InSetup reports whether the current goroutine is inside a Setup execution. This is primarily intended for framework packages that enforce setup-time contracts on helper APIs.

func InitPersistBannerState

func InitPersistBannerState(owner *Owner)

InitPersistBannerState initializes banner state for a session owner. Intended for server/session setup; not for application code.

func IsDevMode

func IsDevMode() bool

IsDevMode reports whether development mode is enabled.

func IsPrefetchMode

func IsPrefetchMode() bool

IsPrefetchMode returns true if the current context is in prefetch mode. This is used by Signal.Set(), Effect(), Interval(), Timeout(), and Action() to enforce read-only behavior during prefetch.

Per Section 8.3.2 of the Routing Spec:

  • Dev mode: Operations panic with descriptive message
  • Prod mode: Operations are silently dropped (no-op)

func IsStrictConcurrency

func IsStrictConcurrency() bool

IsStrictConcurrency reports whether strict concurrency mode is enabled.

func OnSessionRefreshBanner

func OnSessionRefreshBanner(fn func(Ctx) BannerSpec)

OnSessionRefreshBanner registers a handler to customize schema refresh banners.

func OnUnmount

func OnUnmount(fn func())

OnUnmount registers a function to run when the owner is disposed. This is typically used for cleanup when a component unmounts.

Example:

OnUnmount(func() {
    fmt.Println("Component unmounted")
})

func PrimeResourcesForInitialMount added in v0.1.0

func PrimeResourcesForInitialMount(regs []PrimitiveRegistration, fetchCtx, waitCtx context.Context) bool

PrimeResourcesForInitialMount aligns the first live-session tree with the SSR HTML by resolving setup.Resource/setup.ResourceKeyed registrations before the session's initial tree is committed.

This is runtime infrastructure used by the server package during Session.MountRoot. It intentionally preloads only resource primitives; user effects and OnMount hooks still run after the first live commit. Eligible resources are started first on the single-writer mount pass, then waited concurrently under one shared timeout.

func RedactPII

func RedactPII(fields ...any) []any

RedactPII replaces values for disallowed keys in key/value pairs or slog.Attr entries. It does not attempt to scrub content inside strings; it only checks keys.

func RedactSlogAttrs added in v0.2.0

func RedactSlogAttrs(attrs []slog.Attr) []slog.Attr

RedactSlogAttrs returns a copy of attrs with sensitive values redacted. It is intended for slog.Handler implementations and preserves safe attr keys.

func RedactingHandler added in v0.2.0

func RedactingHandler(next slog.Handler) slog.Handler

RedactingHandler wraps a slog.Handler and redacts sensitive attr values by key. Use it at logger construction boundaries so app/framework logs keep structured context without leaking secrets or common PII through default diagnostics.

func RedactingLogger added in v0.2.0

func RedactingLogger(next slog.Handler) *slog.Logger

RedactingLogger returns a slog.Logger backed by RedactingHandler.

func SetCSRFCtxToken added in v0.1.0

func SetCSRFCtxToken(ctx interface{ SetValue(key, value any) }, token string)

SetCSRFCtxToken stores a CSRF token in request-scoped context values.

func SetContext

func SetContext(key, value any)

SetContext sets a context value for the current component scope. This value will be available to all descendants via GetContext.

func SetDevMode

func SetDevMode(enabled bool)

SetDevMode updates development mode in a concurrency-safe way.

func SetGlobalMetricsSink

func SetGlobalMetricsSink(sink MetricsSink)

SetGlobalMetricsSink sets the process-wide metrics sink used as a fallback when no request/session context is available (e.g., off-loop goroutines).

Passing nil disables global metric emission (no-op).

func SetHookSlot

func SetHookSlot(value any)

SetHookSlot stores a value in the current hook slot. Must be called after UseHookSlot returns nil (first render only).

If no owner is set or we're outside render context, this is a no-op.

func SetStrictConcurrency

func SetStrictConcurrency(enabled bool)

SetStrictConcurrency updates strict concurrency mode in a concurrency-safe way.

func Setup

func Setup[P any](props P, fn func(SetupCtx[P]) RenderFn) vdom.Component

Setup creates a stateful component with explicit props binding.

func SetupOnChange

func SetupOnChange[P any, K comparable](s *SetupCtx[P], key func() K, cb func(next, prev K))

SetupOnChange registers a typed change handler during Setup.

func ShowDefaultPersistBanner

func ShowDefaultPersistBanner(err *PersistBudgetError)

ShowDefaultPersistBanner triggers the default banner for a persist error.

func TestBatch

func TestBatch(t *testing.T, fn func())

TestBatch runs fn inside both a session loop and a batch context. Use this when testing batched signal updates.

Example:

func TestBatchedUpdates(t *testing.T) {
    a := NewSignal(0)
    b := NewSignal(0)
    listener := newTestListener()

    WithListener(listener, func() {
        _ = a.Get()
        _ = b.Get()
    })

    TestBatch(t, func() {
        a.Set(1)
        b.Set(2)
    })

    // Listener notified once (batched), not twice
    if listener.getDirtyCount() != 1 {
        t.Fatal("expected single batched notification")
    }
}

func TestDevMode

func TestDevMode(t *testing.T, fn func())

TestDevMode runs fn with DevMode enabled, ensuring write violations panic with descriptive messages instead of being silently dropped.

Example:

func TestOffLoopWritePanics(t *testing.T) {
    TestDevMode(t, func() {
        defer func() {
            if r := recover(); r == nil {
                t.Fatal("expected panic for off-loop write")
            }
        }()
        sig := NewSignal(0)
        sig.Set(1) // This should panic
    })
}

func TestID

func TestID(id string) vdom.Attr

TestID creates a data-testid attribute for querying elements in tests.

func TestProdMode

func TestProdMode(t *testing.T, fn func())

TestProdMode runs fn with DevMode disabled, simulating production behavior where write violations are silently dropped (with logging).

Example:

func TestOffLoopWriteDropped(t *testing.T) {
    TestProdMode(t, func() {
        sig := NewSignal(42)
        sig.Set(100) // Silently dropped (not on session loop)
        if sig.Get() != 42 {
            t.Fatal("expected write to be dropped")
        }
    })
}

func TestSessionLoop

func TestSessionLoop(t *testing.T, fn func())

TestSessionLoop runs fn on a simulated session loop context. Use this in tests when you need to write signals, as production code does via event handlers.

Signal reads (Get/Peek) do not require TestSessionLoop and can be called from anywhere.

Example:

func TestCounter(t *testing.T) {
    count := NewSignal(0)
    TestSessionLoop(t, func() {
        count.Set(42)
    })
    if count.Get() != 42 {
        t.Fatal("expected 42")
    }
}

Multiple writes can be batched in a single TestSessionLoop call:

TestSessionLoop(t, func() {
    count.Set(1)
    name.Set("Alice")
    items.Set([]int{1, 2, 3})
})

func TestSetup

func TestSetup(t *testing.T, fn func())

TestSetup runs fn in a setup context inside a session loop. Use this when testing setup-phase behavior.

Example:

func TestSetupPhase(t *testing.T) {
    TestSetup(t, func() {
        // Setup-phase code here
        if !isInSetup() {
            t.Fatal("expected to be in setup")
        }
    })
}

func TestWithOwner

func TestWithOwner(t *testing.T, owner *Owner, fn func())

TestWithOwner runs fn with the specified owner as the current owner, inside a session loop context. Use this when testing code that creates signals/effects that should belong to a specific owner.

Example:

func TestOwnershipHierarchy(t *testing.T) {
    parent := NewOwner()
    var child *Signal[int]

    TestWithOwner(t, parent, func() {
        child = NewSignal(0)
    })

    // child is now owned by parent
}

func TrackHook

func TrackHook(ht HookType)

TrackHook records a hook call for the current owner. This is used by feature packages (resource, form, urlparam) to participate in hook-order validation during dev mode.

External packages should call this at the beginning of their hook constructors:

func UseForm[T any](initial T) *Form[T] {
    vango.TrackHook(vango.HookForm)
    // ... rest of implementation
}

If no owner is set (outside of render context), this is a no-op.

func Tx

func Tx(fn func())

Tx runs fn as a transaction, grouping all signal updates. This is an alias for Batch() that aligns with the transaction terminology used in the spec (§3.9.4 and §7).

All signal updates within the transaction are collected, deduplicated, and notifications only fire when the transaction completes.

Example:

Tx(func() {
    user.Set(newUser)
    profile.Set(newProfile)
    settings.Set(newSettings)
})
// Single re-render with all changes

func TxNamed

func TxNamed(name string, fn func())

TxNamed runs fn as a named transaction for debugging and tracing. The transaction name is logged in debug mode for observability.

This is useful for understanding which transactions trigger re-renders during development and for production tracing.

Example:

TxNamed("user-profile-update", func() {
    user.Set(newUser)
    profile.Set(newProfile)
})
// Debug output: [TX] user-profile-update start/end

func Untracked

func Untracked(fn func())

Untracked runs a function without tracking signal reads as dependencies. This is useful when you need to read a signal's value without creating a subscription.

Example:

Untracked(func() {
    // Reading count here won't subscribe the current component
    value := count.Get()
    fmt.Println("Current value:", value)
})

Note: For single signal reads, use signal.Peek() instead which is more efficient and clearer in intent.

func UntrackedGet

func UntrackedGet[T any](s *Signal[T]) T

UntrackedGet reads a signal's value without creating a dependency. This is a convenience function equivalent to signal.Peek().

func UseHookSlot

func UseHookSlot() any

UseHookSlot returns stable hook state from the current owner. On first render, returns nil (caller should create value and call SetHookSlot). On subsequent renders, returns the previously stored value.

This provides stable identity for hooks (like URLParam, Resource) across renders.

Usage pattern:

func SomeHook[T any]() *T {
    slot := vango.UseHookSlot()
    if slot != nil {
        return slot.(*T)  // Subsequent render
    }
    instance := &T{...}  // First render
    vango.SetHookSlot(instance)
    return instance
}

If no owner is set or we're outside render context, returns nil.

func WithCtx

func WithCtx(c any, fn func())

WithCtx runs a function with the specified runtime context. This is used by the server to establish context during event handling and component rendering.

Example (internal use by server):

WithCtx(ctx, func() {
    // UseCtx() will return ctx here
    component.Render()
})

func WithListener

func WithListener(l Listener, fn func())

WithListener runs a function with the specified listener for tracking. This is used internally to set up dependency tracking during rendering.

func WithOwner

func WithOwner(owner *Owner, fn func())

WithOwner runs a function with the specified owner as the current owner.

This is an internal wiring utility used by the framework when work executes outside the normal component render/effect lifecycle and still needs to attribute reactive allocations to a specific owner.

Application code should not rely on this. Vango components must not spawn goroutines; use Actions/Resources and framework-managed effect helpers (GoLatest/Interval/Timeout/Subscribe) instead.

Example:

WithOwner(parentOwner, func() {
    // Signals created here belong to parentOwner
    signal := newSignal(0)
    _ = signal
})

func WithRenderAllocationsDisabled

func WithRenderAllocationsDisabled(fn func())

WithRenderAllocationsDisabled runs a function with render allocations forbidden.

func WithSessionLoop

func WithSessionLoop(fn func())

WithSessionLoop marks execution as running on the session loop. This is used by the server runtime and tests to enforce single-writer rules.

func WithSetup

func WithSetup(fn func())

WithSetup runs a function with setup tracking enabled.

func WithTxTraceHook

func WithTxTraceHook(ctx context.Context, hook TxTraceHook) context.Context

WithTxTraceHook attaches a TxTraceHook to a context for TxNamed to use. This is intended for middleware (e.g., OpenTelemetry) to integrate without introducing a dependency from core vango to tracing libraries.

func WithWorkerContext

func WithWorkerContext(kind WorkerKind, meta *primitiveMetadata, runtimeCtx Ctx, fn func())

WithWorkerContext runs fn with the goroutine marked as executing framework worker code. This must be used by Vango internals when running Resource loaders and Action work.

Types

type Action

type Action[A any, R any] struct {
	// contains filtered or unexported fields
}

Action is the structured primitive for async mutations. It bundles loading/error/success state, cancellation, and dispatch into a standard, auditable unit allocated during Setup.

func SetupAction

func SetupAction[P any, A any, R any](
	s *SetupCtx[P],
	work func(ctx context.Context, arg A) (R, error),
	opts ...ActionOption,
) *Action[A, R]

SetupAction creates an action during Setup.

func (*Action[A, R]) Error

func (a *Action[A, R]) Error() error

Error returns the last error, or nil if no error occurred.

func (*Action[A, R]) IsError

func (a *Action[A, R]) IsError() bool

IsError returns true if the action is in the Error state.

func (*Action[A, R]) IsIdle

func (a *Action[A, R]) IsIdle() bool

IsIdle returns true if the action is in the Idle state.

func (*Action[A, R]) IsRunning

func (a *Action[A, R]) IsRunning() bool

IsRunning returns true if the action is in the Running state.

func (*Action[A, R]) IsSuccess

func (a *Action[A, R]) IsSuccess() bool

IsSuccess returns true if the action is in the Success state.

func (*Action[A, R]) Match

func (a *Action[A, R]) Match(handlers ...ActionHandler) *vdom.VNode

Match renders different content based on the action state.

func (*Action[A, R]) Metadata

func (a *Action[A, R]) Metadata() vruntime.PrimitiveMetadata

Metadata returns identity metadata for the primitive.

func (*Action[A, R]) Reset

func (a *Action[A, R]) Reset()

Reset sets the Action back to ActionIdle and clears stored result/error.

func (*Action[A, R]) Result

func (a *Action[A, R]) Result() (R, bool)

Result returns the last successful result and true, or zero value and false if no success has occurred yet.

func (*Action[A, R]) Run

func (a *Action[A, R]) Run(arg A) bool

Run starts the async operation with the given argument. Returns true if the call was accepted (started or queued), false if rejected.

Spec-aligned contract (Developer Guide v1):

  • MUST be called on the session loop (event handler, effect, or Dispatch callback)
  • MUST NOT be called during render or setup
  • Work runs off-loop and MUST respect ctx cancellation

Behavior depends on concurrency policy:

  • CancelLatest: Cancels any in-flight work, starts new. Returns true.
  • DropWhileRunning: Ignores call if already running. Returns false if dropped.
  • Queue: Queues the call if running. Returns false if queue is full.

func (*Action[A, R]) State

func (a *Action[A, R]) State() ActionState

State returns the current ActionState. This is reactive - reading it inside an Effect will subscribe to changes.

type ActionCtx added in v0.1.0

type ActionCtx interface {
	StdContext() context.Context
	Logger() *slog.Logger
	Value(key any) any
	Request() *http.Request
	Path() string
	Method() string
	Query() url.Values
	QueryParam(key string) string
	Param(key string) string
	Header(key string) string
	Cookie(name string) (*http.Cookie, error)
	User() any
	SetUser(user any)
	Principal() (auth.Principal, bool)
	AuthSession() auth.Session
	BroadcastAuthLogout()
}

ActionCtx is the safe capability boundary exposed to progressive route actions.

func NewBufferedActionCtx added in v0.1.0

func NewBufferedActionCtx(base *PageActionBase, params any) (ActionCtx, func(ActionMutationTarget))

NewBufferedActionCtx creates an action context with buffered auth/session mutations.

type ActionHandler

type ActionHandler interface {
	// contains filtered or unexported methods
}

ActionHandler handles a specific Action state.

func OnActionError

func OnActionError(fn func(error) *vdom.VNode) ActionHandler

OnActionError handles the Error state.

func OnActionIdle

func OnActionIdle(fn func() *vdom.VNode) ActionHandler

OnActionIdle handles the Idle state.

func OnActionRunning

func OnActionRunning(fn func() *vdom.VNode) ActionHandler

OnActionRunning handles the Running state.

func OnActionSuccess

func OnActionSuccess[R any](fn func(R) *vdom.VNode) ActionHandler

OnActionSuccess handles the Success state.

type ActionMutationTarget added in v0.1.0

type ActionMutationTarget interface {
	SetUser(user any)
	AuthSession() auth.Session
	BroadcastAuthLogout()
}

ActionMutationTarget is the narrow surface that buffered action mutations can apply back onto after successful completion.

type ActionOption

type ActionOption interface {
	// contains filtered or unexported methods
}

ActionOption is an option for configuring an Action.

func ActionOnError

func ActionOnError(fn func(error)) ActionOption

ActionOnError registers a callback that runs when the action fails. The callback runs on the session loop and receives the error.

func ActionOnSuccess

func ActionOnSuccess(fn func(any)) ActionOption

ActionOnSuccess registers a callback that runs on successful completion. The callback runs on the session loop and receives the result.

Note: Due to Go's type system limitations, this version takes func(any). For type-safe callbacks, use the OnSuccess method on the Action directly or cast the result in the callback.

func ActionTxName

func ActionTxName(name string) ActionOption

ActionTxName sets the transaction name for observability. State transitions will appear in DevTools as:

  • Action:<name>:running
  • Action:<name>:success
  • Action:<name>:error

Without this option, a default name based on component/file is used.

func CancelLatest

func CancelLatest() ActionOption

CancelLatest returns an option that cancels prior in-flight work on new Run. This is the default concurrency policy.

When Run is called while another operation is running:

  • The prior operation is cancelled via context cancellation
  • The new operation starts immediately
  • Run returns true

func DropWhileRunning

func DropWhileRunning() ActionOption

DropWhileRunning returns an option that ignores Run while an operation is running.

When Run is called while another operation is running:

  • The call is ignored (no-op)
  • Run returns false

func OnActionRejected

func OnActionRejected(fn func(ActionRejection)) ActionOption

OnActionRejected registers a callback that runs when Action.Run is rejected by a concurrency policy (e.g., queue full, drop-while-running).

This callback is invoked on the session loop and does not affect ActionState.

func OnActionStart

func OnActionStart(fn func()) ActionOption

OnActionStart registers a callback that runs when the action starts. The callback runs on the session loop (inside a Dispatch).

func Queue

func Queue(maxQueue int) ActionOption

Queue returns an option that queues Run calls and executes them sequentially.

When Run is called while another operation is running:

  • If queue has room, the call is queued. Run returns true.
  • If queue is full, the call is rejected. Run returns false.

maxQueue specifies the maximum number of queued calls (must be > 0).

type ActionPanicError

type ActionPanicError struct {
	Value any
}

ActionPanicError wraps a panic value captured from Action work. It implements errors.Is(err, ErrActionPanicked).

func (*ActionPanicError) Error

func (e *ActionPanicError) Error() string

func (*ActionPanicError) Is

func (e *ActionPanicError) Is(target error) bool

func (*ActionPanicError) Unwrap

func (e *ActionPanicError) Unwrap() error

type ActionRejection

type ActionRejection struct {
	Reason ActionRejectionReason
	When   time.Time
}

ActionRejection is passed to OnActionRejected callbacks. It intentionally does not include the input argument to avoid memory/PII footguns.

type ActionRejectionReason

type ActionRejectionReason string

ActionRejectionReason describes why an Action.Run call was rejected. Rejections are admission-control events (policy/disposal), not work outcomes.

const (
	ActionRejectQueueFull        ActionRejectionReason = "queue_full"
	ActionRejectDropWhileRunning ActionRejectionReason = "dropped_while_running"
)

type ActionState

type ActionState int

ActionState represents the current state of an Action.

const (
	// ActionIdle is the initial state before any Run call.
	ActionIdle ActionState = iota

	// ActionRunning indicates an async operation is in progress.
	ActionRunning

	// ActionSuccess indicates the last operation completed successfully.
	ActionSuccess

	// ActionError indicates the last operation failed.
	ActionError
)

func (ActionState) String

func (s ActionState) String() string

String returns a human-readable name for the action state.

type AnimationEvent

type AnimationEvent struct {
	// Name of the CSS animation
	AnimationName string

	// Time in seconds since the animation started
	ElapsedTime float64

	// Pseudo-element the animation runs on (e.g., "::before")
	PseudoElement string
}

AnimationEvent represents a CSS animation event. Per spec section 3.9.3, lines 1230-1234.

type BannerSpec

type BannerSpec struct {
	Message      string
	Detail       string
	DismissDelay time.Duration
	CSSClass     string
}

BannerSpec defines the session refresh banner content.

func DefaultBannerSpec

func DefaultBannerSpec(devMode bool, reason protocol.SchemaRefreshReason) BannerSpec

DefaultBannerSpec returns the default banner configuration.

type BoolSignal deprecated

type BoolSignal struct {
	*Signal[bool]
}

BoolSignal wraps Signal[bool] with convenience methods for boolean operations.

Deprecated: Use setup.Signal inside vango.Setup. Signal[bool] now has Toggle(), SetTrue(), and SetFalse() methods directly available.

// Old:
visible := vango.NewBoolSignal(false)
visible.Toggle()

// New:
visible := setup.Signal(&s, false)
visible.Toggle()

func NewBoolSignal deprecated

func NewBoolSignal(initial bool) *BoolSignal

NewBoolSignal creates a new BoolSignal with the given initial value.

Deprecated: Use setup.Signal inside vango.Setup. Signal[bool] now has Toggle(), SetTrue(), and SetFalse() methods directly available.

func (*BoolSignal) SetFalse

func (s *BoolSignal) SetFalse()

SetFalse sets the value to false.

func (*BoolSignal) SetTrue

func (s *BoolSignal) SetTrue()

SetTrue sets the value to true.

func (*BoolSignal) Toggle

func (s *BoolSignal) Toggle()

Toggle inverts the boolean value.

type BudgetExceededMode

type BudgetExceededMode int

BudgetExceededMode determines behavior when a storm budget is exceeded. (Re-exported from server/config.go for convenience)

const (
	// BudgetModeThrottle drops excess operations silently (default).
	BudgetModeThrottle BudgetExceededMode = iota

	// BudgetModeTripBreaker pauses effect execution until cleared.
	BudgetModeTripBreaker
)

type BudgetKind

type BudgetKind int

BudgetKind identifies which budget was exceeded.

const (
	BudgetKindPrimitive BudgetKind = iota
	BudgetKindSession
)

func (BudgetKind) String

func (k BudgetKind) String() string

type BudgetScope

type BudgetScope int

BudgetScope indicates which persistence scope a primitive belongs to.

const (
	BudgetScopeLocal BudgetScope = iota
	BudgetScopeSession
	BudgetScopeGlobal
)

type BudgetStats

type BudgetStats struct {
	ResourceStartsInWindow int
	ActionStartsInWindow   int
	GoLatestStartsInWindow int
	EffectRunsThisTick     int
}

Stats returns current budget usage statistics.

type BudgetTracker

type BudgetTracker struct {
	// contains filtered or unexported fields
}

BudgetTracker tracks persisted state sizes for budget enforcement. It is safe for concurrent use.

func NewBudgetTracker

func NewBudgetTracker(cfg StateBudgetConfig, c codec.Codec, devMode bool) *BudgetTracker

NewBudgetTracker creates a BudgetTracker with the given configuration.

func (*BudgetTracker) CheckAndRecord

func (bt *BudgetTracker) CheckAndRecord(scope BudgetScope, sessionID, stableID, debugName string, newBytes int64) *PersistBudgetError

CheckAndRecord validates a write against budgets and updates tracking.

func (*BudgetTracker) EncodedSize

func (bt *BudgetTracker) EncodedSize(value any) (int64, error)

EncodedSize returns the encoded size of a value using the persistence codec.

func (*BudgetTracker) GetSessionSize

func (bt *BudgetTracker) GetSessionSize(sessionID string) int64

GetSessionSize returns the tracked size for a session.

func (*BudgetTracker) RecordExisting

func (bt *BudgetTracker) RecordExisting(sessionID, stableID string, bytes int64)

RecordExisting stores a previously persisted size without budget checks.

func (*BudgetTracker) RemoveSession

func (bt *BudgetTracker) RemoveSession(sessionID string)

RemoveSession cleans up tracking for a closed session.

func (*BudgetTracker) SetMetricsCallbacks

func (bt *BudgetTracker) SetMetricsCallbacks(
	onWrite func(scope BudgetScope, stableID string, bytes int64),
	onRejection func(reason string, stableID string, err *PersistBudgetError),
)

SetMetricsCallbacks configures metrics collection. onWrite receives the scope, stable ID, and bytes written. onRejection receives a normalized reason and stable ID plus the error.

type Cleanup

type Cleanup func()

Cleanup is a function returned by effects to clean up resources. It is called before the effect re-runs and when the effect is disposed.

func GoLatest

func GoLatest[K comparable, R any](
	key K,
	work func(ctx context.Context, key K) (R, error),
	apply func(result R, err error),
	opts ...GoLatestOption,
) Cleanup

GoLatest is the standard helper for async integration work inside Effect. It handles key coalescing, stale suppression, cancellation, and dispatch.

Key semantics:

  • Same key as previous call: No new work starts (existing work continues)
  • Different key: Cancels prior work, starts new work
  • Use GoLatestForceRestart() to restart even with same key

MUST be called inside an Effect:

s.Effect(func() vango.Cleanup {
    q := query.Get()
    return vango.GoLatest(q,
        func(ctx context.Context, q string) ([]User, error) {
            return api.SearchUsers(ctx, q)
        },
        func(users []User, err error) {
            results.Set(users)
        },
    )
})

See SPEC_ADDENDUM.md §A.2.3.

func Interval

func Interval(d time.Duration, fn func(), opts ...IntervalOption) Cleanup

Interval schedules periodic ticks that execute fn on the session loop. It handles cleanup automatically - the returned Cleanup stops future ticks.

By default, the first tick occurs after duration d. Use IntervalImmediate() to trigger the first tick immediately.

MUST be called inside an Effect and the returned Cleanup SHOULD be returned from that Effect:

s.Effect(func() vango.Cleanup {
    return vango.Interval(time.Second, func() {
        counter.Inc()
    })
})

See SPEC_ADDENDUM.md §A.2.1.

func Subscribe

func Subscribe[T any](stream Stream[T], fn func(T), opts ...SubscribeOption) Cleanup

Subscribe connects to an event stream and invokes fn for each message on the session loop. The returned Cleanup unsubscribes from the stream.

MUST be called inside an Effect and the returned Cleanup SHOULD be returned from that Effect:

s.Effect(func() vango.Cleanup {
    return vango.Subscribe(ws.Messages, func(msg Message) {
        messages.Append(msg)
    })
})

See SPEC_ADDENDUM.md §A.2.2.

func Timeout

func Timeout(d time.Duration, fn func(), opts ...TimeoutOption) Cleanup

Timeout creates a one-shot timer that executes fn after duration d. Returns a Cleanup that cancels the timer if called before it fires.

This is a simpler alternative to Interval for single delayed operations:

s.Effect(func() vango.Cleanup {
    return vango.Timeout(5*time.Second, func() {
        showTooltip.Set(true)
    })
})

type Component

type Component = vdom.Component

Component is an alias for vdom.Component for convenience. Components are anything that can render to a VNode.

func DefaultPersistErrorBanner

func DefaultPersistErrorBanner() Component

DefaultPersistErrorBanner renders the default banner component.

type ConcurrencyPolicy

type ConcurrencyPolicy int

ConcurrencyPolicy defines how an Action handles concurrent Run calls.

const (
	// PolicyCancelLatest cancels prior in-flight work when Run is called again.
	// This is the default policy.
	PolicyCancelLatest ConcurrencyPolicy = iota

	// PolicyDropWhileRunning ignores Run calls while work is in progress.
	PolicyDropWhileRunning

	// PolicyQueue queues Run calls and executes them sequentially.
	PolicyQueue
)

type Context

type Context[T any] struct {
	// contains filtered or unexported fields
}

Context provides dependency injection through the component tree. Create a context with CreateContext, provide values with Provider, and consume values with Use.

Provider scoping (normative): Provider() creates a new owner scope (component boundary) so the provided value is only visible to descendants of the Provider, not to sibling components.

Reactivity (normative): Use() is a reactive hook that subscribes the calling component to the context value. When a Provider re-renders with a new value, all components that called Use() on that context will be re-rendered. See VANGO_ARCHITECTURE_AND_GUIDE.md §3.1.3 and §3.9.10.

Example:

var ThemeContext = vango.CreateContext("light")

func App() vango.Component {
    return vango.Setup(vango.NoProps{}, func(s vango.SetupCtx[vango.NoProps]) vango.RenderFn {
        theme := setup.Signal(&s, "dark")
        return func() *vango.VNode {
            return ThemeContext.Provider(theme.Get(),
                Header(),
                Main(),
            )
        }
    })
}

func Button() *vango.VNode {
    theme := ThemeContext.Use()  // Subscribes to changes
    return vdom.Button(vdom.Class("btn-" + theme))
}

func CreateContext

func CreateContext[T any](defaultValue T) *Context[T]

CreateContext creates a new context with the given default value. The default value is returned by Use() when no Provider is found in the component tree.

Example:

var ThemeContext = vango.CreateContext("light")
var UserContext = vango.CreateContext[*User](nil)

func (*Context[T]) Default

func (c *Context[T]) Default() T

Default returns the default value for this context.

func (*Context[T]) Provider

func (c *Context[T]) Provider(value T, children ...any) *vdom.VNode

Provider wraps children with this context's value. Descendant components can access the value via Use().

Provider creates a new component boundary (owner scope) so the context value is only visible to descendants, not siblings. This is the proper scoping behavior per the spec.

The provider is reactive: when the value changes and the parent component re-renders, all descendants that called Use() will also re-render.

Example:

func App() vango.Component {
    return vango.Setup(vango.NoProps{}, func(s vango.SetupCtx[vango.NoProps]) vango.RenderFn {
        theme := setup.Signal(&s, "dark")
        return func() *vango.VNode {
            return ThemeContext.Provider(theme.Get(),
                Header(),
                Main(),
                Footer(),
            )
        }
    })
}

func (*Context[T]) Use

func (c *Context[T]) Use() T

Use retrieves the context value from the nearest Provider ancestor. If no Provider is found, returns the default value.

This is a reactive hook: it subscribes the calling component to the context value. When the Provider re-renders with a new value, this component will also re-render.

This MUST be called unconditionally during render (hook-order semantics). See §3.1.3 Hook-Order Semantics.

Example:

func Button() *vango.VNode {
    theme := ThemeContext.Use()
    return vdom.Button(vdom.Class("btn-" + theme))
}

type Ctx

type Ctx interface {
	// Dispatch queues a function to run on the session's event loop.
	// This is safe to call from any goroutine and is the correct way to
	// update signals from asynchronous operations.
	//
	// Prefer Vango primitives (Action/Resource/GoLatest/Subscribe/Interval/Timeout)
	// over ad hoc concurrency. Dispatch is primarily for integrating with
	// external libraries that invoke callbacks off the session loop.
	//
	// Example (callback invoked off-loop by a library):
	//
	//	unsubscribe := emitter.OnEvent(func(ev Event) {
	//	    ctx.Dispatch(func() {
	//	        lastEvent.Set(ev)
	//	    })
	//	})
	//	defer unsubscribe()
	Dispatch(fn func())

	// StdContext returns the standard library context with trace propagation.
	// Use this when calling external services or database drivers.
	//
	// Example:
	//     row := db.QueryRowContext(ctx.StdContext(), "SELECT * FROM users WHERE id = $1", userID)
	StdContext() context.Context

	// StormBudget returns the storm budget checker for this session.
	// Used by primitives (Action, Resource, GoLatest) to check rate limits.
	// Returns nil if storm budgets are not configured.
	//
	// See SPEC_ADDENDUM.md §A.4 for storm budget configuration.
	StormBudget() StormBudgetChecker

	// Session returns the active session, if any.
	// Typed session keys use this to persist state.
	Session() Session
}

Ctx is the runtime context interface available during render, effects, and event handlers. It provides access to the current request, session, and utility methods.

Use UseCtx() to obtain the current context within a component.

func UseCtx

func UseCtx() Ctx

UseCtx returns the current runtime context for the active session tick. It MUST only be called during a component render, effect, or event handler.

Returns nil if called outside of a render/effect/handler context.

Example:

func MyComponent() vango.Component {
    return vango.Setup(vango.NoProps{}, func(s vango.SetupCtx[vango.NoProps]) vango.RenderFn {
        type User struct {
            Name string
        }

        users := map[int]User{
            1: {Name: "Ada"},
            2: {Name: "Grace"},
        }
        loadUser := func(ctx context.Context, id int) (User, error) {
            select {
            case <-ctx.Done():
                return User{}, ctx.Err()
            case <-time.After(50 * time.Millisecond):
            }
            u, ok := users[id]
            if !ok {
                return User{}, fmt.Errorf("user %d: %w", id, errors.New("not found"))
            }
            return u, nil
        }

        userID := setup.Signal(&s, 1)
        user := setup.Signal(&s, User{})
        loadErr := setup.Signal(&s, error(nil))

        s.Effect(func() vango.Cleanup {
            id := userID.Get()
            return vango.GoLatest(id, loadUser, func(u User, err error) {
                loadErr.Set(err)
                if err == nil {
                    user.Set(u)
                }
            })
        })

        return func() *vango.VNode {
            if err := loadErr.Get(); err != nil {
                return Div(Text(err.Error()))
            }
            return Div(Text(user.Get().Name))
        }
    })
}

type DebugConfig

type DebugConfig struct {
	// IncludeSourceLocations includes file:line in debug messages.
	// Useful for tracing signal/effect creation locations.
	// Default: false (for performance).
	IncludeSourceLocations bool

	// LogRawKeys logs signal persist keys and internal identifiers.
	// Useful for debugging state persistence issues.
	// Default: false.
	LogRawKeys bool

	// LogEffectRuns logs each effect run with timing information.
	// Useful for debugging performance issues.
	// Default: false.
	LogEffectRuns bool

	// LogStormBudget logs when storm budgets are checked or exceeded.
	// Useful for tuning budget limits.
	// Default: false.
	LogStormBudget bool
}

DebugConfig controls debugging features for development. These settings affect logging and error messages.

func DefaultDebugConfig

func DefaultDebugConfig() DebugConfig

DefaultDebugConfig returns a DebugConfig with all debugging disabled. Enable individual options as needed for development.

type Dependency

type Dependency interface {
	// ID is a stable, process-local identifier for this dependency.
	ID() uint64

	// Unsubscribe removes the given listener from this dependency.
	Unsubscribe(listener Listener)
}

Dependency is a reactive source that can be unsubscribed from.

This is a framework-internal interface primarily used by the server runtime to track per-render dependencies for components so that stale subscriptions can be removed when a component stops reading a dependency.

It is intentionally narrow: user code typically never needs to interact with Dependency values directly.

type DependencyTracker

type DependencyTracker interface {
	TrackDependency(dep Dependency)
}

DependencyTracker is implemented by listeners (typically component instances) that want to record which dependencies they read during the current tracking scope (usually a render). The runtime uses this to unsubscribe from stale dependencies between renders.

type DragEvent

type DragEvent struct {
	// Position relative to viewport
	ClientX int
	ClientY int

	// Modifier keys
	CtrlKey  bool
	ShiftKey bool
	AltKey   bool
	MetaKey  bool
	// contains filtered or unexported fields
}

DragEvent represents a drag-and-drop event. Per spec section 3.9.3, lines 1181-1200.

func (*DragEvent) GetData

func (d *DragEvent) GetData(format string) string

GetData gets data from the drag operation.

func (*DragEvent) HasData

func (d *DragEvent) HasData(format string) bool

HasData returns true if the format exists in the data transfer.

func (*DragEvent) SetData

func (d *DragEvent) SetData(format, data string)

SetData sets data for the drag operation.

type DropEvent

type DropEvent = DragEvent

DropEvent is an alias for DragEvent used on drop targets. Per spec section 3.9.3, lines 1197-1199.

type Effect

type Effect struct {
	// contains filtered or unexported fields
}

Effect represents a reactive side effect that runs when its dependencies change. Effects are created using SetupCtx.Effect and are automatically tracked for dependencies during their execution.

Effects run after commit when created during render, and re-run whenever any signal or memo they read during execution changes. If created outside render, they run immediately. They can return a Cleanup function that will be called before the effect re-runs or when the effect is disposed.

func (*Effect) GetCallSiteData

func (e *Effect) GetCallSiteData(idx int) any

GetCallSiteData retrieves stored state for a specific call-site index. Returns nil if no state has been stored for this call-site. Used by effect helpers like GoLatest to maintain state across effect reruns.

func (*Effect) ID

func (e *Effect) ID() uint64

ID returns the unique identifier for this effect. Implements the Listener interface.

func (*Effect) MarkDirty

func (e *Effect) MarkDirty()

MarkDirty marks the effect as needing to re-run. Implements the Listener interface.

func (*Effect) Metadata

func (e *Effect) Metadata() vruntime.PrimitiveMetadata

Metadata returns identity metadata for the primitive.

func (*Effect) SetCallSiteData

func (e *Effect) SetCallSiteData(idx int, data any)

SetCallSiteData stores state for a specific call-site index. Used by effect helpers like GoLatest to maintain state across effect reruns.

type EffectOption

type EffectOption interface {
	// contains filtered or unexported methods
}

EffectOption is an option for configuring an Effect.

func AllowWrites

func AllowWrites() EffectOption

AllowWrites marks an effect as intentionally performing signal writes. Without this option, signal writes during the effect body will trigger a warning (StrictEffectWarn) or panic (StrictEffectPanic).

Most patterns don't need this - writes inside ctx.Dispatch callbacks (as with Interval, Subscribe, GoLatest) are not effect-time writes.

Use this only for rare cases like synchronous initialization:

s.Effect(func() vango.Cleanup {
    syncedValue.Set(legacySystem.ReadCurrentSync())
    return nil
}, vango.AllowWrites())

See SPEC_ADDENDUM.md §A.3.

func EffectTxName

func EffectTxName(name string) EffectOption

EffectTxName sets the transaction name for the effect. This name appears in warnings and DevTools entries for this effect. It does NOT propagate to helper transactions (Interval/Subscribe/GoLatest).

type EventRateLimitConfig

type EventRateLimitConfig struct {
	RatePerSecond float64
	Burst         int
}

EventRateLimitConfig configures token bucket rate limiting for events. RatePerSecond <= 0 disables rate limiting.

func DefaultDOMEventRateLimitConfig

func DefaultDOMEventRateLimitConfig() *EventRateLimitConfig

DefaultDOMEventRateLimitConfig returns a default rate limit for standard DOM events. Designed to allow 120Hz input while still providing DoS backpressure.

func DefaultEventRateLimitConfig

func DefaultEventRateLimitConfig() *EventRateLimitConfig

DefaultEventRateLimitConfig returns a conservative default rate limit.

type Float64Signal deprecated

type Float64Signal struct {
	*Signal[float64]
}

Float64Signal wraps Signal[float64] with convenience methods for float operations.

Deprecated: Use setup.Signal inside vango.Setup. Signal[float64] now has Add(), Sub(), Mul(), and Div() methods directly available.

func NewFloat64Signal deprecated

func NewFloat64Signal(initial float64) *Float64Signal

NewFloat64Signal creates a new Float64Signal with the given initial value.

Deprecated: Use setup.Signal inside vango.Setup. Signal[float64] now has Add(), Sub(), Mul(), and Div() methods directly available.

func (*Float64Signal) Add

func (s *Float64Signal) Add(n float64)

Add adds the given value.

func (*Float64Signal) Div

func (s *Float64Signal) Div(n float64)

Div divides by the given value.

func (*Float64Signal) Mul

func (s *Float64Signal) Mul(n float64)

Mul multiplies by the given value.

func (*Float64Signal) Multiply

func (s *Float64Signal) Multiply(n float64)

Multiply is an alias for Mul. Deprecated: use Mul instead.

func (*Float64Signal) Sub

func (s *Float64Signal) Sub(n float64)

Sub subtracts the given value.

type FormData

type FormData struct {
	// contains filtered or unexported fields
}

FormData represents submitted form data. Per spec section 3.9.3, lines 1169-1179.

func NewFormData

func NewFormData(values map[string][]string) FormData

NewFormData creates a new FormData from a map of values.

func NewFormDataFromSingle

func NewFormDataFromSingle(values map[string]string) FormData

NewFormDataFromSingle creates FormData from a single-value map. This is for backward compatibility with the old map[string]string format.

func (FormData) All

func (f FormData) All() map[string]string

All returns all form fields as a map. For fields with multiple values, only the first value is returned.

func (FormData) AllValues added in v0.1.0

func (f FormData) AllValues() map[string][]string

AllValues returns a deep copy of all submitted form values.

func (FormData) Get

func (f FormData) Get(key string) string

Get returns the first value for a form field.

func (FormData) GetAll

func (f FormData) GetAll(key string) []string

GetAll returns all values for a form field.

func (FormData) Has

func (f FormData) Has(key string) bool

Has returns whether a form field exists.

func (FormData) Keys

func (f FormData) Keys() []string

Keys returns all form field names.

type FormErrors added in v0.1.0

type FormErrors map[string][]string

FormErrors is the multi-error shape used by progressive form actions.

type FormResult added in v0.1.0

type FormResult struct {
	// contains filtered or unexported fields
}

FormResult is the structured outcome returned by progressive route actions.

func Invalid added in v0.1.0

func Invalid(errors FormErrors) *FormResult

Invalid returns a validation outcome for a progressive form action.

func RedirectTo added in v0.1.0

func RedirectTo(path string) *FormResult

RedirectTo returns a redirect outcome for a progressive form action.

func ValidationFailed added in v0.1.0

func ValidationFailed(errors FormErrors, parseErrors map[string]string) *FormResult

ValidationFailed returns an invalid form outcome with both validation and parse errors. It is intended for framework integrations that share the same structured outcome path.

func (*FormResult) Errors added in v0.1.0

func (r *FormResult) Errors() FormErrors

Errors returns a copy of the validation errors carried by the result.

func (*FormResult) IsInvalid added in v0.1.0

func (r *FormResult) IsInvalid() bool

IsInvalid reports whether the result is invalid.

func (*FormResult) IsRedirect added in v0.1.0

func (r *FormResult) IsRedirect() bool

IsRedirect reports whether the result is a redirect.

func (*FormResult) ParseErrors added in v0.1.0

func (r *FormResult) ParseErrors() map[string]string

ParseErrors returns a copy of the parse errors carried by the result.

func (*FormResult) RedirectPath added in v0.1.0

func (r *FormResult) RedirectPath() string

RedirectPath returns the redirect destination.

type GlobalBroadcastBackend

type GlobalBroadcastBackend interface {
	Publish(ctx context.Context, channel string, data []byte) error
	Subscribe(ctx context.Context, channel string) (<-chan []byte, error)
}

GlobalBroadcastBackend broadcasts updates to other instances.

func NewMemoryPubSub

func NewMemoryPubSub() GlobalBroadcastBackend

NewMemoryPubSub creates an in-memory broadcast backend. Intended for tests or single-process development.

func NewRedisPubSub

func NewRedisPubSub(client *redis.Client) GlobalBroadcastBackend

NewRedisPubSub creates a Redis-backed broadcast backend.

type GlobalPersistenceBackend

type GlobalPersistenceBackend interface {
	Get(ctx context.Context, key string) ([]byte, error)
	Set(ctx context.Context, key string, value []byte) error
	// SetManyAtomic persists a batch of keys atomically.
	//
	// Implementations MUST commit the provided batch atomically. Callers are
	// responsible for ensuring any backend-specific constraints are satisfied
	// by the keys (e.g. Redis Cluster hash slot co-location).
	SetManyAtomic(ctx context.Context, values map[string][]byte) error
	Delete(ctx context.Context, key string) error
}

GlobalPersistenceBackend stores global signal values.

type GlobalSignalStore

type GlobalSignalStore struct {
	// contains filtered or unexported fields
}

GlobalSignalStore manages global signals across all sessions.

func NewGlobalSignalStore

func NewGlobalSignalStore(backend GlobalPersistenceBackend, pubsub GlobalBroadcastBackend, opts ...GlobalSignalStoreOption) *GlobalSignalStore

NewGlobalSignalStore creates a global signal store.

func (*GlobalSignalStore) ApplyEncoded

func (gs *GlobalSignalStore) ApplyEncoded(stableID string, encoded []byte) (bool, error)

ApplyEncoded applies an encoded global signal update on the session loop.

func (*GlobalSignalStore) GetOrCreateSignal

func (gs *GlobalSignalStore) GetOrCreateSignal(
	ctx context.Context,
	stableID string,
	fingerprint codec.Fingerprint,
	initializer func() any,
	decode func([]byte) (any, error),
	createSignal func(any) any,
) (any, error)

GetOrCreate retrieves or creates a global signal.

func (*GlobalSignalStore) RefreshAll

func (gs *GlobalSignalStore) RefreshAll(ctx context.Context) ([]GlobalSignalUpdate, error)

RefreshAll fetches latest values for known global signals.

func (*GlobalSignalStore) Set

func (gs *GlobalSignalStore) Set(stableID string, value any) error

Set updates a global signal value and persists it.

func (*GlobalSignalStore) SetBroadcastHandler

func (gs *GlobalSignalStore) SetBroadcastHandler(ctx context.Context, handler func(stableID string, encoded []byte))

SetBroadcastHandler registers a handler for pubsub-delivered updates. The handler is invoked with the stable ID and encoded payload.

func (*GlobalSignalStore) SetBudgetTracker

func (gs *GlobalSignalStore) SetBudgetTracker(tracker *BudgetTracker)

SetBudgetTracker sets the budget tracker for global signals.

type GlobalSignalStoreOption

type GlobalSignalStoreOption interface {
	// contains filtered or unexported methods
}

func WithGlobalSignalSecrets

func WithGlobalSignalSecrets(secret []byte, previous []byte) GlobalSignalStoreOption

WithGlobalSignalSecrets configures HMAC secrets for global signal persistence. When a backend or pubsub is configured, secrets are required for integrity.

type GlobalSignalUpdate

type GlobalSignalUpdate struct {
	StableID string
	Encoded  []byte
}

GlobalSignalUpdate contains a refreshed global signal payload.

type GoLatestOption

type GoLatestOption interface {
	// contains filtered or unexported methods
}

GoLatestOption is an option for configuring GoLatest.

func GoLatestForceRestart

func GoLatestForceRestart() GoLatestOption

GoLatestForceRestart causes work to restart even when the key is unchanged. By default, same key = no new work (existing work continues).

func GoLatestTxName

func GoLatestTxName(name string) GoLatestOption

GoLatestTxName sets the transaction name for observability. Work will appear in DevTools as GoLatest:<name>.

type HTTPError

type HTTPError struct {
	Code    int    // HTTP status code (e.g., 400, 403, 404, 500)
	Message string // Error message to return to client
	Err     error  // Optional underlying error
}

HTTPError represents an HTTP error with a status code and message. It implements the error interface and can be returned from API handlers to send appropriate HTTP status codes to clients.

func BadRequest

func BadRequest(err error) *HTTPError

BadRequest creates a 400 Bad Request error. Use this when the client sent invalid data.

Example:

if err := validate(input); err != nil {
    return nil, vango.BadRequest(err)
}

func BadRequestf

func BadRequestf(format string, args ...any) *HTTPError

BadRequestf creates a 400 Bad Request error with a formatted message.

func Conflict

func Conflict(message ...string) *HTTPError

Conflict creates a 409 Conflict error. Use this when the request conflicts with the current state.

func Forbidden

func Forbidden(message ...string) *HTTPError

Forbidden creates a 403 Forbidden error. Use this when the user is authenticated but lacks permission.

Example:

if !user.HasRole("admin") {
    return nil, vango.Forbidden()
}

func InternalError

func InternalError(err error) *HTTPError

InternalError creates a 500 Internal Server Error. Use this for unexpected server errors. Consider logging the underlying error.

func NotFound

func NotFound(message ...string) *HTTPError

NotFound creates a 404 Not Found error. Use this when the requested resource doesn't exist.

func ServiceUnavailable

func ServiceUnavailable(message ...string) *HTTPError

ServiceUnavailable creates a 503 Service Unavailable error. Use this when the server is temporarily unable to handle requests.

func Unauthorized

func Unauthorized(message ...string) *HTTPError

Unauthorized creates a 401 Unauthorized error. Use this when authentication is required but not provided.

func UnprocessableEntity

func UnprocessableEntity(message ...string) *HTTPError

UnprocessableEntity creates a 422 Unprocessable Entity error. Use this for validation errors on semantically correct but invalid data.

func (*HTTPError) Error

func (e *HTTPError) Error() string

Error implements the error interface.

func (*HTTPError) StatusCode

func (e *HTTPError) StatusCode() int

StatusCode returns the HTTP status code for this error.

func (*HTTPError) Unwrap

func (e *HTTPError) Unwrap() error

Unwrap returns the underlying error for errors.Is/As support.

type Handler

type Handler interface {
	// contains filtered or unexported methods
}

Handler handles a specific resource state.

func OnError

func OnError(fn func(error) *vdom.VNode) Handler

OnError handles the Error state.

func OnLoading

func OnLoading(fn func() *vdom.VNode) Handler

OnLoading handles the Loading state.

func OnLoadingOrPending

func OnLoadingOrPending(fn func() *vdom.VNode) Handler

OnLoadingOrPending handles both Loading and Pending states.

func OnPending

func OnPending(fn func() *vdom.VNode) Handler

OnPending handles the Pending state.

func OnReady

func OnReady[T any](fn func(T) *vdom.VNode) Handler

OnReady handles the Ready state.

type HookEvent

type HookEvent struct {
	// Name of the hook event
	Name string

	// Arbitrary data from the client
	Data map[string]any
	// contains filtered or unexported fields
}

HookEvent represents a client hook event. Per spec section 3.9.3, line 1018.

func (HookEvent) Bool

func (h HookEvent) Bool(key string) bool

Bool returns a bool value from the hook data (spec-aligned).

func (HookEvent) Float

func (h HookEvent) Float(key string) float64

Float returns a float64 value from the hook data (spec-aligned).

func (HookEvent) Get

func (h HookEvent) Get(key string) any

Get returns a value from the hook data.

func (HookEvent) GetBool

func (h HookEvent) GetBool(key string) bool

GetBool returns a bool value from the hook data.

func (HookEvent) GetFloat

func (h HookEvent) GetFloat(key string) float64

GetFloat returns a float64 value from the hook data.

func (HookEvent) GetInt

func (h HookEvent) GetInt(key string) int

GetInt returns an int value from the hook data.

func (HookEvent) GetString

func (h HookEvent) GetString(key string) string

GetString returns a string value from the hook data.

func (HookEvent) GetStrings

func (h HookEvent) GetStrings(key string) []string

GetStrings returns a []string value from the hook data.

func (HookEvent) Int

func (h HookEvent) Int(key string) int

Int returns an int value from the hook data (spec-aligned).

func (HookEvent) Raw

func (h HookEvent) Raw(key string) any

Raw returns a raw value from the hook data (spec-aligned).

func (HookEvent) Revert

func (h HookEvent) Revert()

Revert sends a revert signal to the client hook. Used for optimistic update rollback.

func (*HookEvent) SetContext

func (h *HookEvent) SetContext(hid string, dispatch func(name string, payload any))

SetContext sets the internal context for the hook event. This is called by the runtime when dispatching hook events.

func (HookEvent) String

func (h HookEvent) String(key string) string

String returns a best-effort string value from the hook data (spec-aligned). Unlike GetString, this will format non-string values.

func (HookEvent) Strings

func (h HookEvent) Strings(key string) []string

Strings returns a []string value from the hook data (spec-aligned).

type HookEventHandlerSpec added in v0.2.0

type HookEventHandlerSpec struct {
	Name      string
	Validator HookEventValidator
	Handler   func(HookEvent)
}

HookEventHandlerSpec preserves exact hook event metadata for runtime policy enforcement while still carrying the user handler callback.

type HookEventValidator

type HookEventValidator func(HookEvent) error

HookEventValidator validates a hook event payload. Return an error to reject the event.

func HookSchemaValidator

func HookSchemaValidator[T any](validate func(HookEvent, T) error) HookEventValidator

HookSchemaValidator builds a HookEventValidator that decodes hook payload data into a typed schema using strict JSON rules (unknown fields are rejected).

The callback may be nil to run schema decoding only.

func HookValidatorMap added in v0.2.0

func HookValidatorMap(validators map[string]HookEventValidator) HookEventValidator

HookValidatorMap dispatches hook payload validation by exact hook event name. Unknown names are rejected.

type HookType

type HookType uint8

HookType identifies the type of hook call for order validation.

const (
	HookSignal HookType = iota + 1
	HookMemo
	HookEffect
	HookResource
	HookForm
	HookURLParam
	HookRef
	HookContext
	HookAction // Phase 16: Action API
)

func (HookType) String

func (h HookType) String() string

String returns a human-readable name for the hook type.

type InputEvent

type InputEvent struct {
	// Current value of the input
	Value string

	// Type of input change (e.g., "insertText", "deleteContentBackward")
	InputType string

	// Data being inserted (if any)
	Data string
}

InputEvent represents an input field change event. Per spec section 3.9.3, lines 1131-1133.

type Int64Signal deprecated

type Int64Signal struct {
	*Signal[int64]
}

Int64Signal wraps Signal[int64] with convenience methods for integer operations.

Deprecated: Use setup.Signal inside vango.Setup. Signal[int64] now has Inc(), Dec(), Add(), Sub(), Mul(), and Div() methods directly available.

func NewInt64Signal deprecated

func NewInt64Signal(initial int64) *Int64Signal

NewInt64Signal creates a new Int64Signal with the given initial value.

Deprecated: Use setup.Signal inside vango.Setup. Signal[int64] now has Inc(), Dec(), Add(), Sub(), Mul(), and Div() methods directly available.

func (*Int64Signal) Add

func (s *Int64Signal) Add(n int64)

Add adds the given value.

func (*Int64Signal) Dec

func (s *Int64Signal) Dec()

Dec decrements the value by 1.

func (*Int64Signal) Div

func (s *Int64Signal) Div(n int64)

Div divides by the given value. Note: Integer division truncates toward zero.

func (*Int64Signal) Inc

func (s *Int64Signal) Inc()

Inc increments the value by 1.

func (*Int64Signal) Mul

func (s *Int64Signal) Mul(n int64)

Mul multiplies by the given value.

func (*Int64Signal) Sub

func (s *Int64Signal) Sub(n int64)

Sub subtracts the given value.

type IntSignal deprecated

type IntSignal struct {
	*Signal[int]
}

IntSignal wraps Signal[int] with convenience methods for integer operations.

Deprecated: Use setup.Signal inside vango.Setup. Signal[int] now has Inc(), Dec(), Add(), Sub(), Mul(), and Div() methods directly available.

// Old:
count := vango.NewIntSignal(0)
count.Inc()

// New:
count := setup.Signal(&s, 0)
count.Inc()

func NewIntSignal deprecated

func NewIntSignal(initial int) *IntSignal

NewIntSignal creates a new IntSignal with the given initial value.

Deprecated: Use setup.Signal inside vango.Setup. Signal[int] now has Inc(), Dec(), Add(), Sub(), Mul(), and Div() methods directly available.

func (*IntSignal) Add

func (s *IntSignal) Add(n int)

Add adds the given value.

func (*IntSignal) Dec

func (s *IntSignal) Dec()

Dec decrements the value by 1.

func (*IntSignal) Div

func (s *IntSignal) Div(n int)

Div divides by the given value. Note: Integer division truncates toward zero.

func (*IntSignal) Inc

func (s *IntSignal) Inc()

Inc increments the value by 1.

func (*IntSignal) Mul

func (s *IntSignal) Mul(n int)

Mul multiplies by the given value.

func (*IntSignal) Sub

func (s *IntSignal) Sub(n int)

Sub subtracts the given value.

type IntervalOption

type IntervalOption interface {
	// contains filtered or unexported methods
}

IntervalOption is an option for configuring Interval.

func IntervalImmediate

func IntervalImmediate() IntervalOption

IntervalImmediate causes the first tick to occur immediately instead of after the duration.

func IntervalTxName

func IntervalTxName(name string) IntervalOption

IntervalTxName sets the transaction name for observability. Ticks will appear in DevTools as Interval:<name>.

type IslandMessage

type IslandMessage struct {
	// ID is the island name/module identifier (the value of data-island).
	ID string

	// HID is the unique instance address (the hydration id of the island boundary element).
	// This allows multiple instances with the same ID to coexist on a page.
	HID string

	Raw json.RawMessage
}

IslandMessage represents a message sent between an island and the server.

type IslandMessageHandler

type IslandMessageHandler func(IslandMessage)

IslandMessageHandler handles messages emitted by client islands.

type IslandMessageHandlerSpec added in v0.2.0

type IslandMessageHandlerSpec struct {
	Validator IslandMessageValidator
	Handler   func(IslandMessage)
}

IslandMessageHandlerSpec preserves per-instance island validation metadata.

type IslandMessageValidator

type IslandMessageValidator func(IslandMessage) error

IslandMessageValidator validates an island message payload. Return an error to reject the message.

func IslandSchemaValidator

func IslandSchemaValidator[T any](validate func(IslandMessage, T) error) IslandMessageValidator

IslandSchemaValidator builds an IslandMessageValidator that decodes island message payloads into a typed schema using strict JSON rules.

The callback may be nil to run schema decoding only.

func IslandValidatorMap added in v0.2.0

func IslandValidatorMap(validators map[string]IslandMessageValidator) IslandMessageValidator

IslandValidatorMap dispatches island payload validation by exact island ID. Unknown IDs are rejected.

type IslandMessenger

type IslandMessenger interface {
	RegisterIslandHandler(id string, handler IslandMessageHandler) func()
	SendIslandMessage(id string, payload any) error
	SendIslandMessageToHID(hid string, payload any) error
}

IslandMessenger describes session capabilities for island messaging.

type IslandValidatedMessenger added in v0.2.0

type IslandValidatedMessenger interface {
	IslandMessenger
	RegisterValidatedIslandHandler(id string, validate IslandMessageValidator, handler IslandMessageHandler) func()
}

IslandValidatedMessenger extends island messaging with exact-sink validator registration so the runtime can enforce strict non-dev coverage.

type KeyMod

type KeyMod uint8

KeyMod represents keyboard modifier flags for KeyWithModifiers.

const (
	// Ctrl modifier (Control key)
	Ctrl KeyMod = 0x01

	// Shift modifier
	Shift KeyMod = 0x02

	// Alt modifier (Option on Mac)
	Alt KeyMod = 0x04

	// Meta modifier (Cmd on Mac, Windows key on Windows)
	Meta KeyMod = 0x08
)

func (KeyMod) Has

func (k KeyMod) Has(mod KeyMod) bool

Has returns true if the specified modifier is set.

func (KeyMod) String

func (k KeyMod) String() string

String returns a human-readable representation of the modifiers.

type KeyboardEvent

type KeyboardEvent struct {
	// The key value (e.g., "Enter", "a", "Escape")
	Key string

	// The physical key code (e.g., "Enter", "KeyA", "Escape")
	Code string

	// Modifier keys
	CtrlKey  bool
	ShiftKey bool
	AltKey   bool
	MetaKey  bool

	// True if key is being held down (auto-repeat)
	Repeat bool

	// Key location: 0=standard, 1=left, 2=right, 3=numpad
	Location int
}

KeyboardEvent represents a keyboard event with key and modifiers. Per spec section 3.9.3, lines 1091-1103.

type Listener

type Listener interface {
	// MarkDirty notifies the listener that one of its dependencies has changed.
	// For components, this schedules a re-render.
	// For memos, this invalidates the cached value.
	// For effects, this schedules the effect to re-run.
	MarkDirty()

	// ID returns a unique identifier for this listener.
	// Used for deduplication during batch processing.
	ID() uint64
}

Listener is anything that can be notified when a dependency changes. This interface is implemented by components, memos, and effects.

type MapSignal deprecated

type MapSignal[K comparable, V any] struct {
	*Signal[map[K]V]
}

MapSignal wraps Signal[map[K]V] with convenience methods for map operations.

Deprecated: Use setup.Signal inside vango.Setup. Signal[map[K]V] now has SetKey(), GetKey(), UpdateKey(), RemoveKey(), HasKey(), Keys(), Values(), Clear(), and Len() methods directly available.

Note: MapSignal[K,V] provides type-safe methods (e.g., SetKey(key K, value V)) while the Signal[T] methods use any-typed map helpers (e.g., GetKey(key any) (any, bool)). Typed code can also read through Get()[key] directly. Use MapSignal[K,V] if you prefer compile-time type safety over the unified API while keeping the same semantics.

// Old:
users := vango.NewMapSignal(map[string]User{})
users.SetKey("alice", alice)

// New:
users := setup.Signal(&s, map[string]User{})
users.SetKey("alice", alice)  // Note: uses 'any' parameters

func NewMapSignal deprecated

func NewMapSignal[K comparable, V any](initial map[K]V) *MapSignal[K, V]

NewMapSignal creates a new MapSignal with the given initial value. If initial is nil, creates an empty map.

Deprecated: Use setup.Signal inside vango.Setup. Signal[map[K]V] now has map convenience methods directly available. MapSignal[K,V] is retained for type-safe map operations if preferred.

func (*MapSignal[K, V]) Clear

func (s *MapSignal[K, V]) Clear()

Clear removes all keys from the map.

func (*MapSignal[K, V]) DeleteKey

func (s *MapSignal[K, V]) DeleteKey(key K)

DeleteKey removes a key from the map. Deprecated: use RemoveKey instead.

func (*MapSignal[K, V]) GetKey

func (s *MapSignal[K, V]) GetKey(key K) (V, bool)

GetKey returns the value for a key. This reads the signal and creates a dependency.

func (*MapSignal[K, V]) HasKey

func (s *MapSignal[K, V]) HasKey(key K) bool

HasKey returns true if the key exists in the map. This reads the signal and creates a dependency.

func (*MapSignal[K, V]) Keys

func (s *MapSignal[K, V]) Keys() []K

Keys returns all keys in the map. This reads the signal and creates a dependency.

func (*MapSignal[K, V]) Len

func (s *MapSignal[K, V]) Len() int

Len returns the number of keys in the map. This reads the signal and creates a dependency.

func (*MapSignal[K, V]) RemoveKey

func (s *MapSignal[K, V]) RemoveKey(key K)

RemoveKey removes a key from the map.

func (*MapSignal[K, V]) SetKey

func (s *MapSignal[K, V]) SetKey(key K, value V)

SetKey sets a key-value pair in the map.

func (*MapSignal[K, V]) UpdateKey

func (s *MapSignal[K, V]) UpdateKey(key K, fn func(V) V)

UpdateKey updates the value for a key using the provided function. Does nothing if the key doesn't exist.

func (*MapSignal[K, V]) Values

func (s *MapSignal[K, V]) Values() []V

Values returns all values in the map. This reads the signal and creates a dependency.

type Memo

type Memo[T any] struct {
	// contains filtered or unexported fields
}

Memo is a cached computation that automatically tracks its dependencies. When any dependency changes, the memo is invalidated and will recompute on the next read.

Memos are lazy: they only compute their value when Get() is called. If multiple signals change before a read, the memo only recomputes once.

Memos can also be subscribed to, behaving like signals themselves. This allows building chains of derived values.

func SetupMemo

func SetupMemo[P any, T any](s *SetupCtx[P], compute func() T) *Memo[T]

SetupMemo creates a local memo during Setup.

func (*Memo[T]) Get

func (m *Memo[T]) Get() T

Get returns the memo's value, recomputing if necessary. Creates a dependency on this memo for the current listener.

func (*Memo[T]) ID

func (m *Memo[T]) ID() uint64

ID returns the unique identifier for this memo. Implements the Listener interface.

func (*Memo[T]) MarkDirty

func (m *Memo[T]) MarkDirty()

MarkDirty invalidates the memo and propagates to subscribers. Implements the Listener interface.

func (*Memo[T]) Metadata

func (m *Memo[T]) Metadata() vruntime.PrimitiveMetadata

Metadata returns identity metadata for the primitive.

func (*Memo[T]) Peek

func (m *Memo[T]) Peek() T

Peek returns the memo's value without subscribing. Still triggers recomputation if the value is invalid.

func (*Memo[T]) Unsubscribe

func (m *Memo[T]) Unsubscribe(listener Listener)

Unsubscribe removes a listener from this memo. This is used by the runtime to remove stale subscriptions between renders.

type MemoRef

type MemoRef struct {
	StableID  string
	AnchorKey string
	DebugName string
}

MemoRef is a stable, structured description of a memo instance used for diagnostics. Fields may be empty when metadata is unavailable.

type MetricsSink

type MetricsSink interface {
	RecordSignalWriteViolation(operation, reason string)
	RecordSessionActive(delta int)
	RecordSessionDetached(delta int)
	RecordResumeSuccess()
	RecordResumeFailure(reason string)
	RecordPatchBytes(route string, bytes int)
	RecordPatchMismatch(reason string)
	RecordResourceDuration(resource string, ms int64)
	RecordResourceError(resource string)
	RecordActionDuration(action string, ms int64)
	RecordActionError(action string)
	RecordSchemaMismatch(reason string)
	RecordPersistWriteRejected(reason, stableID string)
	RecordPersistBytes(stableID string, bytes int64)
	RecordSessionPersistBytes(sessionID string, bytes int64)
	RecordColdDeployAck(source string)
}

MetricsSink is the interface used by the runtime to record observability metrics. Implementations should be safe for concurrent use.

func MetricsFromContext

func MetricsFromContext(ctx Ctx) MetricsSink

MetricsFromContext returns a metrics sink if available, otherwise a no-op sink.

type ModifiedHandler

type ModifiedHandler struct {
	// The wrapped handler function
	Handler any

	// Client-side modifiers
	PreventDefault  bool // Prevent default browser behavior
	StopPropagation bool // Stop event bubbling
	Self            bool // Only fire if target is the exact element
	Once            bool // Remove handler after first trigger
	Passive         bool // Passive listener (cannot preventDefault)
	Capture         bool // Fire during capture phase

	// Timing modifiers (client-side implementation)
	Debounce time.Duration // Debounce delay
	Throttle time.Duration // Throttle interval

	// Key filtering (server-side implementation)
	KeyFilter    string   // Single key filter (for Hotkey)
	KeysFilter   []string // Multiple keys filter (for Keys)
	KeyModifiers KeyMod   // Required modifiers (for KeyWithModifiers)
}

ModifiedHandler wraps a handler with modifier flags. The runtime recognizes this wrapper and applies the appropriate behavior: - Client-side: PreventDefault, StopPropagation, Self, Passive, Capture, Once (removal from DOM) - Server-side: Once (handler removal), key filtering, Debounce/Throttle timing

func Capture

func Capture(handler any) ModifiedHandler

Capture wraps a handler to fire during the capture phase. Per spec section 3.9.3, lines 1334-1337.

Note: Due to Vango's event delegation architecture (all events are captured at the document level), per-element capture vs bubble phase control has limitations. Some events (focus, blur, scroll, mouseenter, mouseleave) are always captured, while others (click, input, keydown) bubble. This flag is available for documentation and potential future use.

Example:

OnClick(vango.Capture(func() {
    // Fires during capture phase
}))

func Debounce

func Debounce(duration time.Duration, handler any) ModifiedHandler

Debounce wraps a handler with debounce behavior. The handler will only be called after the specified duration has passed since the last event. Per spec section 3.9.3, lines 1339-1342.

Example:

OnInput(vango.Debounce(300*time.Millisecond, func(value string) {
    search(value)
}))

func Hotkey

func Hotkey(key string, handler any) ModifiedHandler

Hotkey wraps a handler to only fire on a specific key. Per spec section 3.9.3, lines 1349-1352.

Example:

OnKeyDown(vango.Hotkey("Enter", func() {
    submit()
}))

OnKeyDown(vango.Hotkey(vango.KeyEscape, func() {
    closeModal()
}))

func KeyWithModifiers

func KeyWithModifiers(key string, mods KeyMod, handler any) ModifiedHandler

KeyWithModifiers wraps a handler to fire on a key with specific modifiers. Per spec section 3.9.3, lines 1358-1364.

Example:

OnKeyDown(vango.KeyWithModifiers("s", vango.Ctrl, func() {
    save() // Ctrl+S
}))

OnKeyDown(vango.KeyWithModifiers("s", vango.Ctrl|vango.Shift, func() {
    saveAs() // Ctrl+Shift+S
}))

func Keys

func Keys(keys []string, handler any) ModifiedHandler

Keys wraps a handler to fire on any of the specified keys. Per spec section 3.9.3, lines 1354-1356.

Example:

OnKeyDown(vango.Keys([]string{"Enter", "NumpadEnter"}, func() {
    submit()
}))

func Once

func Once(handler any) ModifiedHandler

Once wraps a handler to remove it after the first trigger. Per spec section 3.9.3, lines 1324-1327.

Example:

OnClick(vango.Once(func() {
    // Only fires once
}))

func Passive

func Passive(handler any) ModifiedHandler

Passive wraps a handler as a passive listener for scroll performance. Passive handlers cannot call preventDefault. Per spec section 3.9.3, lines 1329-1332.

Example:

OnScroll(vango.Passive(func(e vango.ScrollEvent) {
    // Cannot call preventDefault
}))

func PreventDefault

func PreventDefault(handler any) ModifiedHandler

PreventDefault wraps a handler to prevent the default browser behavior. Per spec section 3.9.3, lines 1304-1307.

Example:

OnClick(vango.PreventDefault(func() {
    // Click handled, default prevented
}))

func Self

func Self(handler any) ModifiedHandler

Self wraps a handler to only fire if the event target is the exact element. Per spec section 3.9.3, lines 1319-1322.

Example:

OnClick(vango.Self(func() {
    // Only fires if clicked element is this exact element
}))

func StopPropagation

func StopPropagation(handler any) ModifiedHandler

StopPropagation wraps a handler to stop event bubbling. Per spec section 3.9.3, lines 1309-1312.

Example:

OnClick(vango.StopPropagation(func() {
    // Click won't bubble up
}))

func Throttle

func Throttle(duration time.Duration, handler any) ModifiedHandler

Throttle wraps a handler with throttle behavior. The handler will be called at most once per specified duration. Per spec section 3.9.3, lines 1344-1347.

Example:

OnMouseMove(vango.Throttle(100*time.Millisecond, func(e vango.MouseEvent) {
    updatePosition(e.ClientX, e.ClientY)
}))

func (ModifiedHandler) Unwrap

func (m ModifiedHandler) Unwrap() any

Unwrap returns the innermost handler, unwrapping any nested ModifiedHandlers.

type MouseEvent

type MouseEvent struct {
	// Position relative to viewport
	ClientX int
	ClientY int

	// Position relative to document
	PageX int
	PageY int

	// Position relative to target element
	OffsetX int
	OffsetY int

	// Button that triggered the event (0=left, 1=middle, 2=right)
	Button int

	// Bitmask of currently pressed buttons
	Buttons int

	// Modifier keys
	CtrlKey  bool
	ShiftKey bool
	AltKey   bool
	MetaKey  bool
}

MouseEvent represents a mouse event with position and modifiers. Per spec section 3.9.3, lines 1059-1075.

type NavigateEvent struct {
	// The path being navigated to
	Path string

	// Whether this is a replace (vs push) navigation
	Replace bool
}

NavigateEvent represents a navigation request event.

type NoProps

type NoProps struct{}

NoProps is the canonical empty-props type for components that don't need props. Use this instead of struct{} or a custom empty struct.

type NoopMetricsSink

type NoopMetricsSink struct{}

NoopMetricsSink is a no-op implementation for optional metrics wiring.

func (NoopMetricsSink) RecordActionDuration

func (NoopMetricsSink) RecordActionDuration(string, int64)

func (NoopMetricsSink) RecordActionError

func (NoopMetricsSink) RecordActionError(string)

func (NoopMetricsSink) RecordColdDeployAck

func (NoopMetricsSink) RecordColdDeployAck(string)

func (NoopMetricsSink) RecordPatchBytes

func (NoopMetricsSink) RecordPatchBytes(string, int)

func (NoopMetricsSink) RecordPatchMismatch

func (NoopMetricsSink) RecordPatchMismatch(string)

func (NoopMetricsSink) RecordPersistBytes

func (NoopMetricsSink) RecordPersistBytes(string, int64)

func (NoopMetricsSink) RecordPersistWriteRejected

func (NoopMetricsSink) RecordPersistWriteRejected(string, string)

func (NoopMetricsSink) RecordResourceDuration

func (NoopMetricsSink) RecordResourceDuration(string, int64)

func (NoopMetricsSink) RecordResourceError

func (NoopMetricsSink) RecordResourceError(string)

func (NoopMetricsSink) RecordResumeFailure

func (NoopMetricsSink) RecordResumeFailure(string)

func (NoopMetricsSink) RecordResumeSuccess

func (NoopMetricsSink) RecordResumeSuccess()

func (NoopMetricsSink) RecordSchemaMismatch

func (NoopMetricsSink) RecordSchemaMismatch(string)

func (NoopMetricsSink) RecordSessionActive

func (NoopMetricsSink) RecordSessionActive(int)

func (NoopMetricsSink) RecordSessionDetached

func (NoopMetricsSink) RecordSessionDetached(int)

func (NoopMetricsSink) RecordSessionPersistBytes

func (NoopMetricsSink) RecordSessionPersistBytes(string, int64)

func (NoopMetricsSink) RecordSignalWriteViolation

func (NoopMetricsSink) RecordSignalWriteViolation(string, string)

type ObservabilityConfig

type ObservabilityConfig struct {
	// LogMutations enables Action/Resource intent/outcome logging.
	LogMutations bool

	// LogTransactions enables TxNamed transaction boundary logging.
	// When enabled, TxNamed emits "vango.tx.start" and "vango.tx.end" structured logs.
	//
	// Default: false.
	LogTransactions bool

	// LogTransactionsIncludeInternal includes internal framework TxNamed calls like:
	// - Action:*
	// - Interval:*
	// - Subscribe:*
	// - GoLatest:*
	// - Timeout:*
	//
	// Default: false.
	LogTransactionsIncludeInternal bool

	// LogTransactionsLevel controls the log level used for tx start/end events.
	// Supported values:
	// - "debug" (default)
	// - "info"
	LogTransactionsLevel string

	// LogTransactionsMaxDepth limits TxNamed nesting depth that will be logged.
	// Depth is 0 for the outermost TxNamed, 1 for nested, etc.
	//
	// Default: 6.
	LogTransactionsMaxDepth int

	// LogTransactionsMaxNameBytes truncates tx names to this many bytes (UTF-8 safe).
	//
	// Default: 120.
	LogTransactionsMaxNameBytes int

	// LogTransactionsAllowedCategories optionally restricts logging to specific categories.
	// Category is the substring before the first ":" in the tx name, or the whole name if no ":" exists.
	//
	// If empty/nil: all categories allowed (subject to internal filtering).
	LogTransactionsAllowedCategories []string

	// TraceTransactionsIncludeName controls whether tx.name is included in trace events.
	// By default, trace events emit only tx.category to avoid high-cardinality attributes.
	//
	// Default: false.
	TraceTransactionsIncludeName bool
}

ObservabilityConfig controls optional observability features. All fields are opt-in and default to false.

type OnChangeRegistration

type OnChangeRegistration[K comparable] struct {
	// contains filtered or unexported fields
}

OnChangeRegistration represents a registered OnChange callback.

func (*OnChangeRegistration[K]) Metadata

Metadata returns identity metadata for the primitive.

type OnMountRegistration

type OnMountRegistration struct {
	// contains filtered or unexported fields
}

OnMountRegistration represents a registered OnMount callback.

func (*OnMountRegistration) Metadata

Metadata returns identity metadata for the primitive.

type Owner

type Owner struct {
	// contains filtered or unexported fields
}

Owner represents a component scope that owns reactive primitives. When an Owner is disposed, all signals, memos, effects, and child owners it contains are also disposed. This ensures proper cleanup and prevents memory leaks.

Owners form a hierarchy: each component creates an Owner that is a child of its parent component's Owner. This mirrors the component tree structure.

func NewOwner

func NewOwner(parent *Owner) *Owner

NewOwner creates a new Owner with the given parent. The new Owner is automatically registered as a child of the parent. If parent is nil, creates a root Owner.

func (*Owner) Dispose

func (o *Owner) Dispose()

Dispose disposes this Owner and all its children, effects, and cleanups. Children are disposed in reverse order (last created first). After disposal, the Owner cannot be used.

func (*Owner) EndRender

func (o *Owner) EndRender()

EndRender is called at the end of a component render. In debug mode, it validates that all expected hooks were called.

func (*Owner) GetValue

func (o *Owner) GetValue(key any) any

GetValue retrieves a value from this Owner or its parents.

func (*Owner) GetValueLocal

func (o *Owner) GetValueLocal(key any) any

GetValueLocal retrieves a value from this Owner only, without checking parents. This is used by context Providers to check if they have already stored a contextValue in their own scope (vs. inheriting from an ancestor).

func (*Owner) HasPendingEffects

func (o *Owner) HasPendingEffects() bool

HasPendingEffects returns true if this owner or any child has pending effects.

func (*Owner) ID

func (o *Owner) ID() uint64

ID returns the unique identifier for this Owner.

func (*Owner) IsDisposed

func (o *Owner) IsDisposed() bool

IsDisposed returns true if this Owner has been disposed.

func (*Owner) MemoryUsage

func (o *Owner) MemoryUsage() int64

MemoryUsage estimates the memory usage of this Owner and its children.

func (*Owner) OnCleanup

func (o *Owner) OnCleanup(fn func())

OnCleanup registers a cleanup function to run when this Owner is disposed.

func (*Owner) Parent

func (o *Owner) Parent() *Owner

Parent returns the parent Owner, or nil if this is a root Owner.

func (*Owner) RunPendingEffects

func (o *Owner) RunPendingEffects(budget StormBudgetChecker)

RunPendingEffects executes all pending effects. This is called after the render phase to run scheduled effects. The server runtime calls this after event handlers execute.

The budget parameter is optional (can be nil). When provided, effects are checked against the per-tick effect budget before running. Effects that exceed the budget are re-scheduled for the next tick.

func (*Owner) SetHookSlot

func (o *Owner) SetHookSlot(value any)

SetHookSlot stores a value in the current hook slot. Must be called after UseHookSlot returns nil (first render).

func (*Owner) SetValue

func (o *Owner) SetValue(key, value any)

SetValue sets a value on this Owner.

func (*Owner) StartRender

func (o *Owner) StartRender()

StartRender is called at the beginning of a component render. It resets the hook slot index for stable identity, and in debug mode, also resets the hook order validation index.

func (*Owner) TrackHook

func (o *Owner) TrackHook(ht HookType)

TrackHook records a hook call during render for order validation. In debug mode, it validates that hooks are called in the same order on every render. Violations cause a panic with a descriptive error.

func (*Owner) UseHookSlot

func (o *Owner) UseHookSlot() any

UseHookSlot returns the stored value for the current hook slot, or stores and returns the initial value on first render. This provides stable identity for hooks (like URLParam, Resource) across renders.

Usage pattern:

func SomeHook[T any]() *T {
    slot := owner.UseHookSlot(nil)
    if slot != nil {
        return slot.(*T)  // Subsequent render: return stored instance
    }
    instance := &T{...}  // First render: create new instance
    owner.SetHookSlot(instance)
    return instance
}

type PageActionBase added in v0.1.0

type PageActionBase struct {
	// contains filtered or unexported fields
}

PageActionBase is the immutable request/session snapshot used to start a page action.

func NewPageActionBase added in v0.1.0

func NewPageActionBase(
	stdCtx context.Context,
	request *http.Request,
	logger *slog.Logger,
	valueFn func(any) any,
	user any,
	principal auth.Principal,
	hasPrincipal bool,
	authSession auth.Session,
) *PageActionBase

NewPageActionBase constructs an immutable page action snapshot.

func (*PageActionBase) AuthSession added in v0.1.0

func (b *PageActionBase) AuthSession() auth.Session

AuthSession returns the captured auth session.

func (*PageActionBase) Logger added in v0.1.0

func (b *PageActionBase) Logger() *slog.Logger

Logger returns the request/session logger carried by the snapshot.

func (*PageActionBase) Principal added in v0.1.0

func (b *PageActionBase) Principal() (auth.Principal, bool)

Principal returns the captured principal, if any.

func (*PageActionBase) Request added in v0.1.0

func (b *PageActionBase) Request() *http.Request

Request returns the captured request, if any.

func (*PageActionBase) StdContext added in v0.1.0

func (b *PageActionBase) StdContext() context.Context

StdContext returns the stdlib context carried by the snapshot.

func (*PageActionBase) User added in v0.1.0

func (b *PageActionBase) User() any

User returns the captured authenticated user.

func (*PageActionBase) Value added in v0.1.0

func (b *PageActionBase) Value(key any) any

Value returns a request-scoped value from the captured lookup function.

func (*PageActionBase) WithStdContext added in v0.1.0

func (b *PageActionBase) WithStdContext(ctx context.Context) *PageActionBase

WithStdContext returns a copy of the snapshot with a different stdlib context.

type PageActionBinding added in v0.1.0

type PageActionBinding struct {
	Path      string
	InputType reflect.Type
	Params    any
	Handler   PageActionHandler
}

PageActionBinding exposes the current route action to setup helpers during render.

type PageActionExecution added in v0.1.0

type PageActionExecution struct {
	Result *FormResult
	State  *RouteFormState
	Apply  func(ActionMutationTarget)
}

PageActionExecution is the internal execution payload returned by wrapped page actions.

func (*PageActionExecution) ApplyTo added in v0.1.0

func (e *PageActionExecution) ApplyTo(target ActionMutationTarget)

ApplyTo applies buffered mutations onto the provided target.

type PageActionHandler added in v0.1.0

type PageActionHandler func(base *PageActionBase, params any, formData FormData) (*PageActionExecution, error)

PageActionHandler is the wrapped runtime handler used for page actions.

type PagedResponse

type PagedResponse[T any] struct {
	Items      []T `json:"items"`
	Page       int `json:"page"`
	PerPage    int `json:"per_page"`
	Total      int `json:"total"`
	TotalPages int `json:"total_pages"`
}

PagedResponse is a convenience type for paginated list responses.

type PersistBannerState

type PersistBannerState struct {
	// contains filtered or unexported fields
}

PersistBannerState tracks the banner state per session.

type PersistBudgetError

type PersistBudgetError struct {
	Kind                BudgetKind
	PrimitiveID         string
	DebugName           string
	RequestedBytes      int64
	LimitBytes          int64
	CurrentSessionBytes int64
	IncidentCode        string
}

PersistBudgetError is returned when a persisted write exceeds budget limits.

func (*PersistBudgetError) Error

func (e *PersistBudgetError) Error() string

func (*PersistBudgetError) Is

func (e *PersistBudgetError) Is(target error) bool

Is implements errors.Is support.

type PersistedSignalStore

type PersistedSignalStore struct {
	// contains filtered or unexported fields
}

PersistedSignalStore manages persisted signals for a session.

func NewPersistedSignalStore

func NewPersistedSignalStore() *PersistedSignalStore

NewPersistedSignalStore creates a new persisted signal store.

func (*PersistedSignalStore) ClearDirty

func (ps *PersistedSignalStore) ClearDirty()

ClearDirty marks all signals as clean.

func (*PersistedSignalStore) DirtySignals

func (ps *PersistedSignalStore) DirtySignals() []string

DirtySignals returns the set of signals that need saving.

func (*PersistedSignalStore) GetOrCreateSignal

func (ps *PersistedSignalStore) GetOrCreateSignal(
	stableID string,
	fingerprint codec.Fingerprint,
	initializer func() any,
	decode func([]byte) (any, error),
	createSignal func(any) any,
) (any, error)

GetOrCreate retrieves or creates a persisted signal.

func (*PersistedSignalStore) HasDirty

func (ps *PersistedSignalStore) HasDirty() bool

HasDirty reports whether any persisted signals are marked dirty.

func (*PersistedSignalStore) Restore

func (ps *PersistedSignalStore) Restore(data map[string][]byte)

Restore stores encoded persisted signals without decoding.

func (*PersistedSignalStore) Serialize

func (ps *PersistedSignalStore) Serialize() (map[string][]byte, error)

Serialize returns all persisted signals as encoded bytes.

func (*PersistedSignalStore) Set

func (ps *PersistedSignalStore) Set(stableID string, value any) error

Set updates a persisted signal value.

type PrefetchModeChecker

type PrefetchModeChecker interface {
	// Mode returns the current render mode.
	// 0 = normal, 1 = prefetch
	Mode() int
}

PrefetchModeChecker is implemented by contexts that support prefetch mode. Used by primitives to check if side effects should be suppressed.

type PrimitiveRegistration

type PrimitiveRegistration struct {
	AnchorKey string
	StableID  string
	DebugName string
	Kind      string
	Class     string
	Persisted bool
	Primitive any
}

PrimitiveRegistration captures identity metadata for session inspection.

type Props

type Props = vdom.Props

Props is an alias for vdom.Props. Props holds attributes and event handlers.

type PropsCell

type PropsCell[P any] interface {
	// Get returns the current props value and creates a reactive dependency.
	Get() P

	// Peek returns the current props value without creating a dependency.
	Peek() P
}

PropsCell is a read-only reactive cell containing component props. Get() returns the current value with dependency tracking (added in Phase 2). Peek() returns the value without tracking.

type RenderFn

type RenderFn = func() *vdom.VNode

RenderFn is the render closure returned by Setup callbacks.

type ResizeEvent

type ResizeEvent struct {
	// New width in pixels
	Width int

	// New height in pixels
	Height int
}

ResizeEvent represents a resize event. Per spec section 3.9.3, line 1291.

type Resource

type Resource[T any] struct {
	// contains filtered or unexported fields
}

Resource manages asynchronous data fetching and state.

func SetupResource

func SetupResource[P any, T any](
	s *SetupCtx[P],
	load func(ctx context.Context) (T, error),
	opts ...ResourceOption,
) *Resource[T]

SetupResource creates a runtime-only resource during Setup.

func SetupResourceKeyed

func SetupResourceKeyed[P any, K comparable, T any](
	s *SetupCtx[P],
	key func() K,
	load func(ctx context.Context, k K) (T, error),
	opts ...ResourceOption,
) *Resource[T]

SetupResourceKeyed creates a keyed resource during Setup.

func (*Resource[T]) Data

func (r *Resource[T]) Data() T

func (*Resource[T]) DataOr

func (r *Resource[T]) DataOr(fallback T) T

func (*Resource[T]) Error

func (r *Resource[T]) Error() error

func (*Resource[T]) Fetch

func (r *Resource[T]) Fetch()

Fetch triggers a non-force data fetch. It respects StaleTime for fresh ready data and reuses/coalesces equivalent in-flight work instead of restarting it. To cancel and restart the current work, use Refetch().

func (*Resource[T]) Invalidate

func (r *Resource[T]) Invalidate()

Invalidate marks the current resource selection as stale. For keyed resources, only the currently selected key is invalidated. Invalidate does not cancel in-flight work or trigger a fetch.

func (*Resource[T]) IsError

func (r *Resource[T]) IsError() bool

func (*Resource[T]) IsLoading

func (r *Resource[T]) IsLoading() bool

func (*Resource[T]) IsReady

func (r *Resource[T]) IsReady() bool

func (*Resource[T]) Match

func (r *Resource[T]) Match(handlers ...Handler) *vdom.VNode

Match renders different content based on the resource state.

func (*Resource[T]) Metadata

func (r *Resource[T]) Metadata() vruntime.PrimitiveMetadata

Metadata returns identity metadata for the primitive.

func (*Resource[T]) Mutate

func (r *Resource[T]) Mutate(fn func(T) T)

Mutate optimistically updates the local data.

func (*Resource[T]) OnError

func (r *Resource[T]) OnError(fn func(error)) *Resource[T]

OnError registers a callback to be called when data loading fails.

func (*Resource[T]) OnSuccess

func (r *Resource[T]) OnSuccess(fn func(T)) *Resource[T]

OnSuccess registers a callback to be called when data is successfully loaded.

func (*Resource[T]) Refetch

func (r *Resource[T]) Refetch()

Refetch forces a data fetch, bypassing cache and canceling/restarting the current work for the same selection when needed. All signal writes are dispatched via ctx.Dispatch to ensure thread safety.

func (*Resource[T]) ResourceCacheSize

func (r *Resource[T]) ResourceCacheSize(n int) *Resource[T]

ResourceCacheSize configures the maximum number of cached key entries for keyed resources. This is used only by ResourceKeyed; non-keyed resources ignore it.

func (*Resource[T]) RetryOnError

func (r *Resource[T]) RetryOnError(count int, delay time.Duration) *Resource[T]

RetryOnError sets the number of retries and delay between them.

func (*Resource[T]) StaleTime

func (r *Resource[T]) StaleTime(d time.Duration) *Resource[T]

StaleTime sets the duration before data is considered stale.

func (*Resource[T]) State

func (r *Resource[T]) State() State

type ResourceOption

type ResourceOption interface {
	// contains filtered or unexported methods
}

ResourceOption configures a Resource created by SetupCtx.

func OnResourceError

func OnResourceError(fn func(error)) ResourceOption

OnResourceError registers an error callback for resource loads.

func OnResourceSuccess

func OnResourceSuccess(fn func(any)) ResourceOption

OnResourceSuccess registers a success callback for resource loads.

func ResourceCacheSize

func ResourceCacheSize(n int) ResourceOption

ResourceCacheSize configures the maximum number of cached key entries for ResourceKeyed. This enables fast reuse when switching between a bounded set of keys.

Note: only keyed resources use this option; non-keyed resources ignore it.

func RetryOnError

func RetryOnError(count int, delay time.Duration) ResourceOption

RetryOnError configures retry count and delay.

func StaleTime

func StaleTime(d time.Duration) ResourceOption

StaleTime sets the duration before data is considered stale.

type Response

type Response[T any] struct {
	// Data is the response payload.
	Data T `json:"data,omitempty"`

	// Meta contains optional metadata (pagination, counts, etc.)
	Meta map[string]any `json:"meta,omitempty"`

	// StatusCode is the HTTP status code for this response.
	// Not included in JSON output.
	StatusCode int `json:"-"`
}

Response wraps an API response with optional metadata. It provides a standard structure for JSON API responses.

Example usage in API handlers:

func GET(ctx vango.Ctx) (*vango.Response[[]Project], error) {
    projects, err := db.Projects.All()
    if err != nil {
        return nil, vango.InternalError(err)
    }
    return vango.OK(projects), nil
}

func POST(ctx vango.Ctx, input CreateProjectInput) (*vango.Response[*Project], error) {
    project, err := db.Projects.Create(input)
    if err != nil {
        return nil, vango.BadRequest(err)
    }
    return vango.Created(project), nil
}

func Accepted

func Accepted[T any](data T) *Response[T]

Accepted creates a 202 Accepted response with the given data.

func Created

func Created[T any](data T) *Response[T]

Created creates a 201 Created response with the given data.

func NoContent

func NoContent[T any]() *Response[T]

NoContent creates a 204 No Content response. Typically used for successful DELETE operations.

func OK

func OK[T any](data T) *Response[T]

OK creates a 200 OK response with the given data.

func Paginated

func Paginated[T any](items []T, page, perPage, total int) *Response[PagedResponse[T]]

Paginated creates a paginated response.

func (*Response[T]) JSON

func (r *Response[T]) JSON() ([]byte, error)

JSON returns the JSON-encoded response.

func (*Response[T]) WithMeta

func (r *Response[T]) WithMeta(key string, value any) *Response[T]

WithMeta adds metadata to the response.

func (*Response[T]) WithPagination

func (r *Response[T]) WithPagination(page, perPage, total int) *Response[T]

WithPagination adds pagination metadata to the response.

func (*Response[T]) Write

func (r *Response[T]) Write(w http.ResponseWriter) error

Write writes the response to an http.ResponseWriter.

type RouteFormState added in v0.1.0

type RouteFormState struct {
	FormData    FormData
	Errors      FormErrors
	ParseErrors map[string]string
	Failure     error
}

RouteFormState carries submitted form state across HTTP rerenders and live updates.

func (*RouteFormState) Clone added in v0.1.0

func (s *RouteFormState) Clone() *RouteFormState

Clone returns a deep copy of the route form state.

type RuntimeMetricInstrument added in v0.2.0

type RuntimeMetricInstrument string

RuntimeMetricInstrument describes the metric instrument type.

const (
	RuntimeMetricCounter   RuntimeMetricInstrument = "counter"
	RuntimeMetricGauge     RuntimeMetricInstrument = "gauge"
	RuntimeMetricHistogram RuntimeMetricInstrument = "histogram"
)

type RuntimeMetricLabel added in v0.2.0

type RuntimeMetricLabel struct {
	Name        string `json:"name"`
	Description string `json:"description"`
}

RuntimeMetricLabel describes one low-cardinality metric label.

type RuntimeMetricSpec added in v0.2.0

type RuntimeMetricSpec struct {
	Name           string                  `json:"name"`
	Instrument     RuntimeMetricInstrument `json:"instrument"`
	Unit           string                  `json:"unit,omitempty"`
	Description    string                  `json:"description"`
	Labels         []RuntimeMetricLabel    `json:"labels,omitempty"`
	SinkMethod     string                  `json:"sink_method"`
	PrometheusName string                  `json:"prometheus_name,omitempty"`
	Stability      string                  `json:"stability"`
}

RuntimeMetricSpec describes one production runtime metric emitted through MetricsSink and, where applicable, the Prometheus middleware.

func RuntimeMetricCatalog added in v0.2.0

func RuntimeMetricCatalog() []RuntimeMetricSpec

RuntimeMetricCatalog returns the stable runtime metric schema for Vango production telemetry sinks.

func RuntimeMetricSpecFor added in v0.2.0

func RuntimeMetricSpecFor(name string) (RuntimeMetricSpec, bool)

RuntimeMetricSpecFor returns a defensive copy of the catalog entry for name.

type ScrollEvent

type ScrollEvent struct {
	// Scroll position from top
	ScrollTop int

	// Scroll position from left
	ScrollLeft int
}

ScrollEvent represents a scroll event. Per spec section 3.9.3, lines 1269-1271.

type Session

type Session interface {
	Get(key string) any
	Set(key string, value any)
	Delete(key string)
}

Session exposes the minimal session operations needed by SessionKey.

type SessionKey

type SessionKey[T any] struct {
	// contains filtered or unexported fields
}

SessionKey is a typed, schema-safe session key. SessionKeys declared at package scope participate in the schema hash.

func NewSessionKey

func NewSessionKey[T any](name string, opts ...SessionKeyOption[T]) *SessionKey[T]

NewSessionKey creates a typed session key. The name must be a string literal for static discoverability by tooling.

func (*SessionKey[T]) CodecFingerprint

func (sk *SessionKey[T]) CodecFingerprint() codec.Fingerprint

CodecFingerprint returns the schema fingerprint for this key.

func (*SessionKey[T]) DefaultValue

func (sk *SessionKey[T]) DefaultValue() T

DefaultValue returns the default value (or zero value if no default).

func (*SessionKey[T]) Delete

func (sk *SessionKey[T]) Delete(ctx Ctx)

Delete removes the value from the session.

func (*SessionKey[T]) Get

func (sk *SessionKey[T]) Get(ctx Ctx) T

Get retrieves the value from the session context. Returns the default value (or zero value) if the key is absent.

func (*SessionKey[T]) HasDefault

func (sk *SessionKey[T]) HasDefault() bool

HasDefault reports whether a default value was provided.

func (*SessionKey[T]) Name

func (sk *SessionKey[T]) Name() string

Name returns the key name.

func (*SessionKey[T]) Peek

func (sk *SessionKey[T]) Peek(ctx Ctx) (T, bool)

Peek retrieves the value without tracking.

func (*SessionKey[T]) Set

func (sk *SessionKey[T]) Set(ctx Ctx, value T) error

Set stores the value in the session context.

func (*SessionKey[T]) StableID

func (sk *SessionKey[T]) StableID() string

StableID returns the stable ID (empty if not bound by generated bindings).

type SessionKeyInfo

type SessionKeyInfo struct {
	Name         string
	StableID     string
	Fingerprint  codec.Fingerprint
	HasDefault   bool
	DefaultValue any
	Decode       func([]byte) (any, error)
}

SessionKeyInfo contains metadata for a registered session key.

func GetSessionKeyByStableID

func GetSessionKeyByStableID(stableID string) (SessionKeyInfo, bool)

GetSessionKeyByStableID returns a registered session key by stable ID.

type SessionKeyOption

type SessionKeyOption[T any] func(*SessionKey[T])

SessionKeyOption configures a SessionKey.

func Default

func Default[T any](v T) SessionKeyOption[T]

Default sets the default value for when the key is absent. Without Default(), absence returns the zero value of T.

type SessionSignalStore

type SessionSignalStore interface {
	// GetOrCreateSignal retrieves an existing signal by stable ID, or creates
	// a new one using the provided factory function if it doesn't exist.
	GetOrCreateSignal(stableID string, createFn func() any) any
}

SessionSignalStore is the interface for session-scoped shared signal storage. The store maps stable IDs to per-session signal instances.

type SetupComponent

type SetupComponent[P any] struct {
	// contains filtered or unexported fields
}

SetupComponent is a component created by vango.Setup. It carries the setup callback and current props for runtime integration.

func (*SetupComponent[P]) ApplyProps

func (sc *SetupComponent[P]) ApplyProps(state *SetupState) bool

ApplyProps updates the setup state with the current props. Returns true if the props changed.

func (*SetupComponent[P]) Invoker

func (sc *SetupComponent[P]) Invoker() SetupComponentInvoker

Invoker returns the type-erased setup invocation function.

func (*SetupComponent[P]) IsSetupComponent

func (sc *SetupComponent[P]) IsSetupComponent() bool

IsSetupComponent identifies this as a Setup-based component.

func (*SetupComponent[P]) Props

func (sc *SetupComponent[P]) Props() any

Props returns the current props as an untyped value.

func (*SetupComponent[P]) Render

func (sc *SetupComponent[P]) Render() *vdom.VNode

Render implements vdom.Component. This one-shot path is used for SSR/diff/navigation where no component instance exists.

type SetupComponentDetector

type SetupComponentDetector interface {
	IsSetupComponent() bool
	Props() any
	ApplyProps(state *SetupState) bool
	Invoker() SetupComponentInvoker
}

SetupComponentDetector is implemented by Setup components for runtime detection.

type SetupComponentInvoker

type SetupComponentInvoker func(owner *Owner, state *SetupState, props any, ctx Ctx) RenderFn

SetupComponentInvoker is the type-erased invocation function for Setup callbacks.

type SetupCtx

type SetupCtx[P any] struct {
	// contains filtered or unexported fields
}

SetupCtx provides access to props and context during setup. Typed reactive primitives are provided via package-level helpers in package setup.

func (SetupCtx[P]) Ctx

func (s SetupCtx[P]) Ctx() Ctx

func (SetupCtx[P]) Effect

func (s SetupCtx[P]) Effect(fn func() Cleanup)

func (SetupCtx[P]) OnChange

func (s SetupCtx[P]) OnChange(key func() any, cb func(next, prev any))

OnChange provides an untyped change handler. Prefer the typed helper.

func (SetupCtx[P]) OnMount

func (s SetupCtx[P]) OnMount(fn func() Cleanup)

func (SetupCtx[P]) OnPersistError

func (s SetupCtx[P]) OnPersistError(fn func(*PersistBudgetError))

OnPersistError registers a session-scoped persistence error handler.

func (SetupCtx[P]) Props

func (s SetupCtx[P]) Props() PropsCell[P]

type SetupState

type SetupState struct {
	// contains filtered or unexported fields
}

SetupState holds runtime state for a Setup-based component instance.

func NewSetupState

func NewSetupState() *SetupState

NewSetupState creates a new SetupState for component instances.

func (*SetupState) AddOnMount

func (s *SetupState) AddOnMount(reg *OnMountRegistration)

func (*SetupState) AddRegistration

func (s *SetupState) AddRegistration(reg PrimitiveRegistration)

AddRegistration stores a primitive registration for session inspection.

func (*SetupState) Dispose

func (s *SetupState) Dispose()

Dispose runs OnMount cleanups and releases references.

func (*SetupState) GetRenderFn

func (s *SetupState) GetRenderFn() RenderFn

func (*SetupState) IsOnMountPending

func (s *SetupState) IsOnMountPending() bool

func (*SetupState) IsSetupComplete

func (s *SetupState) IsSetupComplete() bool

func (*SetupState) MarkSetupComplete

func (s *SetupState) MarkSetupComplete()

func (*SetupState) Registrations

func (s *SetupState) Registrations() []PrimitiveRegistration

Registrations returns a copy of the stored primitive registrations.

func (*SetupState) RunOnMountHooks

func (s *SetupState) RunOnMountHooks()

RunOnMountHooks executes all OnMount hooks registered during setup.

func (*SetupState) SetOnMountPending

func (s *SetupState) SetOnMountPending(pending bool)

func (*SetupState) SetRenderFn

func (s *SetupState) SetRenderFn(fn RenderFn)

func (*SetupState) UpdateProps

func (s *SetupState) UpdateProps(newProps any) bool

UpdateProps updates the props cell and notifies dependents. Returns true if props changed.

type Signal

type Signal[T any] struct {
	// contains filtered or unexported fields
}

Signal is a reactive value container. Reading a Signal's value during a tracked context (component render, memo computation, or effect execution) automatically subscribes the current listener to receive notifications when the value changes.

func NewSignalForTest

func NewSignalForTest[T any](initial T) *Signal[T]

NewSignalForTest creates a signal for tests outside the vango package. Prefer setup.Signal in production code.

func SetupGlobalSignal

func SetupGlobalSignal[P any, T any](s *SetupCtx[P], initial T) *Signal[T]

SetupGlobalSignal creates a global signal during Setup.

func SetupSharedSignal

func SetupSharedSignal[P any, T any](s *SetupCtx[P], initial T) *Signal[T]

SetupSharedSignal creates a session-scoped signal during Setup.

func SetupSignal

func SetupSignal[P any, T any](s *SetupCtx[P], initial T) *Signal[T]

SetupSignal creates a local signal during Setup.

func (*Signal[T]) Add

func (s *Signal[T]) Add(n any)

Add adds n to the value. The parameter n must be the same numeric type as the signal's value. Panics if the signal's type is not numeric or if n is the wrong type.

func (*Signal[T]) Append

func (s *Signal[T]) Append(suffix string)

Append appends a suffix to a string value. Panics if the signal's type is not string.

func (*Signal[T]) AppendItem

func (s *Signal[T]) AppendItem(item any)

AppendItem appends an item to a slice value. The item must be assignable to the slice's element type. Panics if the signal's type is not a slice.

func (*Signal[T]) Clear

func (s *Signal[T]) Clear()

Clear sets the value to its empty state. Works for string (empty string), slice (empty slice), and map (empty map). Panics if the signal's type is not one of these.

func (*Signal[T]) Dec

func (s *Signal[T]) Dec()

Dec decrements the value by 1. Panics if the signal's type is not numeric.

func (*Signal[T]) Div

func (s *Signal[T]) Div(n any)

Div divides the value by n. The parameter n must be the same numeric type as the signal's value. Panics if the signal's type is not numeric or if n is the wrong type. Note: Integer division truncates toward zero.

func (*Signal[T]) Filter

func (s *Signal[T]) Filter(predicate func(any) bool)

Filter keeps only items that satisfy the predicate. Panics if the signal's type is not a slice.

func (*Signal[T]) Get

func (s *Signal[T]) Get() T

Get returns the current value and subscribes the current listener. If called during a tracked context (component render, memo computation, or effect execution), the current listener will be notified when this signal's value changes.

func (*Signal[T]) GetAny

func (s *Signal[T]) GetAny() any

GetAny returns the current value as an interface{}. This is used for serialization without knowing the concrete type.

func (*Signal[T]) GetKey added in v0.2.0

func (s *Signal[T]) GetKey(key any) (any, bool)

GetKey returns the value for a key. This reads the signal and creates a dependency. Panics if the signal's type is not a map.

func (*Signal[T]) HasKey

func (s *Signal[T]) HasKey(key any) bool

HasKey returns true if the key exists in the map. Panics if the signal's type is not a map.

func (*Signal[T]) ID

func (s *Signal[T]) ID() uint64

ID returns the unique identifier for this signal.

func (*Signal[T]) Inc

func (s *Signal[T]) Inc()

Inc increments the value by 1. Panics if the signal's type is not numeric.

func (*Signal[T]) InsertAt

func (s *Signal[T]) InsertAt(index int, item any)

InsertAt inserts an item at the given index. If index is out of bounds, the item is appended (if index >= len) or prepended (if index < 0). Panics if the signal's type is not a slice.

func (*Signal[T]) Keys added in v0.2.0

func (s *Signal[T]) Keys() []any

Keys returns all keys in the map. This reads the signal and creates a dependency. Panics if the signal's type is not a map.

func (*Signal[T]) Len

func (s *Signal[T]) Len() int

Len returns the length of the value. Works for string, slice, and map types. Panics if the signal's type is not one of these. This reads the signal and creates a dependency.

func (*Signal[T]) Metadata

func (s *Signal[T]) Metadata() vruntime.PrimitiveMetadata

Metadata returns identity metadata for the primitive.

func (*Signal[T]) Mul

func (s *Signal[T]) Mul(n any)

Mul multiplies the value by n. The parameter n must be the same numeric type as the signal's value. Panics if the signal's type is not numeric or if n is the wrong type.

func (*Signal[T]) Peek

func (s *Signal[T]) Peek() T

Peek returns the current value without subscribing. This is useful when you need to read a value without creating a dependency.

func (*Signal[T]) Prepend

func (s *Signal[T]) Prepend(prefix string)

Prepend prepends a prefix to a string value. Panics if the signal's type is not string.

func (*Signal[T]) PrependItem

func (s *Signal[T]) PrependItem(item any)

PrependItem prepends an item to a slice value. The item must be assignable to the slice's element type. Panics if the signal's type is not a slice.

func (*Signal[T]) RemoveAt

func (s *Signal[T]) RemoveAt(index int)

RemoveAt removes the item at the given index. Does nothing if index is out of bounds. Panics if the signal's type is not a slice.

func (*Signal[T]) RemoveFirst

func (s *Signal[T]) RemoveFirst()

RemoveFirst removes the first item from the slice. Does nothing if the slice is empty. Panics if the signal's type is not a slice.

func (*Signal[T]) RemoveKey

func (s *Signal[T]) RemoveKey(key any)

RemoveKey removes a key from a map. Does nothing if the key doesn't exist. Panics if the signal's type is not a map.

func (*Signal[T]) RemoveLast

func (s *Signal[T]) RemoveLast()

RemoveLast removes the last item from the slice. Does nothing if the slice is empty. Panics if the signal's type is not a slice.

func (*Signal[T]) RemoveWhere

func (s *Signal[T]) RemoveWhere(predicate func(any) bool)

RemoveWhere removes all items that satisfy the predicate. The predicate receives each item as any and returns true to remove it. Panics if the signal's type is not a slice.

func (*Signal[T]) Set

func (s *Signal[T]) Set(value T)

Set updates the signal's value and notifies subscribers if the value changed. Uses the signal's equality function to determine if the value changed.

func (*Signal[T]) SetAny

func (s *Signal[T]) SetAny(value any) error

SetAny sets the value from an interface{}. Returns an error if the type doesn't match. This is used for deserialization without knowing the concrete type.

func (*Signal[T]) SetAt

func (s *Signal[T]) SetAt(index int, item any)

SetAt sets the item at the given index. Does nothing if index is out of bounds. Panics if the signal's type is not a slice.

func (*Signal[T]) SetFalse

func (s *Signal[T]) SetFalse()

SetFalse sets the value to false. Panics if the signal's type is not bool.

func (*Signal[T]) SetKey

func (s *Signal[T]) SetKey(key, value any)

SetKey sets a key-value pair in a map. The key and value must be assignable to the map's key and value types. Panics if the signal's type is not a map.

func (*Signal[T]) SetTrue

func (s *Signal[T]) SetTrue()

SetTrue sets the value to true. Panics if the signal's type is not bool.

func (*Signal[T]) Sub

func (s *Signal[T]) Sub(n any)

Sub subtracts n from the value. The parameter n must be the same numeric type as the signal's value. Panics if the signal's type is not numeric or if n is the wrong type.

func (*Signal[T]) Toggle

func (s *Signal[T]) Toggle()

Toggle inverts a boolean value. Panics if the signal's type is not bool.

func (*Signal[T]) Unsubscribe

func (s *Signal[T]) Unsubscribe(listener Listener)

Unsubscribe removes a listener from this signal. This is used by the runtime to remove stale subscriptions between renders.

func (*Signal[T]) Update

func (s *Signal[T]) Update(fn func(T) T)

Update atomically reads and updates the signal's value. The function receives the current value and returns the new value.

func (*Signal[T]) UpdateAt

func (s *Signal[T]) UpdateAt(index int, fn func(any) any)

UpdateAt updates the item at the given index using the provided function. Does nothing if index is out of bounds. Panics if the signal's type is not a slice.

func (*Signal[T]) UpdateKey

func (s *Signal[T]) UpdateKey(key any, fn func(any) any)

UpdateKey updates a key's value using the provided function. If the key doesn't exist, the function receives nil/zero value. Panics if the signal's type is not a map.

func (*Signal[T]) UpdateWhere

func (s *Signal[T]) UpdateWhere(predicate func(any) bool, fn func(any) any)

UpdateWhere updates all items that satisfy the predicate using the provided function. Panics if the signal's type is not a slice.

func (*Signal[T]) Values added in v0.2.0

func (s *Signal[T]) Values() []any

Values returns all values in the map. This reads the signal and creates a dependency. Panics if the signal's type is not a map.

func (*Signal[T]) WithEquals

func (s *Signal[T]) WithEquals(fn func(T, T) bool) *Signal[T]

WithEquals returns the signal configured with a custom equality function. This is useful for custom types where reflect.DeepEqual is too expensive or has incorrect semantics.

type SimpleSessionSignalStore

type SimpleSessionSignalStore struct {
	// contains filtered or unexported fields
}

SimpleSessionSignalStore is a basic implementation of SessionSignalStore using sync.Map for concurrent access.

func NewSimpleSessionSignalStore

func NewSimpleSessionSignalStore() *SimpleSessionSignalStore

NewSimpleSessionSignalStore creates a new simple session signal store.

func (*SimpleSessionSignalStore) GetOrCreateSignal

func (s *SimpleSessionSignalStore) GetOrCreateSignal(stableID string, createFn func() any) any

GetOrCreateSignal retrieves an existing signal or creates a new one.

type SliceSignal deprecated

type SliceSignal[T any] struct {
	*Signal[[]T]
}

SliceSignal wraps Signal[[]T] with convenience methods for slice operations.

Deprecated: Use setup.Signal inside vango.Setup. Signal[[]T] now has AppendItem(), PrependItem(), InsertAt(), RemoveAt(), SetAt(), UpdateAt(), RemoveWhere(), UpdateWhere(), Filter(), Clear(), and Len() methods directly available.

Note: SliceSignal[T] provides type-safe methods (e.g., Append(item T)) while the Signal[T] methods use any (e.g., AppendItem(item any)). Use SliceSignal[T] if you prefer compile-time type safety over the unified API.

// Old:
items := vango.NewSliceSignal([]Item{})
items.Append(newItem)

// New:
items := setup.Signal(&s, []Item{})
items.AppendItem(newItem)  // Note: uses 'any' parameter

func NewSliceSignal deprecated

func NewSliceSignal[T any](initial []T) *SliceSignal[T]

NewSliceSignal creates a new SliceSignal with the given initial value. If initial is nil, creates an empty slice.

Deprecated: Use setup.Signal inside vango.Setup. Signal[[]T] now has slice convenience methods directly available. SliceSignal[T] is retained for type-safe slice operations if preferred.

func (*SliceSignal[T]) Append

func (s *SliceSignal[T]) Append(item T)

Append adds an item to the end of the slice.

func (*SliceSignal[T]) AppendAll

func (s *SliceSignal[T]) AppendAll(items ...T)

AppendAll adds multiple items to the end of the slice.

func (*SliceSignal[T]) Clear

func (s *SliceSignal[T]) Clear()

Clear removes all items from the slice.

func (*SliceSignal[T]) Filter

func (s *SliceSignal[T]) Filter(predicate func(T) bool)

Filter keeps only items that satisfy the predicate.

func (*SliceSignal[T]) InsertAt

func (s *SliceSignal[T]) InsertAt(index int, item T)

InsertAt inserts an item at the given index. If index is out of bounds, the item is appended (if index >= len) or prepended (if index < 0).

func (*SliceSignal[T]) Len

func (s *SliceSignal[T]) Len() int

Len returns the length of the slice. This reads the signal and creates a dependency.

func (*SliceSignal[T]) Prepend

func (s *SliceSignal[T]) Prepend(item T)

Prepend adds an item to the beginning of the slice.

func (*SliceSignal[T]) RemoveAt

func (s *SliceSignal[T]) RemoveAt(index int)

RemoveAt removes the item at the given index. Does nothing if index is out of bounds.

func (*SliceSignal[T]) RemoveFirst

func (s *SliceSignal[T]) RemoveFirst()

RemoveFirst removes and returns the first item from the slice. Does nothing if the slice is empty.

func (*SliceSignal[T]) RemoveLast

func (s *SliceSignal[T]) RemoveLast()

RemoveLast removes the last item from the slice. Does nothing if the slice is empty.

func (*SliceSignal[T]) RemoveWhere

func (s *SliceSignal[T]) RemoveWhere(predicate func(T) bool)

RemoveWhere removes all items that satisfy the predicate.

func (*SliceSignal[T]) SetAt

func (s *SliceSignal[T]) SetAt(index int, item T)

SetAt sets the item at the given index. Does nothing if index is out of bounds.

func (*SliceSignal[T]) UpdateAt

func (s *SliceSignal[T]) UpdateAt(index int, fn func(T) T)

UpdateAt updates the item at the given index using the provided function. Does nothing if index is out of bounds.

func (*SliceSignal[T]) UpdateWhere

func (s *SliceSignal[T]) UpdateWhere(predicate func(T) bool, fn func(T) T)

UpdateWhere updates all items that satisfy the predicate using the provided function.

type Slot

type Slot struct {
	// contains filtered or unexported fields
}

Slot is an opaque, framework-owned renderable container for children. It is intended for use in props structs and layout handlers.

func Children

func Children(children ...any) Slot

Children constructs a Slot from heterogeneous child inputs.

func (Slot) ChildrenNodes

func (s Slot) ChildrenNodes() []*vdom.VNode

ChildrenNodes exposes Slot nodes to the VDOM integration layer. This is intended for framework use only.

type State

type State int

State represents the current state of a resource.

const (
	Pending State = iota // Initial state, before first fetch
	Loading              // Fetch in progress
	Ready                // Data successfully loaded
	Error                // Fetch failed
)

type StateBudgetConfig

type StateBudgetConfig struct {
	PerPrimitiveBytes int64
	PerSessionBytes   int64
}

StateBudgetConfig configures limits on persisted state size. Zero values fall back to defaults.

func ResolveStateBudget

func ResolveStateBudget(cfg *StateBudgetConfig) StateBudgetConfig

ResolveStateBudget returns a StateBudgetConfig with defaults applied.

type StormBudgetChecker

type StormBudgetChecker interface {
	CheckResource() error
	CheckAction() error
	CheckGoLatest() error
	CheckEffectRun() error
	ResetTick()
}

StormBudgetChecker is the interface exposed to primitives for budget checking. This is implemented by Session and exposed via Ctx.

type StormBudgetConfig

type StormBudgetConfig struct {
	MaxResourceStartsPerSecond int
	MaxActionStartsPerSecond   int
	MaxGoLatestStartsPerSecond int
	MaxEffectRunsPerTick       int
	WindowDuration             time.Duration
	OnExceeded                 BudgetExceededMode
}

StormBudgetConfig holds configuration for storm budgets. This mirrors the server/config.StormBudgetConfig for use in the vango package.

type StormBudgetTracker

type StormBudgetTracker struct {
	// contains filtered or unexported fields
}

StormBudgetTracker tracks rate limits for effect primitives. It provides protection against amplification bugs where effects cascade into more effects, potentially causing performance issues or infinite loops.

func NewStormBudgetTracker

func NewStormBudgetTracker(cfg *StormBudgetConfig) *StormBudgetTracker

NewStormBudgetTracker creates a new storm budget tracker with the given configuration.

func (*StormBudgetTracker) CheckAction

func (t *StormBudgetTracker) CheckAction() error

CheckAction checks if an Action can start. Returns nil if allowed, ErrBudgetExceeded if rate limited.

func (*StormBudgetTracker) CheckEffectRun

func (t *StormBudgetTracker) CheckEffectRun() error

CheckEffectRun checks if another effect can run this tick. Returns nil if allowed, ErrBudgetExceeded if limit reached.

func (*StormBudgetTracker) CheckGoLatest

func (t *StormBudgetTracker) CheckGoLatest() error

CheckGoLatest checks if GoLatest work can start. Returns nil if allowed, ErrBudgetExceeded if rate limited.

func (*StormBudgetTracker) CheckResource

func (t *StormBudgetTracker) CheckResource() error

CheckResource checks if a Resource fetch can start. Returns nil if allowed, ErrBudgetExceeded if rate limited.

func (*StormBudgetTracker) GetOnExceeded

func (t *StormBudgetTracker) GetOnExceeded() BudgetExceededMode

GetOnExceeded returns the configured behavior when budget is exceeded.

func (*StormBudgetTracker) ResetTick

func (t *StormBudgetTracker) ResetTick()

ResetTick resets the per-tick counters. Should be called at the start of each event/dispatch processing.

func (*StormBudgetTracker) Stats

func (t *StormBudgetTracker) Stats() BudgetStats

type Stream

type Stream[T any] interface {
	Subscribe(handler func(T)) (unsubscribe func())
}

Stream is an interface for event streams that support subscription. The Subscribe method returns an unsubscribe function.

type StrictEffectMode

type StrictEffectMode int

StrictEffectMode controls how effect-time signal writes are handled. This helps catch bugs where effects modify signals during their synchronous body, which can cause unexpected re-renders and cascading effects.

See SPEC_ADDENDUM.md §A.3 for effect enforcement details.

const (
	// StrictEffectOff disables effect-time write detection.
	// No warnings or errors for signal writes during effects.
	StrictEffectOff StrictEffectMode = iota

	// StrictEffectWarn logs a warning when an effect writes to a signal
	// without the AllowWrites() option. This is the recommended mode for
	// development to catch bugs without breaking existing code.
	StrictEffectWarn

	// StrictEffectPanic panics when an effect writes to a signal without
	// the AllowWrites() option. Use this mode to strictly enforce the rule
	// during testing or in strict development environments.
	StrictEffectPanic
)

type StringSignal deprecated

type StringSignal struct {
	*Signal[string]
}

StringSignal wraps Signal[string] with convenience methods for string operations.

Deprecated: Use setup.Signal inside vango.Setup. Signal[string] now has Append(), Prepend(), Clear(), and Len() methods directly available.

// Old:
text := vango.NewStringSignal("")
text.Append("hello")

// New:
text := setup.Signal(&s, "")
text.Append("hello")

func NewStringSignal deprecated

func NewStringSignal(initial string) *StringSignal

NewStringSignal creates a new StringSignal with the given initial value.

Deprecated: Use setup.Signal inside vango.Setup. Signal[string] now has Append(), Prepend(), Clear(), and Len() methods directly available.

func (*StringSignal) Append

func (s *StringSignal) Append(suffix string)

Append adds the given string to the end.

func (*StringSignal) Clear

func (s *StringSignal) Clear()

Clear sets the value to an empty string.

func (*StringSignal) IsEmpty

func (s *StringSignal) IsEmpty() bool

IsEmpty returns true if the string is empty. This reads the signal and creates a dependency.

func (*StringSignal) Len

func (s *StringSignal) Len() int

Len returns the length of the string. This reads the signal and creates a dependency.

func (*StringSignal) Prepend

func (s *StringSignal) Prepend(prefix string)

Prepend adds the given string to the beginning.

type SubscribeOption

type SubscribeOption interface {
	// contains filtered or unexported methods
}

SubscribeOption is an option for configuring Subscribe.

func SubscribeTxName

func SubscribeTxName(name string) SubscribeOption

SubscribeTxName sets the transaction name for observability. Messages will appear in DevTools as Subscribe:<name>.

type TimeoutOption

type TimeoutOption interface {
	// contains filtered or unexported methods
}

TimeoutOption is an option for configuring Timeout.

func TimeoutTxName

func TimeoutTxName(name string) TimeoutOption

TimeoutTxName sets the transaction name for observability. The timeout will appear in DevTools as Timeout:<name>.

type Touch

type Touch struct {
	// Unique identifier for the touch point
	Identifier int

	// Position relative to viewport
	ClientX int
	ClientY int

	// Position relative to document
	PageX int
	PageY int
}

Touch represents a single touch point. Per spec section 3.9.3, lines 1219-1225.

type TouchEvent

type TouchEvent struct {
	// All current touches on the screen
	Touches []Touch

	// Touches that started on this element
	TargetTouches []Touch

	// Touches that changed in this event
	ChangedTouches []Touch
}

TouchEvent represents a touch event. Per spec section 3.9.3, lines 1212-1217.

type TrackingContext

type TrackingContext struct {
	// contains filtered or unexported fields
}

TrackingContext holds the reactive state for a goroutine. Each goroutine has its own tracking context to support concurrent component rendering and signal access.

type TransitionEvent

type TransitionEvent struct {
	// Name of the CSS property being transitioned
	PropertyName string

	// Time in seconds since the transition started
	ElapsedTime float64

	// Pseudo-element the transition runs on
	PseudoElement string
}

TransitionEvent represents a CSS transition event. Per spec section 3.9.3, lines 1236-1239.

type TxTraceEvent

type TxTraceEvent struct {
	Category       string
	Name           string
	Depth          int
	CommitBoundary bool
	Outcome        string
	DurationMs     int64
}

TxTraceEvent is emitted to an optional trace hook stored in StdContext().

This is intentionally low-cardinality by default: - Category is recommended for trace attributes. - Name may be omitted depending on configuration.

type TxTraceHook

type TxTraceHook interface {
	OnTxStart(ctx context.Context, ev TxTraceEvent)
	OnTxEnd(ctx context.Context, ev TxTraceEvent)
}

TxTraceHook receives TxNamed start/end events for trace integration. Implementations must be safe for concurrent use.

type TypeMismatchError

type TypeMismatchError struct {
	Expected string
	Actual   string
}

TypeMismatchError is returned when SetAny receives a value of the wrong type.

func (*TypeMismatchError) Error

func (e *TypeMismatchError) Error() string

type TypedPropsCell

type TypedPropsCell[P any] struct {
	// contains filtered or unexported fields
}

TypedPropsCell wraps propsCellImpl for type-safe access.

func (*TypedPropsCell[P]) Get

func (t *TypedPropsCell[P]) Get() P

func (*TypedPropsCell[P]) Peek

func (t *TypedPropsCell[P]) Peek() P

type VKind

type VKind = vdom.VKind

VKind is an alias for vdom.VKind. VKind is the node type discriminator.

type VNode

type VNode = vdom.VNode

VNode is an alias for vdom.VNode for convenience. VNode represents a virtual DOM node.

type WasmMessage

type WasmMessage struct {
	// ID is the wasm component name/module identifier (the value of data-wasm).
	ID string

	// HID is the unique instance address (the hydration id of the wasm boundary element).
	// This allows multiple instances with the same ID to coexist on a page.
	HID string

	Raw json.RawMessage
}

WasmMessage represents a message sent between a WASM component and the server.

type WasmMessageHandler

type WasmMessageHandler func(WasmMessage)

WasmMessageHandler handles messages emitted by client WASM components.

type WasmMessageHandlerSpec added in v0.2.0

type WasmMessageHandlerSpec struct {
	Validator WasmMessageValidator
	Handler   func(WasmMessage)
}

WasmMessageHandlerSpec preserves per-instance WASM validation metadata.

type WasmMessageValidator

type WasmMessageValidator func(WasmMessage) error

WasmMessageValidator validates a WASM message payload. Return an error to reject the message.

func WasmSchemaValidator

func WasmSchemaValidator[T any](validate func(WasmMessage, T) error) WasmMessageValidator

WasmSchemaValidator builds a WasmMessageValidator that decodes WASM message payloads into a typed schema using strict JSON rules.

The callback may be nil to run schema decoding only.

func WasmValidatorMap added in v0.2.0

func WasmValidatorMap(validators map[string]WasmMessageValidator) WasmMessageValidator

WasmValidatorMap dispatches WASM payload validation by exact component ID. Unknown IDs are rejected.

type WasmMessenger

type WasmMessenger interface {
	RegisterWasmHandler(id string, handler WasmMessageHandler) func()
	SendWasmMessage(id string, payload any) error
	SendWasmMessageToHID(hid string, payload any) error
}

WasmMessenger describes session capabilities for WASM messaging.

type WasmValidatedMessenger added in v0.2.0

type WasmValidatedMessenger interface {
	WasmMessenger
	RegisterValidatedWasmHandler(id string, validate WasmMessageValidator, handler WasmMessageHandler) func()
}

WasmValidatedMessenger extends WASM messaging with exact-sink validator registration so the runtime can enforce strict non-dev coverage.

type WheelEvent

type WheelEvent struct {
	// Scroll amounts
	DeltaX float64
	DeltaY float64
	DeltaZ float64

	// Delta mode: 0=pixels, 1=lines, 2=pages
	DeltaMode int

	// Position relative to viewport
	ClientX int
	ClientY int

	// Modifier keys
	CtrlKey  bool
	ShiftKey bool
	AltKey   bool
	MetaKey  bool
}

WheelEvent represents a mouse wheel event. Per spec section 3.9.3, line 1056.

type WorkerContext

type WorkerContext struct {
	Kind WorkerKind

	WorkerStableID  string
	WorkerDebugName string
	WorkerAnchorKey string

	// RuntimeCtx is the originating runtime context for the session, if available.
	// This is used to locate the session for self-heal behavior on violations.
	RuntimeCtx Ctx
}

WorkerContext carries metadata about the current framework worker. This is goroutine-local and is used to produce actionable diagnostics and to fail safe (session self-heal) on correctness violations in production.

type WorkerKind

type WorkerKind string

WorkerKind identifies which framework worker context is currently executing. These run off the session loop and must never write reactive state directly.

const (
	WorkerResourceLoader WorkerKind = "resource_loader"
	WorkerActionWork     WorkerKind = "action_work"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL