### 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}; } ``` ```