# makeNavigationCore

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

## Signatures

```ts
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

```ts
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)
```
