@esmx/router 3.0.0-rc.17 → 3.0.0-rc.19

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 (155) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +70 -0
  3. package/README.zh-CN.md +70 -0
  4. package/dist/error.d.ts +23 -0
  5. package/dist/error.mjs +61 -0
  6. package/dist/increment-id.d.ts +7 -0
  7. package/dist/increment-id.mjs +11 -0
  8. package/dist/index.d.ts +5 -3
  9. package/dist/index.mjs +14 -3
  10. package/dist/index.test.mjs +8 -0
  11. package/dist/location.d.ts +15 -0
  12. package/dist/location.mjs +53 -0
  13. package/dist/location.test.d.ts +8 -0
  14. package/dist/location.test.mjs +370 -0
  15. package/dist/matcher.d.ts +3 -0
  16. package/dist/matcher.mjs +44 -0
  17. package/dist/matcher.test.mjs +1492 -0
  18. package/dist/micro-app.d.ts +18 -0
  19. package/dist/micro-app.dom.test.d.ts +1 -0
  20. package/dist/micro-app.dom.test.mjs +532 -0
  21. package/dist/micro-app.mjs +80 -0
  22. package/dist/navigation.d.ts +43 -0
  23. package/dist/navigation.mjs +143 -0
  24. package/dist/navigation.test.d.ts +1 -0
  25. package/dist/navigation.test.mjs +681 -0
  26. package/dist/options.d.ts +4 -0
  27. package/dist/options.mjs +88 -0
  28. package/dist/route-task.d.ts +40 -0
  29. package/dist/route-task.mjs +75 -0
  30. package/dist/route-task.test.d.ts +1 -0
  31. package/dist/route-task.test.mjs +673 -0
  32. package/dist/route-transition.d.ts +53 -0
  33. package/dist/route-transition.mjs +307 -0
  34. package/dist/route-transition.test.d.ts +1 -0
  35. package/dist/route-transition.test.mjs +146 -0
  36. package/dist/route.d.ts +72 -0
  37. package/dist/route.mjs +194 -0
  38. package/dist/route.test.d.ts +1 -0
  39. package/dist/route.test.mjs +1664 -0
  40. package/dist/router-back.test.d.ts +1 -0
  41. package/dist/router-back.test.mjs +361 -0
  42. package/dist/router-forward.test.d.ts +1 -0
  43. package/dist/router-forward.test.mjs +376 -0
  44. package/dist/router-go.test.d.ts +1 -0
  45. package/dist/router-go.test.mjs +73 -0
  46. package/dist/router-guards-cleanup.test.d.ts +1 -0
  47. package/dist/router-guards-cleanup.test.mjs +437 -0
  48. package/dist/router-link.d.ts +10 -0
  49. package/dist/router-link.mjs +126 -0
  50. package/dist/router-push.test.d.ts +1 -0
  51. package/dist/router-push.test.mjs +115 -0
  52. package/dist/router-replace.test.d.ts +1 -0
  53. package/dist/router-replace.test.mjs +114 -0
  54. package/dist/router-resolve.test.d.ts +1 -0
  55. package/dist/router-resolve.test.mjs +393 -0
  56. package/dist/router-restart-app.dom.test.d.ts +1 -0
  57. package/dist/router-restart-app.dom.test.mjs +616 -0
  58. package/dist/router-window-navigation.test.d.ts +1 -0
  59. package/dist/router-window-navigation.test.mjs +359 -0
  60. package/dist/router.d.ts +109 -102
  61. package/dist/router.mjs +260 -361
  62. package/dist/types.d.ts +246 -0
  63. package/dist/types.mjs +18 -0
  64. package/dist/util.d.ts +26 -0
  65. package/dist/util.mjs +53 -0
  66. package/dist/util.test.d.ts +1 -0
  67. package/dist/util.test.mjs +1020 -0
  68. package/package.json +10 -13
  69. package/src/error.ts +84 -0
  70. package/src/increment-id.ts +12 -0
  71. package/src/index.test.ts +9 -0
  72. package/src/index.ts +54 -3
  73. package/src/location.test.ts +406 -0
  74. package/src/location.ts +96 -0
  75. package/src/matcher.test.ts +1685 -0
  76. package/src/matcher.ts +59 -0
  77. package/src/micro-app.dom.test.ts +708 -0
  78. package/src/micro-app.ts +101 -0
  79. package/src/navigation.test.ts +858 -0
  80. package/src/navigation.ts +195 -0
  81. package/src/options.ts +131 -0
  82. package/src/route-task.test.ts +901 -0
  83. package/src/route-task.ts +105 -0
  84. package/src/route-transition.test.ts +178 -0
  85. package/src/route-transition.ts +425 -0
  86. package/src/route.test.ts +2014 -0
  87. package/src/route.ts +308 -0
  88. package/src/router-back.test.ts +487 -0
  89. package/src/router-forward.test.ts +506 -0
  90. package/src/router-go.test.ts +91 -0
  91. package/src/router-guards-cleanup.test.ts +595 -0
  92. package/src/router-link.ts +235 -0
  93. package/src/router-push.test.ts +140 -0
  94. package/src/router-replace.test.ts +139 -0
  95. package/src/router-resolve.test.ts +475 -0
  96. package/src/router-restart-app.dom.test.ts +783 -0
  97. package/src/router-window-navigation.test.ts +457 -0
  98. package/src/router.ts +289 -470
  99. package/src/types.ts +341 -0
  100. package/src/util.test.ts +1262 -0
  101. package/src/util.ts +116 -0
  102. package/dist/history/abstract.d.ts +0 -29
  103. package/dist/history/abstract.mjs +0 -107
  104. package/dist/history/base.d.ts +0 -79
  105. package/dist/history/base.mjs +0 -275
  106. package/dist/history/html.d.ts +0 -22
  107. package/dist/history/html.mjs +0 -183
  108. package/dist/history/index.d.ts +0 -7
  109. package/dist/history/index.mjs +0 -16
  110. package/dist/matcher/create-matcher.d.ts +0 -5
  111. package/dist/matcher/create-matcher.mjs +0 -218
  112. package/dist/matcher/create-matcher.spec.mjs +0 -0
  113. package/dist/matcher/index.d.ts +0 -1
  114. package/dist/matcher/index.mjs +0 -1
  115. package/dist/task-pipe/index.d.ts +0 -1
  116. package/dist/task-pipe/index.mjs +0 -1
  117. package/dist/task-pipe/task.d.ts +0 -30
  118. package/dist/task-pipe/task.mjs +0 -66
  119. package/dist/utils/bom.d.ts +0 -5
  120. package/dist/utils/bom.mjs +0 -10
  121. package/dist/utils/encoding.d.ts +0 -48
  122. package/dist/utils/encoding.mjs +0 -44
  123. package/dist/utils/guards.d.ts +0 -9
  124. package/dist/utils/guards.mjs +0 -12
  125. package/dist/utils/index.d.ts +0 -7
  126. package/dist/utils/index.mjs +0 -27
  127. package/dist/utils/path.d.ts +0 -60
  128. package/dist/utils/path.mjs +0 -281
  129. package/dist/utils/path.spec.mjs +0 -27
  130. package/dist/utils/scroll.d.ts +0 -25
  131. package/dist/utils/scroll.mjs +0 -59
  132. package/dist/utils/utils.d.ts +0 -16
  133. package/dist/utils/utils.mjs +0 -11
  134. package/dist/utils/warn.d.ts +0 -2
  135. package/dist/utils/warn.mjs +0 -12
  136. package/src/history/abstract.ts +0 -149
  137. package/src/history/base.ts +0 -408
  138. package/src/history/html.ts +0 -228
  139. package/src/history/index.ts +0 -20
  140. package/src/matcher/create-matcher.spec.ts +0 -3
  141. package/src/matcher/create-matcher.ts +0 -293
  142. package/src/matcher/index.ts +0 -1
  143. package/src/task-pipe/index.ts +0 -1
  144. package/src/task-pipe/task.ts +0 -97
  145. package/src/utils/bom.ts +0 -14
  146. package/src/utils/encoding.ts +0 -153
  147. package/src/utils/guards.ts +0 -25
  148. package/src/utils/index.ts +0 -27
  149. package/src/utils/path.spec.ts +0 -32
  150. package/src/utils/path.ts +0 -417
  151. package/src/utils/scroll.ts +0 -120
  152. package/src/utils/utils.ts +0 -30
  153. package/src/utils/warn.ts +0 -13
  154. /package/dist/{matcher/create-matcher.spec.d.ts → index.test.d.ts} +0 -0
  155. /package/dist/{utils/path.spec.d.ts → matcher.test.d.ts} +0 -0
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020 Vanelink
3
+ Copyright (c) 2020 Esmx Team
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md ADDED
@@ -0,0 +1,70 @@
1
+ <div align="center">
2
+ <img src="https://www.esmnext.com/logo.svg?t=2025" width="120" alt="Esmx Logo" />
3
+ <h1>@esmx/router</h1>
4
+
5
+ <div>
6
+ <a href="https://www.npmjs.com/package/@esmx/router">
7
+ <img src="https://img.shields.io/npm/v/@esmx/router.svg" alt="npm version" />
8
+ </a>
9
+ <a href="https://github.com/esmnext/esmx/actions/workflows/build.yml">
10
+ <img src="https://github.com/esmnext/esmx/actions/workflows/build.yml/badge.svg" alt="Build" />
11
+ </a>
12
+ <a href="https://www.esmnext.com/coverage/">
13
+ <img src="https://img.shields.io/badge/coverage-live%20report-brightgreen" alt="Coverage Report" />
14
+ </a>
15
+ <a href="https://nodejs.org/">
16
+ <img src="https://img.shields.io/node/v/@esmx/router.svg" alt="node version" />
17
+ </a>
18
+ <a href="https://bundlephobia.com/package/@esmx/router">
19
+ <img src="https://img.shields.io/bundlephobia/minzip/@esmx/router" alt="size" />
20
+ </a>
21
+ </div>
22
+
23
+ <p>A universal, framework-agnostic router that works seamlessly with modern frontend frameworks</p>
24
+
25
+ <p>
26
+ English | <a href="https://github.com/esmnext/esmx/blob/master/packages/router/README.zh-CN.md">中文</a>
27
+ </p>
28
+ </div>
29
+
30
+ ## 🚀 Features
31
+
32
+ - **Framework Agnostic** - Works with any frontend framework (Vue, React, Preact, Solid, etc.)
33
+ - **Universal Support** - Runs in both browser and Node.js environments
34
+ - **TypeScript Ready** - Full TypeScript support with excellent type inference
35
+ - **High Performance** - Optimized for production use with minimal bundle size
36
+ - **SSR Compatible** - Complete server-side rendering support
37
+ - **Modern API** - Clean and intuitive API design
38
+
39
+ ## 📦 Installation
40
+
41
+ ```bash
42
+ npm install @esmx/router
43
+ ```
44
+
45
+ ## 🚀 Quick Start
46
+
47
+ ```typescript
48
+ import { Router, RouterMode } from '@esmx/router';
49
+
50
+ // Create router instance
51
+ const router = new Router({
52
+ root: '#app', // Required in browser environment
53
+ mode: RouterMode.history,
54
+ routes: [
55
+ { path: '/', component: () => 'Home Page' },
56
+ { path: '/about', component: () => 'About Page' }
57
+ ]
58
+ });
59
+
60
+ // Navigate to route
61
+ await router.push('/about');
62
+ ```
63
+
64
+ ## 📚 Documentation
65
+
66
+ Visit the [official documentation](https://www.esmnext.com) for detailed usage guides and API reference.
67
+
68
+ ## 📄 License
69
+
70
+ MIT © [Esmx Team](https://github.com/esmnext/esmx)
@@ -0,0 +1,70 @@
1
+ <div align="center">
2
+ <img src="https://www.esmnext.com/logo.svg?t=2025" width="120" alt="Esmx Logo" />
3
+ <h1>@esmx/router</h1>
4
+
5
+ <div>
6
+ <a href="https://www.npmjs.com/package/@esmx/router">
7
+ <img src="https://img.shields.io/npm/v/@esmx/router.svg" alt="npm version" />
8
+ </a>
9
+ <a href="https://github.com/esmnext/esmx/actions/workflows/build.yml">
10
+ <img src="https://github.com/esmnext/esmx/actions/workflows/build.yml/badge.svg" alt="Build" />
11
+ </a>
12
+ <a href="https://www.esmnext.com/coverage/">
13
+ <img src="https://img.shields.io/badge/coverage-live%20report-brightgreen" alt="Coverage Report" />
14
+ </a>
15
+ <a href="https://nodejs.org/">
16
+ <img src="https://img.shields.io/node/v/@esmx/router.svg" alt="node version" />
17
+ </a>
18
+ <a href="https://bundlephobia.com/package/@esmx/router">
19
+ <img src="https://img.shields.io/bundlephobia/minzip/@esmx/router" alt="size" />
20
+ </a>
21
+ </div>
22
+
23
+ <p>通用的框架无关路由器,与现代前端框架无缝协作</p>
24
+
25
+ <p>
26
+ <a href="https://github.com/esmnext/esmx/blob/master/packages/router/README.md">English</a> | 中文
27
+ </p>
28
+ </div>
29
+
30
+ ## 🚀 特性
31
+
32
+ - **框架无关** - 适用于任何前端框架(Vue、React、Preact、Solid 等)
33
+ - **通用支持** - 在浏览器和 Node.js 环境中运行
34
+ - **TypeScript 就绪** - 完整的 TypeScript 支持,出色的类型推断
35
+ - **高性能** - 为生产环境优化,最小化包体积
36
+ - **SSR 兼容** - 完整的服务端渲染支持
37
+ - **现代 API** - 简洁直观的 API 设计
38
+
39
+ ## 📦 安装
40
+
41
+ ```bash
42
+ npm install @esmx/router
43
+ ```
44
+
45
+ ## 🚀 快速开始
46
+
47
+ ```typescript
48
+ import { Router, RouterMode } from '@esmx/router';
49
+
50
+ // 创建路由器实例
51
+ const router = new Router({
52
+ root: '#app', // 浏览器环境中必需
53
+ mode: RouterMode.history,
54
+ routes: [
55
+ { path: '/', component: () => '首页' },
56
+ { path: '/about', component: () => '关于页面' }
57
+ ]
58
+ });
59
+
60
+ // 导航到路由
61
+ await router.push('/about');
62
+ ```
63
+
64
+ ## 📚 文档
65
+
66
+ 访问[官方文档](https://www.esmnext.com)获取详细的使用指南和 API 参考。
67
+
68
+ ## 📄 许可证
69
+
70
+ MIT © [Esmx Team](https://github.com/esmnext/esmx)
@@ -0,0 +1,23 @@
1
+ import type { Route } from './route';
2
+ export declare class RouteError extends Error {
3
+ readonly code: string;
4
+ readonly to: Route;
5
+ readonly from: Route | null;
6
+ constructor(message: string, code: string, to: Route, from?: Route | null);
7
+ }
8
+ export declare class RouteTaskCancelledError extends RouteError {
9
+ readonly taskName: string;
10
+ constructor(taskName: string, to: Route, from?: Route | null);
11
+ }
12
+ export declare class RouteTaskExecutionError extends RouteError {
13
+ readonly taskName: string;
14
+ readonly originalError: Error;
15
+ constructor(taskName: string, to: Route, from?: Route | null, originalError?: unknown);
16
+ }
17
+ export declare class RouteNavigationAbortedError extends RouteError {
18
+ readonly taskName: string;
19
+ constructor(taskName: string, to: Route, from?: Route | null);
20
+ }
21
+ export declare class RouteSelfRedirectionError extends RouteError {
22
+ constructor(fullPath: string, to: Route, from?: Route | null);
23
+ }
package/dist/error.mjs ADDED
@@ -0,0 +1,61 @@
1
+ export class RouteError extends Error {
2
+ code;
3
+ to;
4
+ from;
5
+ constructor(message, code, to, from = null) {
6
+ super(message);
7
+ this.name = "RouteError";
8
+ this.code = code;
9
+ this.to = to;
10
+ this.from = from;
11
+ }
12
+ }
13
+ export class RouteTaskCancelledError extends RouteError {
14
+ taskName;
15
+ constructor(taskName, to, from = null) {
16
+ super(
17
+ `Route task "${taskName}" was cancelled`,
18
+ "ROUTE_TASK_CANCELLED",
19
+ to,
20
+ from
21
+ );
22
+ this.name = "RouteTaskCancelledError";
23
+ this.taskName = taskName;
24
+ }
25
+ }
26
+ export class RouteTaskExecutionError extends RouteError {
27
+ taskName;
28
+ originalError;
29
+ constructor(taskName, to, from = null, originalError) {
30
+ const error = originalError instanceof Error ? originalError : new Error(String(originalError));
31
+ const message = `Route task "${taskName}" failed${error.message ? `: ${error.message}` : ""}`;
32
+ super(message, "ROUTE_TASK_EXECUTION_ERROR", to, from);
33
+ this.name = "RouteTaskExecutionError";
34
+ this.taskName = taskName;
35
+ this.originalError = error;
36
+ }
37
+ }
38
+ export class RouteNavigationAbortedError extends RouteError {
39
+ taskName;
40
+ constructor(taskName, to, from = null) {
41
+ super(
42
+ `Navigation was aborted by task "${taskName}"`,
43
+ "ROUTE_NAVIGATION_ABORTED",
44
+ to,
45
+ from
46
+ );
47
+ this.name = "RouteNavigationAbortedError";
48
+ this.taskName = taskName;
49
+ }
50
+ }
51
+ export class RouteSelfRedirectionError extends RouteError {
52
+ constructor(fullPath, to, from = null) {
53
+ super(
54
+ `Detected a self-redirection to "${fullPath}". Aborting navigation.`,
55
+ "ROUTE_SELF_REDIRECTION",
56
+ to,
57
+ from
58
+ );
59
+ this.name = "RouteSelfRedirectionError";
60
+ }
61
+ }
@@ -0,0 +1,7 @@
1
+ export declare class IncrementId {
2
+ private value;
3
+ equal(id: number): boolean;
4
+ next(): number;
5
+ }
6
+ export declare const PAGE_ID: IncrementId;
7
+ export declare const LAYER_ID: IncrementId;
@@ -0,0 +1,11 @@
1
+ export class IncrementId {
2
+ value = 0;
3
+ equal(id) {
4
+ return this.value === id;
5
+ }
6
+ next() {
7
+ return ++this.value;
8
+ }
9
+ }
10
+ export const PAGE_ID = new IncrementId();
11
+ export const LAYER_ID = new IncrementId();
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
- export { createRouter } from './router';
2
- export * from './types';
3
- export * from './utils';
1
+ export { Router } from './router';
2
+ export { Route } from './route';
3
+ export { RouteTransition, ROUTE_TYPE_HANDLERS } from './route-transition';
4
+ export { type Awaitable, RouterMode, RouteType, type RouteConfirmHook, type RouteConfirmHookResult, type RouteVerifyHook, type RouteHandleHook, type RouteNotifyHook, type RouteMeta, type RouteState, type RouteHandleResult, type RouteMatchType, type RouteLocation, type RouteLocationInput, type RouteConfig, type RouteParsedConfig, type RouteMatchResult, type RouteMatcher, type RouteOptions, type RouteLayerOptions, type RouteLayerResult, type RouterLayerOptions, type RouterMicroApp, type RouterMicroAppCallback, type RouterMicroAppOptions, type RouterOptions, type RouterParsedOptions, type RouterLinkType, type RouterLinkAttributes, type RouterLinkProps, type RouterLinkResolved } from './types';
5
+ export { RouteError, RouteTaskCancelledError, RouteTaskExecutionError, RouteNavigationAbortedError, RouteSelfRedirectionError } from './error';
package/dist/index.mjs CHANGED
@@ -1,3 +1,14 @@
1
- export { createRouter } from "./router.mjs";
2
- export * from "./types";
3
- export * from "./utils/index.mjs";
1
+ export { Router } from "./router.mjs";
2
+ export { Route } from "./route.mjs";
3
+ export { RouteTransition, ROUTE_TYPE_HANDLERS } from "./route-transition.mjs";
4
+ export {
5
+ RouterMode,
6
+ RouteType
7
+ } from "./types.mjs";
8
+ export {
9
+ RouteError,
10
+ RouteTaskCancelledError,
11
+ RouteTaskExecutionError,
12
+ RouteNavigationAbortedError,
13
+ RouteSelfRedirectionError
14
+ } from "./error.mjs";
@@ -0,0 +1,8 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { Router as IndexRouter } from "./index.mjs";
3
+ import { Router } from "./router.mjs";
4
+ describe("index exports", () => {
5
+ it("should export Router correctly", () => {
6
+ expect(IndexRouter).toBe(Router);
7
+ });
8
+ });
@@ -0,0 +1,15 @@
1
+ import type { RouteLocationInput } from './types';
2
+ /**
3
+ * Normalizes a URL input into a URL object.
4
+ * @param url - The URL or string to normalize.
5
+ * @param base - The base URL to resolve against if the input is relative.
6
+ * @returns A URL object.
7
+ */
8
+ export declare function normalizeURL(url: string | URL, base: URL): URL;
9
+ /**
10
+ * Parses a RouteLocationInput object into a full URL.
11
+ * @param toInput - The route location input.
12
+ * @param baseURL - The base URL to resolve against.
13
+ * @returns The parsed URL object.
14
+ */
15
+ export declare function parseLocation(toInput: RouteLocationInput, baseURL: URL): URL;
@@ -0,0 +1,53 @@
1
+ import { isNotNullish } from "./util.mjs";
2
+ export function normalizeURL(url, base) {
3
+ if (url instanceof URL) {
4
+ return url;
5
+ }
6
+ if (url.startsWith("//")) {
7
+ return new URL(`http:${url}`);
8
+ }
9
+ if (url.startsWith("/")) {
10
+ const newBase = new URL(".", base);
11
+ const parsed = new URL(url, newBase);
12
+ parsed.pathname = newBase.pathname.slice(0, -1) + parsed.pathname;
13
+ return parsed;
14
+ }
15
+ try {
16
+ return new URL(url);
17
+ } catch (e) {
18
+ return new URL(url, base);
19
+ }
20
+ }
21
+ export function parseLocation(toInput, baseURL) {
22
+ if (typeof toInput === "string") {
23
+ return normalizeURL(toInput, baseURL);
24
+ }
25
+ const url = normalizeURL(toInput.path ?? toInput.url ?? "", baseURL);
26
+ const searchParams = url.searchParams;
27
+ const mergedQuery = {};
28
+ if (toInput.query) {
29
+ Object.entries(toInput.query).forEach(([key, value]) => {
30
+ if (typeof value !== "undefined") {
31
+ mergedQuery[key] = value;
32
+ }
33
+ });
34
+ }
35
+ if (toInput.queryArray) {
36
+ Object.entries(toInput.queryArray).forEach(([key, value]) => {
37
+ if (typeof value !== "undefined") {
38
+ mergedQuery[key] = value;
39
+ }
40
+ });
41
+ }
42
+ Object.entries(mergedQuery).forEach(([key, value]) => {
43
+ searchParams.delete(key);
44
+ value = Array.isArray(value) ? value : [value];
45
+ value.filter((v) => isNotNullish(v) && !Number.isNaN(v)).forEach((v) => {
46
+ searchParams.append(key, String(v));
47
+ });
48
+ });
49
+ if (toInput.hash) {
50
+ url.hash = toInput.hash;
51
+ }
52
+ return url;
53
+ }
@@ -0,0 +1,8 @@
1
+ declare module 'vitest' {
2
+ interface ToEqURLMatchers {
3
+ toEqURL(expected: URL | string): void;
4
+ }
5
+ interface Assertion extends ToEqURLMatchers {
6
+ }
7
+ }
8
+ export {};