Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/hot-pugs-worry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'sv-router': patch
---

correctly handle cancellation of navigations, return Error in navigate
11 changes: 7 additions & 4 deletions src/create-router.svelte.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
stripBase,
updatedLocation,
} from './helpers/utils.js';
import { Navigation } from './navigation.js';
import { syncSearchParams } from './search-params.svelte.js';

/** @type {import('./index.d.ts').Routes} */
Expand Down Expand Up @@ -114,11 +115,12 @@ export function createRouter(r) {
* params?: Record<string, string>;
* search?: import('./index.d.ts').Search;
* }} options
* @returns Promise<Error>
*/
function navigate(path, options = {}) {
if (typeof path === 'number') {
globalThis.history.go(path);
return;
return new Navigation(`History entry: ${path}`);
}

path = constructPath(path, options.params);
Expand All @@ -128,6 +130,7 @@ function navigate(path, options = {}) {
options.hash = '#' + options.hash;
}
onNavigate(path, options);
return new Navigation(`${path}${options?.search ?? ''}${options?.hash ?? ''}`);
}

/**
Expand All @@ -142,7 +145,7 @@ export async function onNavigate(path, options = {}) {
navigationIndex++;
const currentNavigationIndex = navigationIndex;

let matchPath = getMatchPath(path);
const matchPath = getMatchPath(path);
const { match, layouts, hooks, meta: newMeta, params: newParams } = matchRoute(matchPath, routes);

const search = parseSearch(options.search);
Expand Down Expand Up @@ -176,7 +179,7 @@ export async function onNavigate(path, options = {}) {
}
if (
navigationIndex !== currentNavigationIndex ||
(fromBeforeLoadHook && pendingNavigationIndex + 1 !== currentNavigationIndex)
(fromBeforeLoadHook && pendingNavigationIndex !== currentNavigationIndex)
) {
return;
}
Expand Down Expand Up @@ -253,7 +256,7 @@ export function onGlobalClick(event) {

event.preventDefault();
const { replace, state, scrollToTop, viewTransition } = anchor.dataset;
onNavigate(path, {
void onNavigate(path, {
replace: replace === '' || replace === 'true',
search: url.search,
state,
Expand Down
8 changes: 7 additions & 1 deletion src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ export type IsActiveLink = Action<
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface RouteMeta {}

export class Navigation extends Error {
constructor(target: string);
}

export type RouterApi<T extends Routes> = {
/**
* Construct a path while ensuring type safety.
Expand Down Expand Up @@ -139,8 +143,10 @@ export type RouterApi<T extends Routes> = {
*
* @param route The route to navigate to.
* @param options The navigation options.
*
* Returns an Error for use with `throw navigate(...)` inside hooks.
*/
navigate<U extends Path<T>>(...args: NavigateArgs<U>): void;
navigate<U extends Path<T>>(...args: NavigateArgs<U>): Error;

/**
* Will return `true` if the given path is active.
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export { isActiveLink } from './actions.svelte.js';
export { createRouter } from './create-router.svelte.js';
export { serializeSearch } from './helpers/utils.js';
export { Navigation } from './navigation.js';
export { default as Router } from './Router.svelte';
export { searchParams } from './search-params.svelte.js';
9 changes: 9 additions & 0 deletions src/navigation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export class Navigation extends Error {
constructor(
/** @type {string} target */
target,
) {
super(`Navigating to: ${target}`);
this.name = 'Redirect';
}
}