@molecule/app-bond
Infrastructure · bond · App (browser) · v1.0.2 · Apache-2.0
Provider wiring mechanism for app-side packages
npm install @molecule/app-bondHow it works
@molecule/app-bond is a infrastructure package for the app (browser) side (bond).
import { bond, get, require as bondRequire, isBonded } from '@molecule/app-bond'
import { provider as routingProvider } from '@molecule/app-routing-react-router'
import type { StateProvider } from '@molecule/app-state'
import { provider as stateProvider } from '@molecule/app-state-zustand'
import type { ThemeProvider } from '@molecule/app-theme'
import { provider as themeProvider } from '@molecule/app-theme-css-variables'
// Singleton providers (one per category)
bond('state', stateProvider)
bond('theme', themeProvider)
// Named providers (multiple per category)
bond('routing', 'react', routingProvider)
// Retrieve providers
const state = get<StateProvider>('state') // undefined if not bonded
const theme = bondRequire<ThemeProvider>('theme') // throws if not bonded
const router = get('routing', 'react')
// Check before using
if (isBonded('routing', 'react')) {
// ...
}Reference
Runtime provider wiring system for molecule.dev app-side packages.
Enables swappable providers for state management, theming, routing, styling,
and any custom category — all through dynamic string-based keys. Most app
cores' own setup helpers (setFont, setRouter, setClassMap, each
setProvider) delegate INTO this registry, so bond('theme', p) and
@molecule/app-theme's setProvider(p) write the same slot — use either.
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Quick Start
import { bond, get, require as bondRequire, isBonded } from '@molecule/app-bond'
import { provider as routingProvider } from '@molecule/app-routing-react-router'
import type { StateProvider } from '@molecule/app-state'
import { provider as stateProvider } from '@molecule/app-state-zustand'
import type { ThemeProvider } from '@molecule/app-theme'
import { provider as themeProvider } from '@molecule/app-theme-css-variables'
// Singleton providers (one per category)
bond('state', stateProvider)
bond('theme', themeProvider)
// Named providers (multiple per category)
bond('routing', 'react', routingProvider)
// Retrieve providers
const state = get<StateProvider>('state') // undefined if not bonded
const theme = bondRequire<ThemeProvider>('theme') // throws if not bonded
const router = get('routing', 'react')
// Check before using
if (isBonded('routing', 'react')) {
// ...
}
Type
infrastructure
Installation
npm install @molecule/app-bond
API
Interfaces
Provider
Minimal base interface that every bondable provider can optionally satisfy.
Provider implementations may include a name for logging and debugging
but are not required to extend this interface.
interface Provider {
/**
* Optional human-readable identifier for this provider, used in log
* output and error messages.
*/
readonly name?: string
}
ProviderRegistry
Internal data structure that holds all bonded providers at runtime. The registry distinguishes between singleton providers (one per category) and named providers (multiple per category, keyed by a string name).
interface ProviderRegistry {
/**
* Map from category string (e.g. `'state'`, `'theme'`) to the single
* active provider instance for that category.
*/
singletons: Map<string, unknown>
/**
* Two-level map: outer key is the category string (e.g. `'routing'`),
* inner key is the provider name (e.g. `'react'`), value is the provider instance.
*/
named: Map<string, Map<string, unknown>>
}
BondConfig
Options that control bond registration behavior.
interface BondConfig {
/**
* When `true`, bonding a provider to a category that already has a bonded
* provider throws an error instead of silently replacing it.
* @default false
*/
strict?: boolean
/**
* When `true`, every bond / unbond / clear / reset operation emits a
* diagnostic line via `console.debug` (prefixed `[app-bond]`). Useful for
* tracing wiring order at startup; leave `false` in production.
* @default false
*/
verbose?: boolean
}
Functions
bond(type, provider)
Registers a provider at runtime. With two arguments, bonds a singleton provider for the category. With three arguments, bonds a named provider under the category.
function bond(type: string, provider: unknown): void
type— The provider category (e.g.'state','theme','routing').provider— The provider instance to bond as a singleton.
get(type)
Retrieves a bonded singleton provider by category, or undefined if not bonded.
function get(type: string): T | undefined
type— The provider category to look up.
Returns: The bonded provider instance, or undefined if not bonded.
getAll(type)
Retrieves all named providers bonded under a category. Returns an empty Map if no named providers exist for the category.
function getAll(type: string): Map<string, T>
type— The provider category to look up.
Returns: A Map from provider name to provider instance.
require(type)
Retrieves a bonded singleton provider, throwing if not bonded. Use this when the provider is required for the application to function.
function require(type: string): T
type— The provider category to look up.
Returns: The bonded provider instance.
unbond(type)
Removes a bonded singleton provider from a category.
function unbond(type: string): boolean
type— The provider category to unbond.
Returns: true if a provider was removed, false if none was bonded.
unbondAll(type)
Removes all providers (both singleton and named) for a category.
function unbondAll(type: string): void
type— The provider category to clear entirely.
isBonded(type)
Checks whether a singleton provider is bonded for a category.
function isBonded(type: string): boolean
type— The provider category to check.
Returns: true if a singleton provider is bonded for the category.
configure(newConfig)
Merges new configuration options into the current bond configuration.
function configure(newConfig: Partial<BondConfig>): void
newConfig— Partial configuration to merge. Unspecified fields retain their current values.
bondSingleton(type, provider)
Registers a singleton provider for the given category. If provider is null/undefined,
the existing singleton for that category is removed instead. In strict mode, throws
if a provider is already bonded to the category.
function bondSingleton(type: string, provider: T): void
type— The provider category (e.g.'state','theme','routing').provider— The provider instance to bond, or null/undefined to remove.
getSingleton(type)
Retrieves the singleton provider for a category, or undefined if none is bonded.
function getSingleton(type: string): T | undefined
type— The provider category to look up.
Returns: The bonded provider instance cast to T, or undefined if not bonded.
requireSingleton(type)
Retrieves the singleton provider for a category, throwing if none is bonded. Use this when the provider is required for the application to function.
function requireSingleton(type: string): T
type— The provider category to look up.
Returns: The bonded provider instance cast to T.
bondNamed(type, name, provider)
Registers a named provider under a category. Named providers allow multiple
implementations per category (e.g. bond('routing', 'react', reactProvider)).
In strict mode, throws if that name is already bonded in the category.
function bondNamed(type: string, name: string, provider: T): void
type— The provider category (e.g.'routing','oauth').name— The unique name within the category (e.g.'react','github').provider— The provider instance to bond.
getNamed(type, name)
Retrieves a named provider from a category, or undefined if not bonded.
function getNamed(type: string, name: string): T | undefined
type— The provider category to look up.name— The provider name within the category.
Returns: The bonded provider instance cast to T, or undefined if not found.
getAllNamed(type)
Retrieves all named providers bonded under a category as a Map keyed by provider name. Returns an empty Map if no providers are bonded for the category.
function getAllNamed(type: string): Map<string, T>
type— The provider category to look up.
Returns: A Map from provider name to provider instance for the given category.
requireNamed(type, name)
Retrieves a named provider from a category, throwing if not bonded. Use this when the provider is required for the application to function.
function requireNamed(type: string, name: string): T
type— The provider category to look up.name— The provider name within the category.
Returns: The bonded provider instance cast to T.
unbondSingleton(type)
Removes a singleton provider from a category.
function unbondSingleton(type: string): boolean
type— The provider category to unbond.
Returns: true if a provider was removed, false if none was bonded.
unbondNamed(type, name)
Removes a named provider from a category.
function unbondNamed(type: string, name: string): boolean
type— The provider category containing the named provider.name— The provider name to remove.
Returns: true if the provider was removed, false if it was not found.
clearProviders(type)
Removes all providers (both singleton and named) for a given category.
function clearProviders(type: string): void
type— The provider category to clear.
reset()
Removes all bonded providers across all categories, restoring the registry to its initial empty state. Primarily used in test teardown.
function reset(): void
Constants
registry
Global provider registry instance shared across all bond operations. Contains both singleton providers (one per category) and named providers (multiple per category, keyed by name).
const registry: ProviderRegistry
config
Current bond configuration controlling strict mode and verbosity.
const config: BondConfig
Injection Notes
- Wire before ANY module evaluates a bond-backed accessor.
get()returnsundefinedandrequire()THROWS until a provider is bonded — and app modules are imported (module top-level runs) BEFORE yoursetupProviders()/bonds/index.tsexecutes. A module-scopeconst cm = getClassMap()orconst router = require('routing')in a component file therefore runs pre-wiring and breaks the app at load. Call accessors inside components/functions, never at module top-level. - All cores now read this registry. Every
@molecule/app-*core routes itssetProvider()/getProvider()through this bond registry (the ai-*, audio, color-picker, date-range-picker, gallery, image-crop, keyboard-shortcuts, markdown, stepper, timeline, tour, tree-view, battery, bluetooth, brightness, nfc, and screen-orientation cores were migrated off their old module-local singletons), sobond('<category>', p)and the core's ownsetProvider()write the same slot. Use either. - Re-bonding a category silently replaces the provider (last bond wins).
Call
configure({ strict: true })to make double-bonding throw instead.bond(type, null)/bond(type, undefined)REMOVES the singleton for that category.configure({ verbose: true })logs each bond / unbond / clear / reset toconsole.debug(prefixed[app-bond]) for wiring-order tracing. requirecollides with CommonJS — import it renamed:import { require as bondRequire } from '@molecule/app-bond'.