@kitbag/router 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/components/routerLink.d.ts +4 -4
  2. package/dist/components/routerProgress.d.ts +18 -0
  3. package/dist/components/routerProgressBar.d.ts +12 -0
  4. package/dist/compositions/useLink.d.ts +2 -2
  5. package/dist/compositions/useLink.spec-d.d.ts +1 -0
  6. package/dist/compositions/useNavigation.browser.spec.d.ts +1 -0
  7. package/dist/compositions/useNavigation.d.ts +5 -0
  8. package/dist/errors/contextRedirectError.d.ts +1 -2
  9. package/dist/errors/unreachableRouteError.d.ts +7 -0
  10. package/dist/kitbag-router.js +2100 -1711
  11. package/dist/kitbag-router.umd.cjs +2 -2
  12. package/dist/main.d.ts +25 -1
  13. package/dist/main.spec-d.d.ts +1 -0
  14. package/dist/services/addAlias.d.ts +19 -0
  15. package/dist/services/addAlias.spec-d.d.ts +1 -0
  16. package/dist/services/addAlias.spec.d.ts +1 -0
  17. package/dist/services/createCanonicalUrl.d.ts +14 -0
  18. package/dist/services/createCanonicalUrl.spec.d.ts +1 -0
  19. package/dist/services/createDataStore.d.ts +4 -0
  20. package/dist/services/createNavigationProgress.d.ts +49 -0
  21. package/dist/services/createNavigationProgress.spec.d.ts +1 -0
  22. package/dist/services/createNavigationSignals.d.ts +17 -0
  23. package/dist/services/createNavigationSignals.spec.d.ts +1 -0
  24. package/dist/services/createResolvedRoute.d.ts +10 -1
  25. package/dist/services/createRouteValueStore.d.ts +4 -0
  26. package/dist/services/createRouterAssets.d.ts +19 -0
  27. package/dist/services/createRouterHooks.d.ts +7 -2
  28. package/dist/services/createUniqueIdSequence.d.ts +0 -1
  29. package/dist/services/getInitialUrl.d.ts +2 -1
  30. package/dist/services/getMatchesForUrl.d.ts +4 -0
  31. package/dist/services/getRoutesForRouter.d.ts +3 -2
  32. package/dist/services/routeRegex.d.ts +6 -1
  33. package/dist/services/updateResolvedRoute.d.ts +7 -0
  34. package/dist/services/updateResolvedRoute.spec.d.ts +1 -0
  35. package/dist/services/withRouteMethods.d.ts +3 -3
  36. package/dist/tests/loaderPrefetch.browser.spec.d.ts +1 -0
  37. package/dist/tests/navigationProgress.spec.d.ts +1 -0
  38. package/dist/types/addAlias.d.ts +79 -0
  39. package/dist/types/callbackContext.d.ts +0 -5
  40. package/dist/types/createRouteOptions.d.ts +6 -2
  41. package/dist/types/hooks.d.ts +9 -5
  42. package/dist/types/navigation.d.ts +36 -0
  43. package/dist/types/prefetch.d.ts +6 -1
  44. package/dist/types/props.d.ts +1 -0
  45. package/dist/types/redirects.d.ts +4 -0
  46. package/dist/types/resolved.d.ts +22 -2
  47. package/dist/types/route.d.ts +2 -0
  48. package/dist/types/routeAlias.d.ts +41 -0
  49. package/dist/types/routeCallbackContext.d.ts +1 -0
  50. package/dist/types/routeWithMethods.d.ts +3 -2
  51. package/dist/types/routerLink.d.ts +1 -1
  52. package/dist/types/routerNavigationInternal.d.ts +29 -0
  53. package/dist/types/routerRoute.d.ts +5 -1
  54. package/dist/utilities/components.d.ts +6 -2
  55. package/dist/utilities/getRegexMatcher.d.ts +1 -0
  56. package/dist/utilities/getRegexMatcher.spec.d.ts +1 -0
  57. package/dist/utilities/percentEncoding.d.ts +10 -0
  58. package/dist/utilities/percentEncoding.spec.d.ts +1 -0
  59. package/package.json +6 -6
  60. package/dist/services/createNavigationIds.d.ts +0 -6
  61. /package/dist/{services/createNavigationIds.spec.d.ts → components/routerProgress.browser.spec.d.ts} +0 -0
@@ -3,11 +3,25 @@ import { LastInArray } from './utilities';
3
3
  import { ExtractRouteStateParamsAsOptional } from './state';
4
4
  import { UrlString } from './urlString';
5
5
  import { UrlParamsReading } from './url';
6
- import { GetTitleCallback } from './routeTitle';
6
+ import { GetRouteTitle, GetTitleCallback } from './routeTitle';
7
+ import { Hooks } from '../models/hooks';
7
8
  /**
8
9
  * The match a route resolved to, which is the last of its matches. Falls back to the wide match type when
9
10
  * the matches are not a concrete tuple, so an unregistered router stays assignable.
10
11
  */
