API Reference
InitializationTask
A single task — one stage, or one member of a parallel([...]) stage.
interface InitializationTask<S extends StateMap = StateMap> {
id: string;
label?: string;
critical?: boolean; // default true
retry?: number; // total attempts, default 1
retryDelay?: number | ((attempt: number) => number); // ms, default 0
timeout?: number; // ms, per attempt
condition?: (context: InitializationContext<S>) => boolean | Promise<boolean>;
run: (context: InitializationContext<S>) => void | Promise<void>;
}| Field | Type | Description |
|---|---|---|
id | string | Uniquely identifies the task — used for tracking and error reporting. Must be unique across the whole tasks list. |
label | string | Human-readable name for UI (splash/error screens), surfaced on TaskSnapshot. Falls back to id if unset. |
critical | boolean | Defaults to true. false lets the task fail without halting the run — see Concepts. |
retry | number | Total attempts (default 1, no retry). |
retryDelay | number | ((attempt) => number) | Delay in ms before each retry (not before the first attempt, not after the last). A function receives the 1-based attempt that just failed. Defaults to 0. |
timeout | number | Max ms per attempt before it’s treated as a failure (InitializerTimeoutError) — trips context.signal for that attempt. |
condition | (context) => boolean | Promise<boolean> | Returning false skips the task — the only source of 'skipped'. A throw is treated as a failure. |
run | (context) => void | Promise<void> | The task’s work. May be synchronous. |
InitializationContext
Passed to every run/condition call.
interface InitializationContext<S extends StateMap = StateMap> {
signal: AbortSignal;
state: InitializationState<S>;
}InitializationState
The shared key/value bag at context.state, one instance per run — also readable after
the run completes, via InitializerHandle.getState() / useInitializer().getState() /
the onComplete event.
interface InitializationState<S extends StateMap = StateMap> {
get<K extends keyof S>(key: K): S[K] | undefined;
set<K extends keyof S>(key: K, value: S[K]): void;
has(key: keyof S): boolean;
}Parameterize with a StateMap (e.g. InitializationState<{ user: User }>, inferred
automatically from InitializationTask<{ user: User }> /
createInitializer<{ user: User }>() / <Initializer<{ user: User }>>) to get
get/set checked and inferred per key instead of unknown-typed.
parallel()
function parallel<S extends StateMap = StateMap>(
tasks: InitializationTask<S>[],
options?: { concurrency?: number },
): ParallelGroup<S>;Wraps tasks into a single stage that runs them all concurrently — the run waits for the
whole stage to settle before starting the next one. concurrency caps how many of the
stage’s tasks run at once (e.g. to avoid firing 50 simultaneous requests); omit it for no
cap.
<Initializer>
import { Initializer } from '@lamstack/react-initializer';
<Initializer
tasks={tasks}
splashScreen={MySplashScreen}
errorScreen={MyErrorScreen}
cancelledScreen={MyCancelledScreen}
minSplashDuration={300}
onTaskStart={(task) => logger.info(`Starting ${task.id}`)}
onTaskFailed={(task, error) => logger.error(task.id, error)}
>
<App />
</Initializer>;| Prop | Type | Description |
|---|---|---|
tasks | TaskEntry<S>[] | Required. InitializationTasks and/or parallel([...]) stages, run in order. Only read at the moment a run (re)starts — mount, or after retry(). |
splashScreen | ComponentType<SplashScreenProps> | Shown while any task is pending/running. Defaults to a plain built-in screen. |
errorScreen | ComponentType<ErrorScreenProps> | Shown when a critical task fails. Defaults to a plain built-in screen with a “Retry” button. |
cancelledScreen | ComponentType<CancelledScreenProps> | Shown when the run was cancelled via abort(). Defaults to a plain built-in screen with a “Retry” button. |
minSplashDuration | number | Keeps the splash up for at least this many ms once shown, even if the run settles sooner. Defaults to 0. |
children | ReactNode | Rendered once every task has settled successfully (status === 'completed'). |
onTaskStart | (task) => void | Fires when a task begins running (after its condition check passes). |
onTaskComplete | (task) => void | Fires when a task succeeds. |
onTaskFailed | (task, error) => void | Fires when a task’s final attempt fails (after retries are exhausted). |
onComplete | (state: InitializationState<S>) => void | Fires once, when every task has settled with no critical failure — with the final shared state. |
onError | (error: InitializationError) => void | Fires once, with the first critical failure that halted the run. |
onAbort | () => void | Fires when abort() is called manually (not from a critical failure). |
SplashScreenProps
interface SplashScreenProps {
progress: number; // 0-100
tasks: TaskSnapshot[];
}ErrorScreenProps
interface ErrorScreenProps {
error: InitializationError;
retry: () => void;
}CancelledScreenProps
interface CancelledScreenProps {
retry: () => void;
}useInitializer()
Must be called from a component rendered under <Initializer>.
const { status, progress, tasks, error, retry, abort, getState } = useInitializer<S>();| Member | Type | Description |
|---|---|---|
status | InitializationStatus | 'idle' | 'running' | 'completed' | 'failed' | 'cancelled'. |
progress | number | Percentage of tasks that have settled (0-100). |
tasks | TaskSnapshot[] | Per-task status, in declaration order. |
error | InitializationError | null | The critical failure that halted the run, if any. |
retry | () => void | Restarts the whole run from the beginning (a fresh run, fresh state, fresh AbortController). |
abort | () => void | Aborts the run in progress. |
getState | () => InitializationState<S> | The shared state bag. Only reliably complete once status is 'completed'. |
createInitializer()
The framework-independent core, used by <Initializer> internally and usable directly
outside of React — also re-exported from @lamstack/react-initializer for convenience.
import { createInitializer } from '@lamstack/initializer';
const initializer = createInitializer({ tasks, onError: reportToSentry });
const unsubscribe = initializer.subscribe(() => {
console.log(initializer.getSnapshot());
});
await initializer.run();
// later:
console.log(initializer.getState().get('user'));
initializer.abort();
unsubscribe();| Member | Signature | Description |
|---|---|---|
run | () => Promise<void> | Starts the run. tasks is validated synchronously inside createInitializer() itself — a duplicate id throws immediately, before run() is ever called. Calling run() more than once is a no-op. |
abort | () => void | Aborts the run in progress. |
getSnapshot | () => InitializerSnapshot | The current { status, progress, tasks, error }. |
getState | () => InitializationState<S> | The shared state bag. Only reliably complete once getSnapshot().status is 'completed'. |
subscribe | (listener: () => void) => () => void | Registers a listener called on every snapshot change; returns an unsubscribe function. |
Other types
type InitializationStatus = 'idle' | 'running' | 'completed' | 'failed' | 'cancelled';
type InitializationTaskStatus =
| 'pending'
| 'running'
| 'completed'
| 'failed'
| 'skipped'
| 'cancelled';
interface TaskSnapshot {
id: string;
label?: string;
status: InitializationTaskStatus;
critical: boolean;
error?: unknown; // set for BOTH critical and non-critical failures
durationMs?: number; // set once settled as 'completed' or 'failed'
}
interface InitializationError {
taskId: string;
error: unknown;
}
interface InitializerSnapshot {
status: InitializationStatus;
progress: number;
tasks: TaskSnapshot[];
error: InitializationError | null;
}InitializerTimeoutError (extends Error) is thrown internally when a task exceeds its
timeout — check error.error instanceof InitializerTimeoutError in onTaskFailed/
onError to distinguish a timeout from any other failure.
Dev-mode diagnostics
Outside NODE_ENV=production, createInitializer logs a console.warn for a task with
retry but no timeout, and for a critical: false task placed in its own sequential
stage (its failure won’t block the run, but the next stage still waits for it to settle).
Call checkTasks(tasks) yourself to get these as a plain string[] — e.g. to assert on
in a test, or run as a lint script — instead of relying on the console.