variable / @typed/navigation

makeNavigationCore

Builds the Navigation service state machine around a provider-specific commit Effect.

Package version
1.0.0-beta.7
Category
Backend history state
Since
1.0.0

Import

import { makeNavigationCore } from "@typed/navigation";

Signatures

export declare const makeNavigationCore: (origin: string, base: string, state: RefSubject.RefSubject<NavigationState, never, never>, commit: (before: BeforeNavigationEvent, runHandlers: (destination: Destination) => Effect.Effect<void>) => Effect.Effect<Destination, NavigationError>) => Effect.Effect<{
    origin: string;
    base: string;
    entries: RefSubject.Computed<readonly {
        readonly id: string;
        readonly key: string;
        readonly url: URL;
        readonly state: unknown;
        readonly sameDocument: boolean;
    }[], never, never>;
    currentEntry: RefSubject.Computed<{
        readonly id: string;
        readonly key: string;
        readonly url: URL;
        readonly state: unknown;
        readonly sameDocument: boolean;
    }, never, never>;
    transition: RefSubject.Filtered<{
        readonly type: "push" | "replace" | "reload" | "traverse";
        readonly from: {
            readonly id: string;
            readonly key: string;
            readonly url: URL;
            readonly state: unknown;
            readonly sameDocument: boolean;
        };
        readonly to: {
            readonly url: URL;
            readonly state: unknown;
            readonly sameDocument: boolean;
            readonly key?: string | undefined;
        };
        readonly info?: unknown;
    }, never, never>;
    canGoBack: RefSubject.Computed<boolean, never, never>;
    canGoForward: RefSubject.Computed<boolean, never, never>;
    navigate: (pathOrUrl: string | URL, options?: NavigationNavigateOptions | undefined) => Effect.Effect<{
        readonly id: string;
        readonly key: string;
        readonly url: URL;
        readonly state: unknown;
        readonly sameDocument: boolean;
    }, NavigationError, never>;
    back: (options?: {
        readonly info?: unknown;
    } | undefined) => Effect.Effect<{
        readonly id: string;
        readonly key: string;
        readonly url: URL;
        readonly state: unknown;
        readonly sameDocument: boolean;
    }, NavigationError, never>;
    forward: (options?: {
        readonly info?: unknown;
    } | undefined) => Effect.Effect<{
        readonly id: string;
        readonly key: string;
        readonly url: URL;
        readonly state: unknown;
        readonly sameDocument: boolean;
    }, NavigationError, never>;
    traverseTo: (key: string, options?: {
        readonly info?: unknown;
    } | undefined) => Effect.Effect<{
        readonly id: string;
        readonly key: string;
        readonly url: URL;
        readonly state: unknown;
        readonly sameDocument: boolean;
    }, NavigationError, never>;
    reload: (options?: NavigationReloadOptions | undefined) => Effect.Effect<{
        readonly id: string;
        readonly key: string;
        readonly url: URL;
        readonly state: unknown;
        readonly sameDocument: boolean;
    }, NavigationError, never>;
    onBeforeNavigation: <R = never, R2 = never>(handler: BeforeNavigationHandler<R, R2>) => Effect.Effect<void, never, R | R2 | Scope.Scope>;
    onNavigation: <R = never, R2 = never>(handler: NavigationHandler<R, R2>) => Effect.Effect<void, never, R | R2 | Scope.Scope>;
    updateCurrentEntry: (options: {
        readonly state: unknown;
    }) => Effect.Effect<{
        readonly id: string;
        readonly key: string;
        readonly url: URL;
        readonly state: unknown;
        readonly sameDocument: boolean;
    }, NavigationError, never>;
}, never, Scope.Scope>;

Why

Browser and memory providers must agree on ordering: publish the transition, run before handlers sequentially, follow redirect/cancel control flow, commit, update state, clear the transition, then run post-commit handlers. Centralizing that protocol prevents backend drift.

Ownership and lifetime

The calling Layer owns the supplied state and returned service. Handler registration captures its Effect context and unregisters when its Scope closes. Redirects are capped at ten; malformed URLs, backend failures, and redirect cycles surface as NavigationError. Interruption clears a still- current transition through normal Effect cleanup.

Examples

import { makeNavigationCore, type NavigationState } from "@typed/navigation/_core"
import type { RefSubject } from "@typed/fx"
import * as Effect from "effect/Effect"
import type { BeforeNavigationEvent, Destination } from "@typed/navigation/model"

declare const state: RefSubject.RefSubject<NavigationState>
declare const commit: (
  event: BeforeNavigationEvent,
  runHandlers: (destination: Destination) => Effect.Effect<void>
) => Effect.Effect<Destination, never>

const NavigationLive = makeNavigationCore("https://example.com", "/", state, commit)

Other public imports

These import paths expose the same declaration. Each page retains its own public name and signature.

Source