12
+ export declare const IS_RESOLVED_ROUTE_SYMBOL: unique symbol;
13
+ /**
14
+ * A type guard for determining if a value is a ResolvedRoute.
15
+ * @param value - The value to check.
16
+ * @returns `true` if the value is a ResolvedRoute, otherwise `false`.
17
+ * @group Type Guards
18
+ */
19
+ export declare function isResolvedRoute(value: unknown): value is ResolvedRoute & ResolvedRouteInternal;
20
+ export type ResolvedRouteInternal = {
21
+ [IS_RESOLVED_ROUTE_SYMBOL]: true;
22
+ hooks: Hooks[];
23
+ getRouteTitle: GetRouteTitle;
24
+ };
11
25
  type MatchedRoute<TMatches> = LastInArray<TMatches, CreatedRouteOptions> extends infer TMatched ? unknown extends TMatched ? CreatedRouteOptions : TMatched : never;
12
26
  /**
13
27
  * Represents a route that the router has matched to current browser location.
@@ -40,9 +54,15 @@ export type ResolvedRoute<TRoute extends Route = Route> = Readonly<{
40
54
  */
41
55
  state: ExtractRouteStateParamsAsOptional<TRoute['state']>;
42
56
  /**
43
- * String value of the resolved URL.
57
+ * String value of the resolved URL. When the route was matched through an alias this is the alias url,
58
+ * so navigating to it again stays where the user is.
44
59
  */
45
60
  href: UrlString;
61
+ /**
62
+ * String value of the route's own URL, built from its path and the resolved params. The same as `href`
63
+ * unless the route was matched through an alias.
64
+ */
65
+ canonical: UrlString;
46
66
  /**
47
67
  * Query value of the route.
48
68
  */
@@ -12,6 +12,7 @@ import { Hooks } from '../models/hooks';
12
12
  import { RouteRedirect } from './redirects';
13
13
  import { RouteViews } from './routeViews';
14
14
  import { LoadersDataReturnType, RouteLoaders } from './routeLoaders';
15
+ import { RouteAlias } from './routeAlias';
15
16
  export declare const IS_ROUTE_SYMBOL: unique symbol;
16
17
  export declare function isRoute(value: unknown): value is Route & RouteInternal;
