diff --git a/src/api/IAppHistory.ts b/src/api/IAppHistory.ts index 0e98ff6..779cc86 100644 --- a/src/api/IAppHistory.ts +++ b/src/api/IAppHistory.ts @@ -9,13 +9,25 @@ export interface IAppHistory extends IHistory { readonly depth: number; readonly isSuppressed: boolean; - cut(): void; + cut(): IAppHistory; findLast(match: string | RegExp | PathPredicate): number; - goHome(to: string, state?: any): void; - goHome(to?: Partial): void; + go(delta: number): IAppHistory; + + goBack(): IAppHistory; + + goForward(): IAppHistory; + + goHome(to: string, state?: any): IAppHistory; + goHome(to?: Partial): IAppHistory; + + push(path: string, state?: any): IAppHistory; + push(location: Partial): IAppHistory; + + replace(path: string, state?: any): IAppHistory; + replace(location: Partial): IAppHistory; suppress(): UnregisterCallback; - suppress(action: WithSuppressionAction): void; + suppress(action: WithSuppressionAction): IAppHistory; } diff --git a/src/createAppHistory.ts b/src/createAppHistory.ts index 58be7d3..4c21fe9 100644 --- a/src/createAppHistory.ts +++ b/src/createAppHistory.ts @@ -18,7 +18,8 @@ import { import { Blocker } from "./Blocker"; import { initialMetaState } from "./initialMetaState"; import { isWrappedLocation } from "./isWrappedLocation"; -import { makeNavigationFunc } from "./makeNavigationFunc"; +import { nextLocation } from "./nextLocation"; +import { nextState } from "./nextState"; import { Notifier } from "./Notifier"; import { Suppressor } from "./Suppressor"; import { unwrapLocation } from "./unwrapLocation"; @@ -40,9 +41,6 @@ export function createAppHistory(options: IAppHistoryOptions = {}): IAppHistory const notifier = new Notifier(source, suppressor); const blocker = new Blocker(source, suppressor); - const push = makeNavigationFunc(source, PUSH, cacheLimit); - const replace = makeNavigationFunc(source, REPLACE, cacheLimit); - const internalFindLast = ( match: string | RegExp | PathPredicate, ): IInternalFindLastResult => { @@ -198,6 +196,48 @@ export function createAppHistory(options: IAppHistoryOptions = {}): IAppHistory isAfterDirtyCut = true; }; + const push = ( + pathOrDescriptor: string | Partial, + state?: any, + ): IAppHistory => { + if (typeof pathOrDescriptor === "string") { + source.push(pathOrDescriptor, nextState(source, PUSH, state, cacheLimit)); + } else { + source.push(nextLocation(source, PUSH, pathOrDescriptor, cacheLimit)); + } + + return history; + }; + + const replace = ( + pathOrDescriptor: string | Partial, + state?: any, + ): IAppHistory => { + if (typeof pathOrDescriptor === "string") { + source.replace(pathOrDescriptor, nextState(source, REPLACE, state, cacheLimit)); + } else { + source.replace(nextLocation(source, REPLACE, pathOrDescriptor, cacheLimit)); + } + + return history; + }; + + function suppress(): UnregisterCallback; + function suppress(action: WithSuppressionAction): IAppHistory; + function suppress(action?: WithSuppressionAction): UnregisterCallback | IAppHistory { + if (typeof action === "undefined") { + return suppressor.suppress(); + } else { + const resume = suppressor.suppress(); + try { + action(history); + } finally { + resume(); + } + return history; + } + } + const history: IAppHistory = { get cacheLimit(): number { return cacheLimit; @@ -223,12 +263,9 @@ export function createAppHistory(options: IAppHistoryOptions = {}): IAppHistory return exposedLocation; }, - push, - - replace, - - cut(): void { + cut(): IAppHistory { const resume = suppressor.suppress(); + try { if (canMakeCleanCut()) { makeCleanCut(); @@ -238,6 +275,8 @@ export function createAppHistory(options: IAppHistoryOptions = {}): IAppHistory } finally { resume(); } + + return history; }, block(prompt?: boolean | string | BlockPrompt): UnregisterCallback { @@ -262,19 +301,25 @@ export function createAppHistory(options: IAppHistoryOptions = {}): IAppHistory return result.delta; }, - go(delta: number): void { + go(delta: number): IAppHistory { source.go(delta); + return history; }, - goBack(): void { + goBack(): IAppHistory { source.goBack(); + return history; }, - goForward(): void { + goForward(): IAppHistory { source.goForward(); + return history; }, - goHome(to?: string | Partial, state?: any) { + goHome( + to?: string | Partial, + state?: any, + ): IAppHistory { if (isWrappedLocation(source.location)) { const meta = source.location.state.meta; if (meta.depth > 0) { @@ -297,25 +342,19 @@ export function createAppHistory(options: IAppHistoryOptions = {}): IAppHistory if (typeof to !== "undefined") { replace(to, state); } + + return history; }, listen(listener: NavigationListener): UnregisterCallback { return notifier.listen(listener); }, - suppress(action?: WithSuppressionAction): UnregisterCallback { - if (typeof action === "undefined") { - return suppressor.suppress(); - } else { - const resume = suppressor.suppress(); - try { - action(history); - } finally { - resume(); - } - return resume; - } - }, + push, + + replace, + + suppress, }; Object.freeze(history); diff --git a/src/makeNavigationFunc.ts b/src/makeNavigationFunc.ts deleted file mode 100644 index b93f91b..0000000 --- a/src/makeNavigationFunc.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { IHistory, ILocation, PUSH, REPLACE } from "./api"; -import { nextLocation } from "./nextLocation"; -import { nextState } from "./nextState"; - -export type CreatableNavigationAction = - typeof PUSH | - typeof REPLACE; - -export type NavigationFunc = ( - pathOrDescriptor: string | Partial, - state?: any, -) => void; - -export function makeNavigationFunc( - source: IHistory, - action: CreatableNavigationAction, - cacheLimit: number, -): NavigationFunc { - let sourceFunc = action === PUSH ? source.push : source.replace; - sourceFunc = sourceFunc.bind(source); - - return (pathOrDescriptor: string | ILocation, state?: any) => { - if (typeof pathOrDescriptor === "string") { - sourceFunc(pathOrDescriptor, nextState(source, action, state, cacheLimit)); - } else { - sourceFunc(nextLocation(source, action, pathOrDescriptor, cacheLimit)); - } - }; -} diff --git a/src/nextLocation.ts b/src/nextLocation.ts index d9b209f..b6fade5 100644 --- a/src/nextLocation.ts +++ b/src/nextLocation.ts @@ -4,9 +4,9 @@ import { nextState } from "./nextState"; export function nextLocation( source: IHistory, action: NavigationAction, - location: ILocation, + location: Partial, cacheLimit: number, -): ILocation { +): Partial> { return { hash: location.hash, key: location.key,