npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@loro-extended/lea

v0.1.0

Published

LEA 3.0 (Loro Extended Architecture) - Pure functional state management with reactive side effects for CRDT applications

Downloads

61

Readme

@loro-extended/lea

LEA 3.0 (Loro Extended Architecture) - A pattern for building CRDT-native applications with pure functional principles.

Overview

LEA extends The Elm Architecture (TEA) to work with CRDTs. The core equation is:

(Frontier, Msg) → Frontier'

Where:

  • Frontier is a CRDT version vector (point in time)
  • Msg is an immutable message describing what happened
  • Frontier' is the new version after applying the message

Key Components

1. Doc (Shared State)

The CRDT document that holds your application state. Uses @loro-extended/change for type-safe schema definitions.

2. Update (State Transition)

A pure function that applies messages to the document:

import { createUpdate } from "@loro-extended/lea"
import { change } from "@loro-extended/change"

const update = createUpdate<MySchema, MyMsg>((doc, msg, timestamp) => {
  switch (msg.type) {
    case "INCREMENT":
      change(doc, draft => {
        draft.counter.value += 1
      })
      break
  }
})

3. Reactors (Side Effects)

Functions that respond to state transitions:

import type { Reactor } from "@loro-extended/lea"
import { entered } from "@loro-extended/lea"

const myReactor: Reactor<MySchema, MyMsg> = (transition, dispatch) => {
  // Detect when we enter a specific state
  if (entered("complete", t => t.status, transition)) {
    console.log("Quiz completed!")
  }
}

4. Runtime (Imperative Shell)

The only impure part - orchestrates everything:

import { createRuntime } from "@loro-extended/lea"

const { dispatch, dispose } = createRuntime({
  doc: myDoc,
  update: myUpdate,
  reactors: [myReactor],
})

// Dispatch messages
dispatch({ type: "INCREMENT" })

// Clean up when done
dispose()

Transition Helpers

Detect state changes with type-safe helpers:

import { entered, exited, changed, transitioned } from "@loro-extended/lea"

// Did we enter a specific value?
if (entered("active", t => t.status, transition)) { ... }

// Did we exit a specific value?
if (exited("loading", t => t.status, transition)) { ... }

// Did a value change at all?
if (changed(t => t.count, transition)) { ... }

// Did we transition from one value to another?
if (transitioned("draft", "published", t => t.status, transition)) { ... }

History Tracking

Track message history for debugging and time travel:

import { 
  HistoryDocSchema, 
  appendHistoryEntry, 
  getHistoryEntries 
} from "@loro-extended/lea"

// Create a history document
const historyDoc = createTypedDoc(HistoryDocSchema)

// Pass to runtime for automatic tracking
const { dispatch, dispose } = createRuntime({
  doc: myDoc,
  update: myUpdate,
  reactors: [],
  historyDoc, // Messages are automatically recorded
})

// Later, retrieve history
const entries = getHistoryEntries(historyDoc)

Installation

pnpm add @loro-extended/lea @loro-extended/change loro-crdt

API Reference

Types

  • Transition<Schema> - Before/after state pair
  • Dispatch<Msg> - Function to dispatch messages
  • Reactor<Schema, Msg> - Function that responds to transitions
  • Program<Schema, Msg> - Runtime configuration

Functions

  • createUpdate<Schema, Msg>(handler) - Create an update function
  • createRuntime(program) - Create a runtime instance
  • entered(value, selector, transition) - Detect entering a state
  • exited(value, selector, transition) - Detect exiting a state
  • changed(selector, transition) - Detect any change
  • transitioned(from, to, selector, transition) - Detect specific transition

History

  • HistoryDocSchema - Schema for history documents
  • appendHistoryEntry(doc, msg, timestamp) - Add a history entry
  • getHistoryEntries(doc) - Get all history entries
  • getHistoryDocId(appDocId) - Generate history doc ID from app doc ID

Philosophy

LEA follows these principles:

  1. Pure Core, Impure Shell - Update functions are pure; runtime handles side effects
  2. Single Source of Truth - The CRDT document is the only state
  3. Deterministic Transitions - Same frontier + same message = same result
  4. Lazy Evaluation - TypedDoc proxies avoid unnecessary serialization
  5. Unified Reactors - Views, effects, and subscriptions are all reactors

License

MIT