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

domwires

v5.0.1

Published

Flexible and extensible MVC framework

Readme

DomWires 5.0

Typed messages. Explicit state changes. Components with clear lifetimes.

DomWires is a dependency-free TypeScript framework for composing applications from models, mediators, commands and contexts. It works in browsers and Node.js, alongside your UI or rendering library.

A context connects components through messages and contracts. Commands change model state. Views capture input and render data. Mediators translate view callbacks into messages and read live state through Immutable interfaces. Context boundaries make dependencies, routing and cleanup explicit.

Get started · Documentation · API reference · Examples

5.0 introduces a new API. The previous implementation is preserved on v2.x. See the changelog and release guide.

How it fits together

This is one real route from the scene lab. Each context creates its mediators; each mediator creates and disposes its view. The walkthrough expands it to nested contexts, level loading, cancellation and HUD updates.

| Component | Responsibility | | --- | --- | | Model | Owns state and emits change notifications. | | Immutable interface | Exposes the same live model without its mutation methods. It does not freeze or clone the object. | | View | Captures input, reports callbacks or UI events, and renders data. | | Mediator | Creates and owns its view, translates input into messages, reads model state and updates the view. | | Command | Performs an application action, synchronously or asynchronously. | | Context | Composes components, maps messages, controls boundaries and owns lifetimes. | | Adapter | Ordinary infrastructure object used by commands; no required Service base class. |

Quick start

Install DomWires in your application:

npm install domwires@^5.0.0

To build this repository and run the examples:

npm ci
npm run build
npm run example

Open the printed localhost URL for the counter and scene lab. To test local changes in another application, run npm pack and install the resulting tarball. Import from domwires.

A complete message-to-command program:

import {AbstractCommand, AbstractContext, Factory, MessageType} from "domwires";

const GREET = new MessageType<{name: string}>("greet");

class Greet extends AbstractCommand<{name: string}>
{
    public override execute(input: {name: string}): void
    {
        console.log("Hello, " + input.name + "!");
    }
}

class AppContext extends AbstractContext
{
    protected override init(): void
    {
        super.init();
        this.map(GREET, Greet);
    }
}

async function main(): Promise<void>
{
    const factory = new Factory();
    const app = factory.getInstance(AppContext);

    try
    {
        app.dispatchMessage(GREET, {name: "DomWires"});
        await app.settle();
    }
    finally
    {
        await app.close();
        factory.dispose();
    }
}

void main();

Create contexts through the factory so their initialization hook runs. dispatchMessage() delivers synchronously; settle() drains command work; close() cancels and awaits teardown. Continue with the counter model and mediator.

What 5.0 brings

  • Typed contracts: payloads, command input, model access and dependency tokens checked together.
  • Scoped composition: separate roles for commands, models, mediators and adapters; explicit child-context imports.
  • Native async commands: invocation-local state, cooperative cancellation and guarded model commits.
  • Per-mapping concurrency: parallel, serial, latest and drop policies; disposable registrations and guards.
  • Owned resources: startup, reverse-order cleanup and an awaitable close boundary.
  • Observable execution: optional trace callbacks with correlated IDs, isolated observer failures and no built-in history buffer.
  • Flexible construction: constructor/provider injection or optional legacy property decorators; no reflection-metadata dependency.

Explore the examples

| Example | Focus | | --- | --- | | Counter | Basic model/mediator flow, read/write tokens, guards and remounting | | Scene lab | Nested contexts, tick, projectile reuse, async loading, scene switching and trace | | Concurrent requests | Scoped injection and cancellation before committing a result | | Node config | Platform-specific JSON loading through domwires/node |

Runtime and development

Built with TypeScript 7, targeting ES2022. The package declares Node 20+ and the CI workflow checks Node 20/22/24. The root entry point is browser-compatible; Node-specific loading is a separate export. Node ESM and CommonJS entry points share the same classes, tokens and registries, so mixing import and require preserves identity. Browser bundlers select one native ESM implementation for both import styles. Both formats include declarations and source maps; application types are checked with TypeScript 6 and 7.

Property decorators use experimentalDecorators; constructor and provider injection need no decorator syntax. Runtime dependencies are empty.

See contributing for the complete verification commands, source organization and generated API documentation. Public method contracts live in source comments and are carried into declaration files.

License and origins

MIT. DomWires grew from ActionScript 3 and Haxe implementations; 5.0 keeps the component model while making TypeScript contracts and lifetimes explicit. Visual identity and logo references.