Sign in

    mizchi/luna/luna/signal does not have a README file

    Snapshot

    pub trait Snapshot {
    snapshot(Self) -> Self
    }

    Trait for signal records that can produce a snapshot

    AsyncState

    pub enum AsyncState[T] {
    Pending
    Success(T)
    Failure(String)
    }

    Async state representation - environment independent

    AsyncState::error

    fn[T] AsyncState::error(self : AsyncState[T]) -> String?

    Get error if failure, None otherwise

    AsyncState::is_failure

    fn[T] AsyncState::is_failure(self : AsyncState[T]) -> Bool

    Check if state is failure

    AsyncState::is_pending

    fn[T] AsyncState::is_pending(self : AsyncState[T]) -> Bool

    Check if state is pending

    AsyncState::is_success

    fn[T] AsyncState::is_success(self : AsyncState[T]) -> Bool

    Check if state is success

    AsyncState::value

    fn[T] AsyncState::value(self : AsyncState[T]) -> T?

    Get value if success, None otherwise

    Context

    pub struct Context[T] {
    id : Int
    default_value : () -> T
    providers : Array[(Int, () -> T)]
    }

    Context type with typed getter The current_getter is managed per-context and tracks the current value chain

    EffectRunner

    pub struct EffectRunner {
    id : Int
    run : () -> Unit
    }

    Effect wrapper with unique ID for deduplication

    Lens

    pub struct Lens[S, A] {
    get : (S) -> A
    set : (S, A) -> S
    }

    A lens focuses on a specific part of a larger structure

    Lens::new

    fn[S, A] Lens::new(get : (S) -> A, set : (S, A) -> S) -> Lens[S, A]

    LensStore

    pub struct LensStore[T] {
    source : Signal[T]
    }

    A store with lens-based field access Each focused lens creates a derived signal that only updates when that field changes

    LensStore::focus

    fn[T, A : Eq] LensStore::focus(self : LensStore[T], lens : Lens[T, A]) -> (Signal[A], (A) -> Unit)

    Focus on a field using a lens, returns getter and setter functions The getter is memoized and only recomputes when the focused value changes

    LensStore::new

    fn[T] LensStore::new(initial : T) -> LensStore[T]

    LensStore::snapshot

    fn[T] LensStore::snapshot(self : LensStore[T]) -> T

    Get the current snapshot of the entire store

    LensStore::update

    fn[T] LensStore::update(self : LensStore[T], f : (T) -> T) -> Unit

    Update the entire store

    Owner

    pub struct Owner {
    id : Int
    parent : Owner?
    children : Array[Owner]
    cleanups : Array[() -> Unit]
    disposers : Array[() -> Unit]
    disposed : Bool
    }

    Owner - manages lifecycle of reactive computations (Solid.js style)

    Owner::dispose

    fn Owner::dispose(self : Owner) -> Unit

    Dispose this owner and all its children

    Owner::new

    fn Owner::new(parent : Owner?) -> Owner

    Create a new Owner

    Resource

    pub struct Resource[T] {
    state : Signal[AsyncState[T]]
    // private fields
    }

    Resource - Async value container with Signal integration Environment-agnostic: uses callbacks instead of Promise/async directly

    Resource::error

    fn[T] Resource::error(self : Resource[T]) -> String?

    Get error if failure

    Resource::get

    fn[T] Resource::get(self : Resource[T]) -> AsyncState[T]

    Get current async state (reactive)

    Resource::is_failure

    fn[T] Resource::is_failure(self : Resource[T]) -> Bool

    Check if failed

    Resource::is_pending

    fn[T] Resource::is_pending(self : Resource[T]) -> Bool

    Check if currently pending

    Resource::is_success

    fn[T] Resource::is_success(self : Resource[T]) -> Bool

    Check if successfully loaded

    Resource::peek

    fn[T] Resource::peek(self : Resource[T]) -> AsyncState[T]

    Peek current state without tracking

    Resource::refetch

    fn[T] Resource::refetch(self : Resource[T]) -> Unit

    Trigger refetch

    Resource::value

    fn[T] Resource::value(self : Resource[T]) -> T?

    Get value if success

    Signal

    pub struct Signal[T] {
    value : T
    subscribers : Array[EffectRunner]
    }

    Signal type - holds a value and notifies subscribers on change

    Signal::clear_subscribers

    fn[T] Signal::clear_subscribers(self : Signal[T]) -> Unit

    Clear all subscribers (for cleanup)

    Signal::filter

    fn[T] Signal::filter(self : Signal[T], predicate : (T) -> Bool) -> Signal[T?]

    Returns a signal that only updates when predicate passes

    Signal::filter_map

    fn[T, U] Signal::filter_map(self : Signal[T], f : (T) -> U?) -> Signal[U?]

    Filter and map signal updates

    Signal::get

    fn[T] Signal::get(self : Signal[T]) -> T

    Get the current value and track dependency if inside an effect

    Signal::map

    fn[T, U] Signal::map(self : Signal[T], f : (T) -> U) -> (() -> U)

    Returns a getter function (like memo)

    Signal::new

    fn[T] Signal::new(initial : T) -> Signal[T]

    Create a new signal with initial value

    Signal::peek

    fn[T] Signal::peek(self : Signal[T]) -> T

    Get value without tracking (won't create dependency)

    Signal::remove_subscriber

    fn[T] Signal::remove_subscriber(self : Signal[T], id : Int) -> Unit

    Remove a specific subscriber by ID

    Signal::set

    fn[T] Signal::set(self : Signal[T], new_value : T) -> Unit

    Set a new value and notify all subscribers

    Signal::subscriber_count

    fn[T] Signal::subscriber_count(self : Signal[T]) -> Int

    Get number of subscribers (for debugging)

    Signal::to_getter

    fn[T] Signal::to_getter(self : Signal[T]) -> (() -> T)

    Create a read-only getter for a signal

    Signal::update

    fn[T] Signal::update(self : Signal[T], f : (T) -> T) -> Unit

    Update the value using a function

    SplitStore2

    pub struct SplitStore2[A, B] {
    field1 : Signal[A]
    field2 : Signal[B]
    }

    A record where each field is an independent Signal This is the most performant approach - updates only affect specific fields

    SplitStore2::new

    fn[A, B] SplitStore2::new(v1 : A, v2 : B) -> SplitStore2[A, B]

    SplitStore3

    pub struct SplitStore3[A, B, C] {
    field1 : Signal[A]
    field2 : Signal[B]
    field3 : Signal[C]
    }

    3-field version

    SplitStore3::new

    fn[A, B, C] SplitStore3::new(v1 : A, v2 : B, v3 : C) -> SplitStore3[A, B, C]

    all

    fn all(signals : Array[Signal[Bool]]) -> (() -> Bool)

    Create a signal that is true when all input signals are true

    any

    fn any(signals : Array[Signal[Bool]]) -> (() -> Bool)

    Create a signal that is true when any input signal is true

    batch

    fn[T] batch(f : () -> T) -> T

    Run a function in a batch - all signal updates are batched

    batch_end

    fn batch_end() -> Unit

    End a batch update - run all pending effects

    batch_start

    fn batch_start() -> Unit

    Start a batch update - effects won't run until batch ends

    combine2

    fn[A, B, R] combine2(a : Signal[A], b : Signal[B], f : (A, B) -> R) -> (() -> R)

    Combine two signals into one

    combine3

    fn[A, B, C, R] combine3(a : Signal[A], b : Signal[B], c : Signal[C], f : (A, B, C) -> R) -> (() -> R)

    Combine three signals into one

    combine4

    fn[A, B, C, D, R] combine4(a : Signal[A], b : Signal[B], c : Signal[C], d : Signal[D], f : (A, B, C, D) -> R) -> (() -> R)

    Combine four signals into one

    computed

    fn[T] computed(compute : () -> T) -> (() -> T)

    Create a computed signal (alias for memo with Signal-like API)

    create_context

    fn[T] create_context(default_value : T) -> Context[T]

    Create a new context with a default value Similar to Solid.js createContext

    create_root

    fn[T] create_root(f : (() -> Unit) -> T) -> T

    Create a new reactive root scope The function receives a dispose callback Returns the result of the function

    create_root_with_dispose

    fn[T] create_root_with_dispose(f : () -> T) -> (T, () -> Unit)

    Create a reactive root and return both result and dispose function

    deferred

    fn[T] deferred() -> (Resource[T], (T) -> Unit, (String) -> Unit)

    Create a deferred Resource (starts pending, resolve/reject manually)

    effect

    fn effect(fn_ : () -> Unit) -> (() -> Unit)

    Supports onCleanup() calls inside the effect If inside an owner scope, the effect is automatically registered for disposal

    effect_once

    fn effect_once(fn_ : () -> Unit) -> Unit

    Create a one-time effect that disposes itself after first run

    effect_when

    fn effect_when(condition : () -> Bool, fn_ : () -> Unit) -> (() -> Unit)

    Create an effect that only runs when condition is true

    flatten

    fn[T] flatten(outer : Signal[Signal[T]]) -> (() -> T)

    Flatten a signal of signals

    get_current_subscriber

    fn get_current_subscriber() -> EffectRunner?

    Get current subscriber (if any) during signal read

    get_owner

    fn get_owner() -> Owner?

    Get the current owner (if any)

    has_owner

    fn has_owner() -> Bool

    Check if currently inside an owner scope

    is_batching

    fn is_batching() -> Bool

    Check if we're currently inside a batch

    memo

    fn[T] memo(compute : () -> T) -> (() -> T)

    Returns a getter function that caches the result

    new_effect_id

    fn new_effect_id() -> Int

    Generate a new unique effect ID
    fn[T] on(sig : Signal[T], callback : (T) -> Unit) -> (() -> Unit)

    Unlike effect(), this doesn't auto-track and only listens to this one signal

    on_cleanup

    fn on_cleanup(cleanup : () -> Unit) -> Unit

    Must be called inside an effect

    on_immediate

    fn[T] on_immediate(sig : Signal[T], callback : (T) -> Unit) -> (() -> Unit)

    Subscribe and run immediately with current value

    on_mount

    fn on_mount(fn_ : () -> Unit) -> Unit

    Run a function once after mount (Solid.js style onMount) The function runs without tracking dependencies Cleanup registered via onCleanup inside will run when owner is disposed
    fn[T] previous(sig : Signal[T]) -> (() -> T?)

    Returns a getter function for the previous value

    previous_with_initial

    fn[T] previous_with_initial(sig : Signal[T], initial : T) -> (() -> T)

    Create a signal that holds the previous value with initial value

    provide

    fn[T, R] provide(ctx : Context[T], value : T, f : () -> R) -> R

    Provide a context value for the current Owner and its descendants

    The value is associated with the current Owner and will be available to all effects and components created within this scope.

    Example:
    let theme_ctx = create_context("light") provide(theme_ctx, "dark", fn() { // All components here will see "dark" my_component() })

    register_disposer

    fn register_disposer(disposer : () -> Unit) -> Unit

    Register a disposer with the current owner Called internally by effect() to register its dispose function

    register_owner_cleanup

    fn register_owner_cleanup(cleanup : () -> Unit) -> Unit

    Register a cleanup with the current owner (alternative to onCleanup in effect)

    resource

    fn[T] resource(fetcher : ((T) -> Unit, (String) -> Unit) -> Unit) -> Resource[T]

    Create a Resource from a callback-based fetcher The fetcher receives (resolve, reject) callbacks This is environment-agnostic - the actual async execution is handled by the caller

    resource_rejected

    fn[T] resource_rejected(error : String) -> Resource[T]

    Create a Resource with initial error (already rejected)

    resource_resolved

    fn[T] resource_resolved(value : T) -> Resource[T]

    Create a Resource with initial value (already resolved)

    run_with_cleanup_tracking

    fn[T] run_with_cleanup_tracking(cleanups : Array[() -> Unit], f : () -> T) -> T

    Run a function with cleanup tracking enabled

    run_with_owner

    fn[T] run_with_owner(owner : Owner, f : () -> T) -> T

    Run a function with a specific owner as current

    run_with_subscriber

    fn[T] run_with_subscriber(subscriber : EffectRunner, f : () -> T) -> T

    This enables auto-tracking of signal dependencies

    schedule_effect

    fn schedule_effect(effect : EffectRunner) -> Unit

    Schedule an effect to run (respects batching, deduplicates)

    select

    fn[T] select(items : Signal[Array[T]], index : Signal[Int]) -> (() -> T?)

    Select from an array signal by index signal

    set_current_cleanups

    fn set_current_cleanups(cleanups : Array[() -> Unit]?) -> Array[() -> Unit]?

    Set the current cleanup array (used internally by effect)

    signal

    fn[T] signal(initial : T) -> Signal[T]

    Convenience function to create a signal

    switch_

    fn[T] switch_(condition : Signal[Bool], on_true : Signal[T], on_false : Signal[T]) -> (() -> T)

    Switch between signals based on a boolean signal

    untracked

    fn[T] untracked(f : () -> T) -> T

    Run a function without tracking (useful for avoiding circular deps)

    use_context

    fn[T] use_context(ctx : Context[T]) -> T

    Use a context value - returns the current provided value or default Walks up the Owner chain to find the nearest provided value.

    Similar to Solid.js useContext

    Example:
    let theme = use_context(theme_ctx) // Returns "dark" or default

    watch

    fn[T : Eq] watch(source : () -> T, callback : (T, T) -> Unit) -> (() -> Unit)

    Returns a dispose function

    watch_immediate

    fn[T : Eq] watch_immediate(source : () -> T, callback : (T, T?) -> Unit) -> (() -> Unit)

    Watch with immediate execution (runs callback on first value too)