### Install Deno (PowerShell and shell)
Source: https://github.com/disjukr/bunja/blob/main/examples/timer-solid/README.md
Commands to install Deno 2+ on Windows (PowerShell) and macOS/Linux.
```bash
# Windows (PowerShell)
irm https://deno.land/install.ps1 | iex
```
```bash
# macOS/Linux
curl -fsSL https://deno.land/install.sh | sh
```
--------------------------------
### Start Development Server with deno task dev
Source: https://github.com/disjukr/bunja/blob/main/examples/timer/README.md
Starts the development server. Visit http://localhost:5173 in your browser.
```bash
deno task dev
```
--------------------------------
### Install Dependencies with deno install
Source: https://github.com/disjukr/bunja/blob/main/examples/timer/README.md
Installs project dependencies using Deno's package manager.
```bash
deno install
```
--------------------------------
### Install Deno (macOS/Linux)
Source: https://github.com/disjukr/bunja/blob/main/examples/timer/README.md
Command to install Deno on macOS/Linux using curl. Requires Deno 2+.
```bash
# macOS/Linux
curl -fsSL https://deno.land/install.sh | sh
```
--------------------------------
### BunjaStoreProvider usage example
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/solid.md
Example of using BunjaStoreProvider in a Solid app. Wrap your components with it to provide a bunja store.
```tsx
import { BunjaStoreProvider } from "bunja/solid";
export function App() {
return (
);
}
```
--------------------------------
### prebake usage example
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/bunja-store.md
Example of calling store.prebake with a bunja reference and readScope, then logging the result fields.
```ts
const result = store.prebake(selectedResourceBunja, readScope);
// inspect the whole graph, including inactive bunja.will branches
console.log(result.relatedBunjas);
console.log(result.requiredScopes);
```
--------------------------------
### Install Deno (Windows PowerShell)
Source: https://github.com/disjukr/bunja/blob/main/examples/timer/README.md
Command to install Deno on Windows using PowerShell. Requires Deno 2+.
```bash
# Windows (PowerShell)
irm https://deno.land/install.ps1 | iex
```
--------------------------------
### bindScope usage example
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/solid.md
Example of binding a Solid context to a scope. Creates a context with a default URL, a scope, and binds them.
```tsx
import { createContext } from "solid-js";
import { createScope } from "bunja";
import { bindScope } from "bunja/solid";
const UrlContext = createContext("https://example.com/");
const UrlScope = createScope();
bindScope(UrlScope, UrlContext);
```
--------------------------------
### bindScope usage example
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/react.md
Example of binding a React context to a scope using bindScope.
```tsx
import { createContext } from "react";
import { createScope } from "bunja";
import { bindScope } from "bunja/react";
const UrlContext = createContext("https://example.com/");
const UrlScope = createScope();
bindScope(UrlScope, UrlContext);
```
--------------------------------
### Scope.bind usage example
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/scope.md
Example of creating a scope and binding a value to it, producing a tuple that can be passed to bunja APIs.
```typescript
const UrlScope = createScope();
const pair: [Scope, string] = UrlScope.bind("https://example.com/");
```
--------------------------------
### Basic usage of useBunja with tickBunja
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/solid.md
Example showing how to use useBunja in a Solid component to resolve a bunja instance and access its subscribe method. The instance is mounted while the component is mounted.
```tsx
import { useBunja } from "bunja/solid";
import { tickBunja } from "./tick";
function TickerView() {
const { subscribe } = useBunja(tickBunja);
// subscribe() is the instance value; instance lives while this view is mounted
return ticker ready;
}
```
--------------------------------
### getHook() usage example
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/devtools.md
Usage example for getHook() from react-bunja-devtools/hook. Imports the hook and subscribes to the 'bunjaInstanceMounted' event, logging the bunjaInstanceId when a bunja instance mounts.
```TypeScript
import { getHook } from "react-bunja-devtools/hook";
const hook = getHook();
if (hook) {
const off = hook.on("bunjaInstanceMounted", ({ bunjaInstanceId }) => {
console.log("mounted", bunjaInstanceId);
});
}
```
--------------------------------
### createScopeFromContext usage example
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/react.md
Example of creating a scope from a React context using createScopeFromContext. Imports createContext from react and createScopeFromContext from bunja/react, then creates a context and a bound scope.
```typescript
import { createContext } from "react";
import { createScopeFromContext } from "bunja/react";
const UrlContext = createContext("https://example.com/");
const UrlScope = createScopeFromContext(UrlContext);
```
--------------------------------
### Usage example: creating and inspecting a bunja
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/bunja-class.md
Creates a bunja with the bunja factory, sets a debug label, then after store.get and mount, shows how to inspect the baked state with baked, requiredScopes, relatedBunjas, and toString.
```ts
import { bunja } from "bunja";
const myBunja = bunja(() => ({}));
myBunja.debugLabel = "session state";
// After a store.get or prebake, the graph is baked and inspectable:
const { mount } = store.get(myBunja, readScope);
const unmount = mount();
unmount();
console.log(myBunja.baked); // true
console.log(myBunja.requiredScopes); // the scope list
console.log(myBunja.relatedBunjas); // topological dependency list
console.log(myBunja.toString()); // "[Bunja:0 - session state]"
```
--------------------------------
### bunja usage example
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/bunja-function.md
Example of defining a bunja that manages a WebSocket connection. The init function creates a socket in an effect and returns a send method.
```typescript
import { bunja } from "bunja";
const connectionBunja = bunja(() => {
let socket: WebSocket | null = null;
bunja.effect(() => {
socket = new WebSocket("wss://example.com/ws");
return () => socket?.close();
});
return {
send: (message: unknown) => socket?.send(JSON.stringify(message)),
};
});
```
--------------------------------
### toBunjaRenderTree() usage example
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/devtools.md
Usage example for toBunjaRenderTree() from react-bunja-devtools/brt. Imports the function and a custom getFiber() helper, then traverses the resulting tree and logs each node's no and name.
```TypeScript
import { toBunjaRenderTree } from "react-bunja-devtools/brt";
import { getFiber } from "./my-fiber-access";
const tree = toBunjaRenderTree(getFiber());
for (const node of tree) {
console.log(node.no, node.name);
}
```
--------------------------------
### createScope usage example
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/scope.md
Shows how to create scopes with and without a custom hash function. The LocaleByLengthScope uses a hash that groups languages by length, so 'en' and 'fr' share an instance while 'en-US' is separate.
```typescript
import { createScope } from "bunja";
const LocaleScope = createScope();
// hash by value length — "en" and "fr" share an instance, "en-US" is separate
const LocaleByLengthScope = createScope((lang) => lang.length);
```
--------------------------------
### createBunjaStore with wrapInstance option
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/configuration.md
Creates a Bunja store with a custom wrapInstance function that logs when an instance is disposed. The wrapInstance option wraps every instance creation (both get and prebake paths) and must call the provided dispose function to release the instance.
```TypeScript
import { createBunjaStore } from "bunja";
// track every instance creation
const store = createBunjaStore({
wrapInstance: (fn) =>
fn(() => console.log("an instance was disposed")),
});
```
--------------------------------
### Reactive scope injection and error handling example
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/solid.md
Shows passing a reactive scopeValuePairs accessor to useBunja so that changing a signal re-resolves the scope instance. Imports createSignal and fetchBunja.
```tsx
import { createSignal } from "solid-js";
import { useBunja } from "bunja/solid";
import { fetchBunja } from "./states";
function MyComponent() {
const [url, setUrl] = createSignal("https://example.com/a");
// reactive scope injection: switching url swaps the scope instance
const { queryAtom } = useBunja(fetchBunja, () => [UrlScope.bind(url())]);
return ;
}
```
--------------------------------
### BunjaStoreProvider usage example
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/react.md
React component that wraps children with BunjaStoreProvider to share a BunjaStore.
```tsx
import { BunjaStoreProvider } from "bunja/react";
export function App() {
return (
);
}
```
--------------------------------
### Error handling example: accessing requiredScopes before baking
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/bunja-class.md
Shows that calling requiredScopes before baking throws an error with message 'Bunja is not baked yet.' and that prebaking via createBunjaStore().prebake resolves it, after which requiredScopes returns an empty array.
```ts
const unvisited = bunja(() => ({}));
try {
console.log(unvisited.requiredScopes); // throws — graph not baked yet
} catch (error) {
// Error: "Bunja is not baked yet."
// Bake it first through store.get / store.prebake:
createBunjaStore().prebake(unvisited, readNullScope);
console.log(unvisited.requiredScopes); // []
}
```
--------------------------------
### BunjaDevtoolsGlobalHook
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/types.md
Interface for the global devtools hook installed as globalThis.__BUNJA_DEVTOOLS_GLOBAL_HOOK__ in dev builds. Provides access to all bunjas, scopes, and event subscription.
```APIDOC
## BunjaDevtoolsGlobalHook
### Description
Interface for the global devtools hook installed as `globalThis.__BUNJA_DEVTOOLS_GLOBAL_HOOK__` in dev builds. Provides access to all bunjas, scopes, and event subscription.
### Fields
- **bunjas** (`Record>`) - All bunjas created in this runtime, keyed by `bunja.id`.
- **scopes** (`Record>`) - All scopes, keyed by `scope.id`.
- **listeners** (`Record void>>`) - Listener sets per event type.
### Methods
#### emit(type, event)
Dispatches to all listeners of `type`.
**Parameters:**
- `type` (`BunjaDevtoolsEventType`) - The event type to emit.
- `event` (`BunjaDevtoolsEvent[T]`) - The event payload.
**Returns:** `void`
#### on(type, listener)
Subscribes to an event type; returns an unsubscribe function.
**Parameters:**
- `type` (`BunjaDevtoolsEventType`) - The event type to subscribe to.
- `listener` (`(event: BunjaDevtoolsEvent[T]) => void`) - The listener function.
**Returns:** `() => void` - Unsubscribe function.
### Usage
Installed as `globalThis.__BUNJA_DEVTOOLS_GLOBAL_HOOK__` in dev builds. Read by `getHook()` from `react-bunja-devtools/hook`.
```
--------------------------------
### BunjaDevtoolsGlobalHook interface
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/types.md
Defines the global hook object installed as globalThis.__BUNJA_DEVTOOLS_GLOBAL_HOOK__ in dev builds. Read by getHook() from react-bunja-devtools/hook.
```ts
// bunja/bunja.ts:1134
export interface BunjaDevtoolsGlobalHook {
bunjas: Record>;
scopes: Record>;
listeners: Record void>>;
emit(
type: T,
event: BunjaDevtoolsEvent[T],
): void;
on(
type: T,
listener: (event: BunjaDevtoolsEvent[T]) => void,
): () => void;
}
```
--------------------------------
### Bind scope to React context and use in components
Source: https://github.com/disjukr/bunja/blob/main/README.md
Shows how to bind a scope to a React context so bunjas can retrieve values from the context. Two React instances reference the same fetchBunja but get separate instances due to different context values.
```tsx
import { createContext } from "react";
import { bunja, createScope } from "bunja";
import { bindScope } from "bunja/react";
const UrlContext = createContext("https://example.com/");
const UrlScope = createScope();
bindScope(UrlScope, UrlContext);
const fetchBunja = bunja(() => {
const url = bunja.use(UrlScope);
const queryAtom = atomWithQuery((get) => ({
queryKey: [url],
queryFn: async () => (await fetch(url)).json(),
}));
return { queryAtom };
});
function ParentComponent() {
return (
<>
>
);
}
function ChildComponent() {
const { queryAtom } = useBunja(fetchBunja);
const { data, isPending, isError } = useAtomValue(queryAtom);
// Your component logic here
}
```
--------------------------------
### Preview Built Application with deno task preview
Source: https://github.com/disjukr/bunja/blob/main/examples/timer/README.md
Previews the built application locally.
```bash
deno task preview
```
--------------------------------
### Production Build with deno task build
Source: https://github.com/disjukr/bunja/blob/main/examples/timer/README.md
Builds the application for production. Output is generated in the dist/ directory.
```bash
deno task build
```
--------------------------------
### BunjaStoreProvider({ children })
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/react.md
Creates a fresh BunjaStore once and disposes it on unmount. All useBunja calls inside the provider share that store.
```APIDOC
## BunjaStoreProvider({ children })
### Description
Creates a fresh `BunjaStore` once (`useState(createBunjaStore)`) and disposes it on unmount (`useEffect(() => () => value.dispose(), [value])`). All `useBunja` calls inside the provider share that store.
### Signature
```ts
// bunja/react.ts:39
export function BunjaStoreProvider(
{ children }: PropsWithChildren,
): React.JSX.Element
```
### Parameters
#### Props
- **children** (`PropsWithChildren`) - Required - React children to be rendered inside the provider.
### Returns
- `React.JSX.Element` - The provider element.
### Usage Example
```tsx
import { BunjaStoreProvider } from "bunja/react";
export function App() {
return (
);
}
```
```
--------------------------------
### createBunjaStore(config?)
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/bunja-store.md
Creates a new BunjaStore instance with optional configuration. The store manages bunja instances and scope instances, resolving refs and handling instance lifecycle.
```APIDOC
## createBunjaStore(config?)
### Description
Creates a new BunjaStore instance. The store owns all live bunja instances and scope instances, resolves bunja refs against a ReadScope, creates and ref-counts instances, mounts/unmounts dependencies and effects, and can prebake the dependency graph in dry mode for devtools.
### Signature
```ts
export function createBunjaStore(config?: CreateBunjaStoreConfig): BunjaStore
```
### Parameters
#### config (object) - Optional
- **config.wrapInstance** (`WrapInstanceFn`) - Optional - Default: `defaultWrapInstanceFn` (calls `fn(noop)`) - Wraps each instance creation. React adapter leaves it default; Solid adapter uses `createRoot` to tie instance lifetimes to Solid's root disposal. Prebake calls it too and always invokes the passed `dispose`.
### Returns
`BunjaStore` — a new store with an auto-incremented `id`. In dev mode (`NODE_ENV !== "production"`) the store emits a `storeCreated` devtools event.
### Usage Example
```ts
import { createBunjaStore } from "bunja";
const store = createBunjaStore({
wrapInstance: (fn) => fn(() => console.log("instance disposed")),
});
```
```
--------------------------------
### Constructor
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/bunja-class.md
Creates a new Bunja instance with an init function and a default seed.
```APIDOC
## Constructor
### Description
Creates a new Bunja instance. The init function is called once per new instance creation (and per prebake traversal) with the effective seed.
### Method
Constructor
### Signature
```ts
constructor(
public init: (seed: Seed) => T,
public defaultSeed: Seed,
)
```
### Parameters
- **init** (`(seed: Seed) => T`) - Required - Init function; receives the effective seed.
- **defaultSeed** (`Seed`) - Required - Fallback seed used when no seed is supplied by callers and during `store.prebake`.
### Notes
Normally you do not construct `Bunja` directly — `bunja(init)` and `bunja.withSeed(defaultSeed, init)` do this for you with the correct `Seed` generic.
```
--------------------------------
### BunjaStoreProvider
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/solid.md
Creates a store per provider, wrapping each bunja instance in its own Solid root and disposing the store on cleanup.
```APIDOC
## `BunjaStoreProvider`
### Signature
```ts
// bunja/solid.ts:40
export function BunjaStoreProvider(
props: ParentProps,
): JSX.Element
```
### Description
Creates a store per provider with `wrapInstance: (impl) => createRoot(impl, owner)` so each bunja instance is created inside its own Solid root owned by the provider, and disposes the store via `onCleanup(() => bunjaStore.dispose())`.
### Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `props` | `ParentProps` | yes | Props for the provider component, including children. |
### Returns
`JSX.Element` - The provider element.
### Usage example
```tsx
import { BunjaStoreProvider } from "bunja/solid";
export function App() {
return (
);
}
```
```
--------------------------------
### BunjaStoreContext
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/solid.md
A Solid context that provides the default bunja store, created at module load with createRoot as the wrapInstance.
```APIDOC
## `BunjaStoreContext`
### Signature
```ts
// bunja/solid.ts:36
export const BunjaStoreContext: Context = createContext(
createBunjaStore({ wrapInstance: createRoot }),
);
```
### Description
Default context value is a store created at module load that wraps each bunja instance creation with Solid's `createRoot`.
### Type
`Context` - A Solid context object.
### Usage
This context is used internally by `BunjaStoreProvider` and can be consumed by components to access the current bunja store.
```
--------------------------------
### prebake(bunjaOrRef, readScope)
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/bunja-store.md
Prebakes the dependency graph in a dry mode: runs init functions to collect scopes, required refs, and optional refs, but does not create ref-counted instances, mount anything, or run bunja.effect callbacks. Use it from devtools/debugging code to visit declared-but-inactive bunja.will branches.
```APIDOC
## prebake(bunjaOrRef, readScope)
### Description
Prebakes the dependency graph in a dry mode: runs init functions to collect scopes, required refs, and optional refs, but does not create ref-counted instances, mount anything, or run `bunja.effect` callbacks. Use it from devtools/debugging code to visit declared-but-inactive `bunja.will` branches.
### Signature
```ts
prebake(
bunjaOrRef: Bunja | BunjaPrebakeRef,
readScope: ReadScope,
): BunjaStorePrebakeResult
```
### Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `bunjaOrRef` | `Bunja` or `BunjaPrebakeRef` (ref with `seed?: never`) | yes | Root to prebake. A root ref with a runtime `seed` key is rejected. During prebake every bunja is initialized with its declared `defaultSeed`. |
| `readScope` | `ReadScope` | yes | Scope value reader, as in `get`. |
### Returns
`BunjaStorePrebakeResult`:
| Field | Type | Description |
|-------|------|-------------|
| `relatedBunjas` | `Bunja[]` | Topologically ordered list of all required + optional bunjas reachable from the root. |
| `requiredScopes` | `Scope[]` | All scopes the prebaked subtree would need once mounted. |
### Throws
| Error | Condition |
|-------|-----------|
| `Error` "A bunja seed cannot be provided to `store.prebake`." | Root ref object carries a `seed` property. |
| `Error` "Circular bunja dependency detected." | Cycle in the graph. |
### Usage Example
```ts
const result = store.prebake(selectedResourceBunja, readScope);
// inspect the whole graph, including inactive bunja.will branches
console.log(result.relatedBunjas);
console.log(result.requiredScopes);
```
```
--------------------------------
### Bunja + Solid timer component (TSX)
Source: https://github.com/disjukr/bunja/blob/main/examples/timer-solid/README.md
Shows Bunja managing timer state with Solid stores and memos, and a Timer component using useBunja with scoped dependency injection.
```tsx
// Scoped timer state with Solid integration
export const timerBunja = bunja(() => {
// Reactive state with Solid stores
const [timer, setTimer] = createStore({ elapsed: 0, running: false });
// Derived memos for computed values
const seconds = createMemo(() => {
return Math.floor(timer.elapsed / 1000).toString().padStart(2, "0");
});
// Lifetime management
bunja.effect(() => () => cleanup());
return { timer, seconds, start, stop, reset };
});
// Component usage
function Timer(props: Props) {
const timer = useBunja(
timerBunja,
() => [ItemScope.bind(props.id)], // Scoped dependency injection
);
return (
{timer().seconds()}
{timer().timer.running
?
: }
);
}
```
--------------------------------
### createScopeFromContext(context, hash?)
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/react.md
Creates a scope and binds it to the provided React context in one step. The optional hash function is forwarded to createScope for deduplication of injected values.
```APIDOC
## createScopeFromContext(context, hash?)
### Description
Creates a scope and binds it to the context in one step. `hash` is the optional deduplication `HashFn` forwarded to `createScope`.
### Signature
```ts
// bunja/react.ts:58
export function createScopeFromContext(
context: Context,
hash?: HashFn,
): Scope
```
### Parameters
- **context** (`Context`) - Required - Context to read scope values from.
- **hash** (`HashFn`) - Optional - Dedupes injected values into scope instances. Defaults to identity.
### Returns
- **Scope** - The new bound scope.
### Usage Example
```ts
import { createContext } from "react";
import { createScopeFromContext } from "bunja/react";
const UrlContext = createContext("https://example.com/");
const UrlScope = createScopeFromContext(UrlContext);
```
```
--------------------------------
### brtToString(nodes, depth = 0)
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/devtools.md
Serializes a Bunja render tree (BrtNode[]) into a human-readable string representation. The depth parameter controls initial indentation, with each level adding two spaces.
```APIDOC
## `brtToString(nodes, depth = 0)`
### Description
Converts an array of BrtNode objects (produced by `toBunjaRenderTree`) into a string representation. This is useful for debugging or displaying the render tree in a human-readable format.
### Signature
```ts
export function brtToString(nodes: BrtNode[], depth = 0): string
```
### Parameters
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `nodes` | `BrtNode[]` | yes | — | BRT nodes produced by `toBunjaRenderTree`. |
| `depth` | `number` | no | `0` | Initial indentation depth (each level adds two spaces). |
### Returns
`string` — a human-readable tree. Components render as ``; a single context renders as `` (values are stringified with `repr`: functions by name, objects by constructor tag, strings JSON-quoted and truncated at 20 chars); multiple collapsed contexts render as ``.
### Usage example
```ts
import { brtToString, toBunjaRenderTree } from "react-bunja-devtools/brt";
console.log(brtToString(toBunjaRenderTree(rootFiber)));
```
```
--------------------------------
### bunja(init)
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/bunja-function.md
Defines a bunja without seed data. The init function is evaluated once per bunja instance and may call bunja.use, bunja.will, and bunja.effect. Returns a Bunja definition object.
```APIDOC
## bunja(init)
### Description
Defines a bunja without seed data. The init function is evaluated once per bunja instance and may call bunja.use, bunja.will, and bunja.effect. Returns a Bunja definition object.
### Signature
```ts
// bunja/bunja.ts:12
export const bunja: BunjaFn = bunjaFn;
// bunja/bunja.ts:13
function bunjaFn(init: () => T): Bunja {
return new Bunja(() => init(), undefined);
}
```
### Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `init` | `() => T` | yes | Initialization function evaluated once per bunja instance. It may call `bunja.use`, `bunja.will`, and `bunja.effect`. Returned value becomes the bunja instance value. |
### Returns
`Bunja` — a bunja definition object (see [`Bunja` class](./bunja-class.md)).
### Usage example
```ts
import { bunja } from "bunja";
const connectionBunja = bunja(() => {
let socket: WebSocket | null = null;
bunja.effect(() => {
socket = new WebSocket("wss://example.com/ws");
return () => socket?.close();
});
return {
send: (message: unknown) => socket?.send(JSON.stringify(message)),
};
});
```
```
--------------------------------
### createBunjaStore signature and config types
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/bunja-store.md
Signature of createBunjaStore and its config type. The function creates a new BunjaStore, sets the wrapInstance function (defaulting to defaultWrapInstanceFn), and returns the store. The config interface accepts an optional wrapInstance function, and WrapInstanceFn is a generic function that takes a dispose callback and returns a value.
```typescript
// bunja/bunja.ts:86
export function createBunjaStore(config?: CreateBunjaStoreConfig): BunjaStore {
const { wrapInstance = defaultWrapInstanceFn } = config ?? {};
const store = new BunjaStore();
store.wrapInstance = wrapInstance;
return store;
}
// bunja/bunja.ts:83
export interface CreateBunjaStoreConfig {
wrapInstance?: WrapInstanceFn;
}
// bunja/bunja.ts:183
export type WrapInstanceFn = (fn: (dispose: () => void) => T) => T;
```
--------------------------------
### useBunja signatures for React and Solid adapters
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/types.md
Shows the useBunja function signatures exported by the React and Solid adapters. The React version accepts a Bunja or BunjaGetRef and optional ScopeValuePairs, returning the value type T. The Solid version accepts MaybeAccessor-wrapped arguments and returns an Accessor. These are the only named exports from each adapter, along with BunjaStoreContext, BunjaStoreProvider, scopeContextMap, bindScope, and createScopeFromContext.
```typescript
// react.ts:78
export function useBunja(
bunja: Bunja | BunjaGetRef,
scopeValuePairs?: ScopeValuePairs,
): T
```
```typescript
// solid.ts:86 — MaybeAccessor = T | Accessor
export function useBunja(
bunja: MaybeAccessor | BunjaGetRef>,
scopeValuePairs?: MaybeAccessor,
): Accessor
```
--------------------------------
### getHook()
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/devtools.md
Function to retrieve the global bunja devtools hook.
```APIDOC
## `getHook()`
### Description
Returns the global `__BUNJA_DEVTOOLS_GLOBAL_HOOK__` object installed by the core library in dev builds, or `undefined` when the hook was not created (e.g., production build).
### Signature
```ts
export function getHook(): BunjaDevtoolsGlobalHook | undefined
```
### Parameters
None.
### Returns
`BunjaDevtoolsGlobalHook | undefined` — the global devtools hook object, or `undefined` if not available.
### Usage Example
```ts
import { getHook } from "react-bunja-devtools/hook";
const hook = getHook();
if (hook) {
const off = hook.on("bunjaInstanceMounted", ({ bunjaInstanceId }) => {
console.log("mounted", bunjaInstanceId);
});
}
```
```
--------------------------------
### Bunja + Jotai Timer State and Component
Source: https://github.com/disjukr/bunja/blob/main/examples/timer/README.md
Shows how Bunja manages component lifetimes and dependency injection while Jotai provides reactive state. The timerBunja defines scoped atoms and derived atoms; the Timer component uses useBunja with scoped dependency injection to render start/stop controls.
```typescript
// Scoped timer state with Jotai integration
export const timerBunja = bunja(() => {
const store = bunja.use(JotaiStoreScope);
// Reactive state with Jotai atoms
const timerAtom = atom({ elapsed: 0, running: false });
// Derived atoms for computed values
const secondsAtom = atom((get) => {
const { elapsed } = get(timerAtom);
return Math.floor(elapsed / 1000).toString().padStart(2, "0");
});
// Lifetime management
bunja.effect(() => () => cleanup());
return { timerAtom, secondsAtom, start, stop, reset };
});
// Component usage
function Timer({ id }: Props) {
const { timerAtom, secondsAtom, start, stop } = useBunja(
timerBunja,
[ItemScope.bind(id)], // Scoped dependency injection
);
const { running } = useAtomValue(timerAtom);
const seconds = useAtomValue(secondsAtom);
return (
{seconds}
{running
?
: }
);
}
```
--------------------------------
### bindScope(scope, context)
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/solid.md
Binds a Solid context as the value source for a scope, unwrapping accessor values at read time.
```APIDOC
## `bindScope(scope, context)`
### Signature
```ts
// bunja/solid.ts:62
export function bindScope(
scope: Scope,
context: Context>,
): void
```
### Description
Binds a Solid context as the value source for a scope. The context type is `Context>` — the bound value may be a plain `T` or an `Accessor`; it is unwrapped with `access()` at read time (bunja/solid.ts:31–34).
### Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `scope` | `Scope` | yes | Scope to bind. |
| `context` | `Context>` | yes | Solid context providing `T` or `Accessor`. |
### Returns
`void`.
### Usage example
```tsx
import { createContext } from "solid-js";
import { createScope } from "bunja";
import { bindScope } from "bunja/solid";
const UrlContext = createContext("https://example.com/");
const UrlScope = createScope();
bindScope(UrlScope, UrlContext);
```
```
--------------------------------
### BunjaStoreContext
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/react.md
A React context that holds a BunjaStore. The default value is a fresh store created at module load, used when no provider is mounted.
```APIDOC
## BunjaStoreContext
### Description
Default context value is a fresh store created at module load. When no provider is mounted, `useBunja` uses this default store.
### Signature
```ts
// bunja/react.ts:35
export const BunjaStoreContext: Context = createContext(
createBunjaStore(),
);
```
### Type
- `Context` - React context object.
### Default Value
- A fresh `BunjaStore` created at module load.
### Usage
This context is used internally by `useBunja` to access the current store. It can be imported and used directly if needed.
```
--------------------------------
### scopeContextMap
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/react.md
A public registry mapping scopes to contexts, populated by bindScope. Exported for advanced/devtools use.
```APIDOC
## scopeContextMap
### Description
Public registry mapping scopes to contexts, populated by `bindScope`. Exported for advanced/devtools use.
### Signature
```ts
// bunja/react.ts:47
export const scopeContextMap: Map, Context> = new Map();
```
### Type
- **Map, Context>** - Maps scope instances to their associated React contexts.
```
--------------------------------
### delayUnmount with custom delay
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/configuration.md
Defers the unmount of a bunja instance by a specified number of milliseconds using setTimeout. The mount function is obtained from store.get, and the returned delayedUnmount function can be called to trigger the deferred disposal.
```TypeScript
import { delayUnmount } from "bunja";
const { mount } = store.get(myBunja, readScope);
const delayedUnmount = delayUnmount(mount, 100); // dispose 100ms after last sub
```
--------------------------------
### Seed a bunja with bunja.withSeed
Source: https://github.com/disjukr/bunja/blob/main/bunja/README.md
Defines a bunja with a seed value. The seed is used only when the bunja instance is first created; later seeds are ignored. The seed can be supplied to store.get, useBunja, bunja.use, or bunja.will.
```ts
const formBunja = bunja.withSeed({ title: "" }, (seed) => {
const titleAtom = atom(seed.title);
return { titleAtom };
});
useBunja({ bunja: formBunja, seed: { title: "Draft" } });
```
--------------------------------
### Getters
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/bunja-class.md
Getter methods for accessing baked state, dependencies, and scopes.
```APIDOC
## Getters
### Description
Getter methods for accessing baked state, dependencies, and scopes.
### `baked`
Returns `boolean` — whether the dependency graph was baked (frozen) at least once. Baking happens automatically at the end of the first `store.get` / `store.prebake` run that evaluates the init function.
### `requiredBunjas`
Returns `AnyBunja[]` (`Bunja[]`) — deduplicated list of bunjas declared through `bunja.use` (direct and transitive).
### `optionalBunjas`
Returns `AnyBunja[]` — deduplicated list of bunjas declared through `bunja.will`, including transitive optional dependencies.
### `requiredBunjaRefs`
Returns `AnyNormalizedBunjaRef[]` — the raw refs (`{ bunja, scopeValuePairs }`) recorded via `bunja.use`. Throws no error even when unbaked.
### `optionalBunjaRefs`
Returns `AnyNormalizedBunjaRef[]` — the raw refs recorded via `bunja.will`.
### `expandedRequiredBunjas`
Returns `AnyBunja[]` — required bunjas ordered topologically (dependencies first). Throws `Error` "Bunja is not baked yet." when unbaked.
### `relatedBunjas`
Returns `AnyBunja[]` — topological order of `requiredBunjas` plus `optionalBunjas` combined. Throws `Error` "Bunja is not baked yet." when unbaked.
### `requiredScopes`
Returns `Scope[]` — the union of scopes this bunja uses directly plus the unbound required scopes of its required bunja refs. A scope bound through a ref's `with` pairs is excluded. Throws `Error` "Bunja is not baked yet." when unbaked.
```
--------------------------------
### Properties
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/bunja-class.md
Public properties of the Bunja class.
```APIDOC
## Properties
### Description
Public properties of the Bunja class.
### Properties
- **id** (`string`) - Globally unique, auto-incremented identifier (`String(Bunja.counter++)`).
- **debugLabel** (`string`) - Mutable dev label; appears in `toString()` output. Default `""`.
- **init** (`(seed: Seed) => T`) - Public read/write init function.
- **defaultSeed** (`Seed`) - Public read/write default seed.
```
--------------------------------
### Define a bunja with bunja and useBunja
Source: https://github.com/disjukr/bunja/blob/main/bunja/README.md
Defines a bunja with a count atom and a lifecycle effect. The effect logs "mounted" when the bunja instance is created and "unmounted" when it is destroyed. Use the useBunja hook to access the bunja instance in a component.
```ts
import { bunja } from "bunja";
import { useBunja } from "bunja/react";
const countBunja = bunja(() => {
const countAtom = atom(0);
bunja.effect(() => {
console.log("mounted");
return () => console.log("unmounted");
});
return { countAtom };
});
function MyComponent() {
const { countAtom } = useBunja(countBunja);
const [count, setCount] = useAtom(countAtom);
// Your component logic here
}
```
--------------------------------
### createScope(hash?)
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/scope.md
Creates a new Scope instance with an optional hash function for deduplication. The hash function maps injected values to a key; values with the same key share a single scope instance.
```APIDOC
## createScope(hash?)
### Description
Creates a new Scope instance. The optional hash function deduplicates injected values: values that hash to the same key share one scope instance.
### Signature
```ts
export function createScope(hash?: HashFn): Scope;
```
### Parameters
- `hash` (HashFn) - Optional - Deduplication function. Different injected values that hash to the same key share one scope instance. Defaults to identity (returns the value itself).
### Returns
`Scope` - A new scope instance with a fresh auto-incremented `id`.
### Usage Example
```ts
import { createScope } from "bunja";
const LocaleScope = createScope();
// hash by value length — "en" and "fr" share an instance, "en-US" is separate
const LocaleByLengthScope = createScope((lang) => lang.length);
```
```
--------------------------------
### toBunjaRenderTree(fiber)
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/devtools.md
Function to convert a React fiber tree into a bunja render tree.
```APIDOC
## `toBunjaRenderTree(fiber)`
### Description
Converts a React fiber tree into a bunja-specific render tree (BRT). Only components that actually call `useBunja` become `component` nodes; adjacent context providers are collapsed and each node gets a pre-order index.
### Signature
```ts
export function toBunjaRenderTree(fiber: Fiber): BrtNode[]
```
### Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `fiber` | `Fiber` (`ReactReconciler.Fiber`) | yes | Root fiber of the subtree to traverse. |
### Returns
`BrtNode[]` — the bunja render tree. `BrtNode` is the union `BrtComponent | BrtContext`; both extend `BrtBase { no: number; name: string; fiber: Fiber }`. `BrtComponent` adds `type: "component"`, `bunjaHooks: BunjaHookValue[]`, `children: BrtNode[]`; `BrtContext` adds `type: "context"`, `children: BrtNode[]`, `contexts: ContextValuePair[]` where `ContextValuePair = [Context, unknown]`.
### Usage Example
```ts
import { toBunjaRenderTree } from "react-bunja-devtools/brt";
import { getFiber } from "./my-fiber-access";
const tree = toBunjaRenderTree(getFiber());
for (const node of tree) {
console.log(node.no, node.name);
}
```
```
--------------------------------
### FiberProvider, FiberContext, FiberScope
Source: https://github.com/disjukr/bunja/blob/main/_autodocs/api-reference/devtools.md
Provides access to the React fiber of a component through a context. FiberProvider is a class component that exposes its own fiber, FiberContext is the React context, and FiberScope is a bunja scope bound to that context.
```APIDOC
## `FiberProvider`, `FiberContext`, `FiberScope`
### Description
These exports allow accessing the React fiber of a component. `FiberProvider` is a class component that makes its own fiber available in the `FiberContext`. `FiberScope` is a bunja scope that can be used with `bunja.use()` to obtain the fiber inside init functions.
### Signatures
```ts
export type Fiber = ReactReconciler.Fiber;
export const FiberContext = React.createContext(null!);
export const FiberScope = createScopeFromContext(FiberContext);
export class FiberProvider extends React.Component {
private _reactInternals!: Fiber;
override render() {
return (
{this.props.children}
);
}
}
```
### Members
| Member | Type | Description |
|--------|------|-------------|
| `Fiber` | type | Re-exported `ReactReconciler.Fiber`. |
| `FiberContext` | `Context` | Context holding the current fiber; created with a null default. |
| `FiberScope` | `Scope` | A bunja scope bound to `FiberContext` — read with `bunja.use(FiberScope)` inside init functions. |
| `FiberProvider` | class | Class component exposing the component's own fiber (`this._reactInternals`) through `FiberContext`. |
### Usage example
```tsx
import { FiberProvider } from "react-bunja-devtools/fiber/provider";
import { bunja } from "bunja";
import { FiberScope } from "react-bunja-devtools/fiber/provider";
const fiberAwareBunja = bunja(() => {
const fiber = bunja.use(FiberScope);
return { fiber };
});
export function Wrapper({ children }: { children: React.ReactNode }) {
return {children};
}
```
```