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

@realitycollective/service-framework

v1.0.1

Published

TypeScript service framework core for browser and app runtimes.

Downloads

1,095

Readme

@realitycollective/service-framework

The core runtime of the Reality Collective Service Framework for TypeScript - dependency injection, service lifecycle, events, schedulers and configuration, for browser and app runtimes.

npm install @realitycollective/service-framework

A TypeScript-first implementation of the same architecture as the Reality Collective Unity Service Framework: services are registered into a profile, resolved by token, and driven by a scheduler that the host environment owns.

What it provides

| Area | Detail | | --- | --- | | Service manager | Registration, dependency-ordered start/stop, resolution by token, wait-for-service | | Base services | BaseService and BaseServiceModule - lifecycle hooks with typed configuration | | Tokens | createServiceToken<T>() - type-safe resolution with no string keys at the call site | | Scheduler | Named channels such as renderTick that services subscribe to. Your app decides what drives them: a timer, a render loop, or manual ticks | | Events | An in-framework event service for service-to-service messaging | | Configuration | Profile-based configuration with environment awareness | | Runtime adapter | RuntimeAdapter - the host seam a service depends on: a per-frame fan-out, XR capability flags, and an optional session facet (request, end, state and visibility). Host bindings implement it | | Session features | SessionRequestOptions.requiredFeatures and optionalFeatures - WebXR feature strings for one request, merged over the host's own defaults by mergeSessionInit(init, options). An app that swaps mode mid-session needs them, because the host's defaults were chosen for the mode it is leaving | | Capability derivation | deriveCapabilities(session) - reads immersive, handTracking, planeDetection, passthrough and environmentBlendMode off a live XR session. Shared by every host binding, so the same session reports the same flags under IWSDK and three.js. Its input, CapabilitySessionLike, is structural: no WebXR types, no DOM | | State-owning services | SnapshotService<TConfig, TSnapshot> - one immutable snapshot plus pub/sub; subscribers get the current value immediately, then every publish | | Headless testing | MockRuntimeAdapter - drives frames, capabilities and session lifecycle with no engine, no WebXR and no headset | | Adapter conformance | runtimeAdapterContractCases() - the checks every RuntimeAdapter must pass, shipped as data rather than as a test file, so an adapter written outside this repository can prove it conforms |

EnvironmentDescriptor here means the platform environment - the host's name and its capability strings, such as "dom" or "render-loop" - and is not the same thing as EnvironmentSpec in @realitycollective/webxr-environment, which describes the visual environment of sky, fog and lighting. An app can hold both at once, so the two names are worth keeping apart.

Usage

import {
  ManualScheduler,
  ServiceManager,
  createServiceProfile,
} from "@realitycollective/service-framework";

const scheduler = new ManualScheduler();
const manager = new ServiceManager({ scheduler });

manager.initializeProfile(createServiceProfile("my-app", [/* your service registrations */]));
manager.start();

The host decides what drives the scheduler - a timer, a render loop, or an XR frame source.

Host bindings

The core is host-agnostic. Add exactly one binding for your runtime:

| Package | Host | | --- | --- | | service-framework-react | React provider and hooks | | service-framework-three | three.js render loop, plus a WebXR runtime adapter for any page that owns its renderer | | service-framework-babylon | Babylon.js render loop | | service-framework-iwsdk | Meta IWSDK (WebXR) frame source | | service-framework-client | React + three.js, already wired together |

Writing your own binding

An adapter for a host nobody has covered yet has to behave exactly as the bindings above do, or a service that passes its unit tests stops behaving the same way on a headset. runtimeAdapterContractCases() is the set of checks that says so, shipped as data rather than as a test file so it can run in your repository under your own runner. Each case returns silently on success and throws a plain Error describing the failure otherwise:

import { runtimeAdapterContractCases } from "@realitycollective/service-framework";

for (const contractCase of runtimeAdapterContractCases()) {
  it(contractCase.name, () => contractCase.run(makeSubject()));
}

makeSubject() returns a RuntimeAdapterSubject: your adapter, plus a RuntimeAdapterDriver that pushes a frame, sets capability flags and - if your host owns sessions - starts and ends one. Build a fresh subject per case, because the session cases drive a session through its whole lifecycle. Some cases are asynchronous, so the runner has to await what run returns. An adapter with no session facet passes the session cases without running them, since session is optional.

Live examples

Documentation

Architecture, service authoring and consumption patterns are documented in the repository, including a Unity-to-web migration guide. A runnable example ships in this package's Examples/ folder.

License

MIT - see LICENSE.