17
18
  export type RouteInternal = {
@@ -20,6 +21,7 @@ export type RouteInternal = {
20
21
  hooks: Hooks[];
21
22
  redirect: RouteRedirect;
22
23
  getTitle: GetRouteTitle;
24
+ aliases: RouteAlias[];
23
25
  };
24
26
  /**
25
27
  * Represents an immutable array of Route instances. Return value of `createRoute`, expected param for `createRouter`.
@@ -0,0 +1,41 @@
1
+ import { Url } from './url';
2
+ /**
3
+ * What an alias transform is given: the url that matched and the params the alias pattern parsed from it.
4
+ *
5
+ * @template TParams - The alias's own params, typed by the alias pattern.
6
+ */
7
+ export type AliasTransformContext<TParams = Record<string, unknown>> = {
8
+ /**
9
+ * The url that matched the alias.
10
+ */
11
+ url: string;
12
+ /**
13
+ * The params the alias pattern parsed from the url, typed by the alias's own params rather than the
14
+ * route's.
15
+ */
16
+ params: TParams;
17
+ };
18
+ /**
19
+ * Maps what an alias matched into the params the route declares. Runs synchronously during matching. Any
20
+ * param the route declares that the alias pattern does not carry must be supplied here.
21
+ *
22
+ * @template TParams - The alias's own params.
23
+ * @template TRouteParams - The params of the route the alias belongs to.
24
+ */
25
+ export type AliasTransform<TParams = Record<string, unknown>, TRouteParams = Record<string, unknown>> = (context: AliasTransformContext<TParams>) => TRouteParams;
26
+ /**
27
+ * An alias combined with every ancestor into a single url the router can match, plus the transform that
28
+ * maps everything that url parsed into the route's params. The transform is the composition of each
29
+ * level's own transform, so it stays local to the segment each level aliased.
30
+ */
31
+ export type RouteAlias = {
32
+ url: Url;
33
+ transform: (url: string, params: Record<string, unknown>) => Record<string, unknown>;
34
+ };
35
+ /**
36
+ * An alias a url matched and the params that alias parsed from it.
37
+ */
38
+ export type RouteAliasMatch = {
39
+ url: RouteAlias['url'];
40
+ params: Record<string, unknown>;
41
+ };
@@ -16,6 +16,7 @@ export type RouteCallbackContext<TRoute extends Route> = {
16
16
  push: RouterPush<[TRoute] | RouteContextToRoute<TRoute['context']>>;
17
17
  replace: RouterReplace<[TRoute] | RouteContextToRoute<TRoute['context']>>;
18
18
  update: RouteUpdate<ResolvedRoute<TRoute>>;
19
+ signal: AbortSignal;
19
20
  parent: RouteCallbackParent<TRoute>;
20
21
  };
21
22
  /**
@@ -1,3 +1,4 @@
1
+ import { RouteAddAlias } from './addAlias';
1
2
  import { RouteAddLoader } from './addLoader';
2
3
  import { RouteAddView } from './addView';
3
4
  import { InternalRouteHooks } from './hooks';
@@ -6,11 +7,11 @@ import { CreatedRouteOptions, Route } from './route';
6
7
  import { RouteSetTitle } from './routeTitle';
7
8
  import { Url } from './url';
8
9
  /**
9
- * A route plus every chainable/available method: addView, addLoader, hooks, redirects, and title. The type
10
+ * A route plus every chainable/available method: addView, addLoader, addAlias, hooks, redirects, and title. The type
10
11
  * level counterpart to `withRouteMethods`.
11
12
  *
12
13
  * Takes the url and matches rather than an assembled route so that adding a view or a loader can rebuild
13
14
  * from them directly. Taking the route would mean re-deriving the url from it on every call, and that
14
15
  * reference is what made chained calls nest one inside the last.
15
16
  */
16
- export type RouteWithMethods<TUrl extends Url = Url, TMatches extends CreatedRouteOptions[] = CreatedRouteOptions[]> = Route<TUrl, TMatches> & RouteAddView<TUrl, TMatches> & RouteAddLoader<TUrl, TMatches> & InternalRouteHooks<Route<TUrl, TMatches>, Route<TUrl, TMatches>['context']> & RouteRedirects<Route<TUrl, TMatches>> & RouteSetTitle<Route<TUrl, TMatches>>;
17
+ export type RouteWithMethods<TUrl extends Url = Url, TMatches extends CreatedRouteOptions[] = CreatedRouteOptions[]> = Route<TUrl, TMatches> & RouteAddView<TUrl, TMatches> & RouteAddLoader<TUrl, TMatches> & RouteAddAlias<TUrl, TMatches> & InternalRouteHooks<Route<TUrl, TMatches>, Route<TUrl, TMatches>['context']> & RouteRedirects<Route<TUrl, TMatches>> & RouteSetTitle<Route<TUrl, TMatches>>;
@@ -3,7 +3,7 @@ import { UrlString } from './urlString';
3
3
  import { ResolvedRoute } from './resolved';
4
4
  import { Router } from './router';
5
5
  import { RouterPushOptions } from './routerPush';
6
- export type ToCallback<TRouter extends Router> = (resolve: TRouter['resolve']) => ResolvedRoute | UrlString | undefined;
6
+ export type ToCallback<TRouter extends Router> = (resolve: TRouter['resolve']) => ResolvedRoute | UrlString;
7
7
  export type RouterLinkProps<TRouter extends Router> = RouterPushOptions & {
8
8
  /**
9
9
  * The url string to navigate to or a callback that returns a url string
@@ -0,0 +1,29 @@
1
+ import { ResolvedRoute } from './resolved';
2
+ import { Routes } from './route';
3
+ import { RedirectStatus } from './router';
4
+ import { RouterPush, RouterPushOptions } from './routerPush';
5
+ import { RouterReplace, RouterReplaceOptions } from './routerReplace';
6
+ import { RouteParamsByKey } from './routeWithParams';
7
+ import { RoutesName } from './routesMap';
8
+ import { RouteStateByName } from './state';
9
+ import { UrlString } from './urlString';
10
+ /**
11
+ * Push and replace as the router itself calls them, which may carry the status a server responds with for
12
+ * the redirect. The router exposes {@link RouterPush} and {@link RouterReplace} instead.
13
+ */
14
+ export type RouterPushOptionsInternal<TState = unknown> = RouterPushOptions<TState> & {
15
+ redirectStatus?: RedirectStatus;
16
+ };
17
+ export type RouterReplaceOptionsInternal<TState = unknown> = RouterReplaceOptions<TState> & {
18
+ redirectStatus?: RedirectStatus;
19
+ };
20
+ export type RouterPushInternal<TRoutes extends Routes> = RouterPush<TRoutes> & {
21
+ <TSource extends RoutesName<TRoutes>>(name: TSource, params: RouteParamsByKey<TRoutes, TSource> | undefined, options: RouterPushOptionsInternal<RouteStateByName<TRoutes, TSource>>): Promise<void>;
22
+ (route: ResolvedRoute, options: RouterPushOptionsInternal): Promise<void>;
23
+ (url: UrlString, options: RouterPushOptionsInternal): Promise<void>;
24
+ };
25
+ export type RouterReplaceInternal<TRoutes extends Routes> = RouterReplace<TRoutes> & {
26
+ <TSource extends RoutesName<TRoutes>>(name: TSource, params: RouteParamsByKey<TRoutes, TSource> | undefined, options: RouterReplaceOptionsInternal<RouteStateByName<TRoutes, TSource>>): Promise<void>;
27
+ (route: ResolvedRoute, options: RouterReplaceOptionsInternal): Promise<void>;
28
+ (url: UrlString, options: RouterReplaceOptionsInternal): Promise<void>;
29
+ };
@@ -29,9 +29,13 @@ export type RouterRoute<TRoute extends ResolvedRoute = ResolvedRoute> = {
29
29
  */
30
30
  readonly update: RouteUpdate<TRoute>;
31
31
  /**
32
- * String value of the resolved URL.
32
+ * String value of the resolved URL. When the route was matched through an alias this is the alias url.
33
33
  */
34
34
  readonly href: TRoute['href'];
35
+ /**
36
+ * String value of the route's own URL. The same as `href` unless the route was matched through an alias.
37
+ */
38
+ readonly canonical: TRoute['canonical'];
35
39
  /**
36
40
  * Title of the route.
37
41
  */
@@ -10,9 +10,13 @@ export declare function isAsyncComponent(component: Component): component is Com
10
10
  * Decides which of a route's views to load.
11
11
  */
12
12
  export type AsyncComponentFilter = (match: CreatedRouteOptions, view: RouteView<unknown>) => boolean;
13
+ /**
14
+ * The async components a route renders, or only those the filter keeps.
15
+ */
16
+ export declare function getAsyncComponents(route: ResolvedRoute, filter?: AsyncComponentFilter): ComponentWithAsyncLoader[];
13
17
  /**
14
18
  * Loads the async components a route renders, or only those the filter keeps, so they are ready to render
15
- * synchronously.
19
+ * synchronously. Each load is reported on its own.
16
20
  */
17
- export declare function loadAsyncComponents(route: ResolvedRoute, filter?: AsyncComponentFilter): Promise<unknown>;
21
+ export declare function loadAsyncComponents(route: ResolvedRoute, filter?: AsyncComponentFilter): Promise<unknown>[];
18
22
  export {};
@@ -0,0 +1 @@
1
+ export declare function getRegexMatcher(regex: RegExp): RegExp;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Encodes the characters in a param value that would otherwise be read as syntax: a percent sign starts
3
+ * an escape, and square brackets mark a param. Everything else is left for the url to encode.
4
+ */
5
+ export declare function encodeParamValue(value: string): string;
6
+ /**
7
+ * Decodes a param value taken from a url. A malformed escape is kept as written rather than thrown on,
8
+ * and a missing value stays missing.
9
+ */
10
+ export declare function decodeParamValue(value: string | undefined): string | undefined;
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kitbag/router",
3
3
  "private": false,
4
- "version": "0.26.0",
4
+ "version": "0.27.0",
5
5
  "license": "MIT",
6
6
  "bugs": {
7
7
  "url": "https://github.com/kitbagjs/router/issues"
@@ -46,20 +46,20 @@
46
46
  "@kitbag/eslint-config": "1.0.6",
47
47
  "@vitejs/plugin-vue": "^6.0.8",
48
48
  "@vue/language-core": "^3.3.11",
49
- "@vue/test-utils": "^2.5.0",
50
- "arktype": "^2.2.3",
49
+ "@vue/test-utils": "^2.5.1",
50
+ "arktype": "^2.2.5",
51
51
  "eslint": "^9.39.5",
52
52
  "globals": "^17.12.0",
53
- "happy-dom": "^20.14.3",
53
+ "happy-dom": "^20.14.5",
54
54
  "typedoc": "^0.28.20",
55
- "typedoc-plugin-markdown": "^4.13.0",
55
+ "typedoc-plugin-markdown": "^4.13.1",
56
56
  "typedoc-vitepress-theme": "^1.1.4",
57
57
  "typescript": "^6.0.3",
58
58
  "valibot": "^1.0.0",
59
59
  "vite": "^8.2.0",
60
60
  "vite-plugin-dts": "^5.0.3",
61
61
  "vitepress": "^1.6.4",
62
- "vitest": "^5.0.0",
62
+ "vitest": "^5.0.1",
63
63
  "vue-tsc": "^3.3.8",
64
64
  "zod": "4.0.0"
65
65
  },
@@ -1,6 +0,0 @@
1
- export type NavigationIds = {
2
- getNavigationId: () => string;
3
- isCurrentNavigationId: (id: string) => boolean;
4
- stopNavigationIds: () => void;
5
- };
6
- export declare function createNavigationIds(): NavigationIds;