@esmx/router 3.0.0-rc.18 → 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 (158) 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 -30
  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/types/index.d.ts +0 -694
  120. package/dist/types/index.mjs +0 -6
  121. package/dist/utils/bom.d.ts +0 -5
  122. package/dist/utils/bom.mjs +0 -10
  123. package/dist/utils/encoding.d.ts +0 -48
  124. package/dist/utils/encoding.mjs +0 -44
  125. package/dist/utils/guards.d.ts +0 -9
  126. package/dist/utils/guards.mjs +0 -12
  127. package/dist/utils/index.d.ts +0 -7
  128. package/dist/utils/index.mjs +0 -27
  129. package/dist/utils/path.d.ts +0 -60
  130. package/dist/utils/path.mjs +0 -282
  131. package/dist/utils/path.spec.mjs +0 -27
  132. package/dist/utils/scroll.d.ts +0 -25
  133. package/dist/utils/scroll.mjs +0 -59
  134. package/dist/utils/utils.d.ts +0 -16
  135. package/dist/utils/utils.mjs +0 -11
  136. package/dist/utils/warn.d.ts +0 -2
  137. package/dist/utils/warn.mjs +0 -12
  138. package/src/history/abstract.ts +0 -149
  139. package/src/history/base.ts +0 -408
  140. package/src/history/html.ts +0 -228
  141. package/src/history/index.ts +0 -20
  142. package/src/matcher/create-matcher.spec.ts +0 -3
  143. package/src/matcher/create-matcher.ts +0 -292
  144. package/src/matcher/index.ts +0 -1
  145. package/src/task-pipe/index.ts +0 -1
  146. package/src/task-pipe/task.ts +0 -97
  147. package/src/types/index.ts +0 -858
  148. package/src/utils/bom.ts +0 -14
  149. package/src/utils/encoding.ts +0 -153
  150. package/src/utils/guards.ts +0 -25
  151. package/src/utils/index.ts +0 -27
  152. package/src/utils/path.spec.ts +0 -32
  153. package/src/utils/path.ts +0 -418
  154. package/src/utils/scroll.ts +0 -120
  155. package/src/utils/utils.ts +0 -30
  156. package/src/utils/warn.ts +0 -13
  157. /package/dist/{matcher/create-matcher.spec.d.ts → index.test.d.ts} +0 -0
  158. /package/dist/{utils/path.spec.d.ts → matcher.test.d.ts} +0 -0
@@ -0,0 +1,246 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { MatchFunction } from 'path-to-regexp';
3
+ import type { Route } from './route';
4
+ import type { Router } from './router';
5
+ export type { Route };
6
+ export type Awaitable<T> = T | Promise<T>;
7
+ export declare enum RouterMode {
8
+ history = "history",
9
+ memory = "memory"
10
+ }
11
+ export declare enum RouteType {
12
+ push = "push",
13
+ replace = "replace",
14
+ restartApp = "restartApp",
15
+ go = "go",
16
+ forward = "forward",
17
+ back = "back",
18
+ unknown = "unknown",
19
+ pushWindow = "pushWindow",
20
+ replaceWindow = "replaceWindow",
21
+ pushLayer = "pushLayer"
22
+ }
23
+ export type RouteConfirmHookResult = void | false | RouteLocationInput | RouteHandleHook;
24
+ export type RouteConfirmHook = (to: Route, from: Route | null, router: Router) => Awaitable<RouteConfirmHookResult>;
25
+ export type RouteVerifyHook = (to: Route, from: Route | null, router: Router) => Awaitable<boolean>;
26
+ export type RouteHandleHook = (to: Route, from: Route | null, router: Router) => Awaitable<RouteHandleResult>;
27
+ export type RouteNotifyHook = (to: Route, from: Route | null, router: Router) => void;
28
+ export type RouteMeta = Record<string | symbol, unknown>;
29
+ export type RouteState = Record<string, unknown>;
30
+ export type RouteHandleResult = unknown | null | void;
31
+ /**
32
+ * Route matching type
33
+ * - 'route': Route-level matching, compare if route configurations are the same
34
+ * - 'exact': Exact matching, compare if paths are exactly the same
35
+ * - 'include': Include matching, check if current path contains target path
36
+ */
37
+ export type RouteMatchType = 'route' | 'exact' | 'include';
38
+ export interface RouteLocation {
39
+ path?: string;
40
+ url?: string | URL;
41
+ params?: Record<string, string>;
42
+ query?: Record<string, string | undefined>;
43
+ queryArray?: Record<string, string[] | undefined>;
44
+ hash?: string;
45
+ state?: RouteState;
46
+ keepScrollPosition?: boolean;
47
+ statusCode?: number | null;
48
+ layer?: RouteLayerOptions | null;
49
+ confirm?: RouteConfirmHook | null;
50
+ }
51
+ export type RouteLocationInput = RouteLocation | string;
52
+ export interface RouteConfig {
53
+ /** Pass a URL-encoded path */
54
+ path: string;
55
+ component?: unknown;
56
+ children?: RouteConfig[];
57
+ redirect?: RouteLocationInput | RouteConfirmHook;
58
+ meta?: RouteMeta;
59
+ app?: string | RouterMicroAppCallback;
60
+ asyncComponent?: () => Promise<unknown>;
61
+ beforeEnter?: RouteConfirmHook;
62
+ beforeUpdate?: RouteConfirmHook;
63
+ beforeLeave?: RouteConfirmHook;
64
+ /**
65
+ * Route override function for hybrid app development
66
+ *
67
+ * Note: Override is not executed during initial route loading
68
+ *
69
+ * @param to Target route
70
+ * @param from Source route
71
+ * @returns Function to execute instead of default routing, or void for default
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * override: (to, from) => {
76
+ * if (isInApp()) {
77
+ * return () => JSBridge.openNative();
78
+ * }
79
+ * }
80
+ * ```
81
+ */
82
+ override?: RouteConfirmHook;
83
+ }
84
+ export interface RouteParsedConfig extends RouteConfig {
85
+ compilePath: string;
86
+ children: RouteParsedConfig[];
87
+ match: MatchFunction;
88
+ compile: (params?: Record<string, string>) => string;
89
+ }
90
+ export interface RouteMatchResult {
91
+ readonly matches: readonly RouteParsedConfig[];
92
+ readonly params: Record<string, string | string[] | undefined>;
93
+ }
94
+ export type RouteMatcher = (targetURL: URL, baseURL: URL) => RouteMatchResult;
95
+ /**
96
+ * Route constructor options interface
97
+ */
98
+ export interface RouteOptions {
99
+ /** Router parsed options */
100
+ options?: RouterParsedOptions;
101
+ /** Route type */
102
+ toType?: RouteType;
103
+ /** Target route location */
104
+ toInput?: RouteLocationInput;
105
+ /** Source URL */
106
+ from?: URL | null;
107
+ }
108
+ export interface RouteLayerOptions {
109
+ /**
110
+ * Layer zIndex value
111
+ * If not set, will automatically use incremental layer value (1000 + increment)
112
+ */
113
+ zIndex?: number;
114
+ /**
115
+ * Verification hook function before route closure
116
+ * @returns Return true to allow closure, false to prevent closure
117
+ */
118
+ shouldClose?: RouteVerifyHook;
119
+ /**
120
+ * Whether to automatically record route history
121
+ * @default true
122
+ */
123
+ autoPush?: boolean;
124
+ /**
125
+ * Route navigation mode control
126
+ * - When autoPush is true:
127
+ * - true: Use push mode (add new history record)
128
+ * - false: Use replace mode (replace current history record)
129
+ * @default true
130
+ */
131
+ push?: boolean;
132
+ /**
133
+ * Router options for creating the layer instance
134
+ * These options will be merged with the default router configuration
135
+ */
136
+ routerOptions?: RouterLayerOptions;
137
+ }
138
+ export type RouteLayerResult = {
139
+ type: 'close';
140
+ route: Route;
141
+ } | {
142
+ type: 'push';
143
+ route: Route;
144
+ } | {
145
+ type: 'success';
146
+ route: Route;
147
+ data?: any;
148
+ };
149
+ /**
150
+ * Router options for creating layer instances
151
+ * Excludes handler functions and layer fields which are handled internally by createLayer
152
+ */
153
+ export type RouterLayerOptions = Omit<RouterOptions, 'handleBackBoundary' | 'handleLayerClose' | 'layer'>;
154
+ export interface RouterMicroAppOptions {
155
+ mount: (el: HTMLElement) => void;
156
+ unmount: () => void;
157
+ renderToString?: () => Awaitable<string>;
158
+ }
159
+ export type RouterMicroAppCallback = (router: Router) => RouterMicroAppOptions;
160
+ export type RouterMicroApp = Record<string, RouterMicroAppCallback | undefined> | RouterMicroAppCallback;
161
+ export interface RouterOptions {
162
+ /**
163
+ * Application mounting container
164
+ * - Can be a DOM selector string (e.g., '#app', '.container', '[data-mount]')
165
+ * - Can be an HTMLElement object
166
+ * - Defaults to '#root'
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * // Using ID selector
171
+ * new Router({ root: '#my-app' })
172
+ *
173
+ * // Using class selector
174
+ * new Router({ root: '.app-container' })
175
+ *
176
+ * // Using attribute selector
177
+ * new Router({ root: '[data-router-mount]' })
178
+ *
179
+ * // Passing DOM element directly
180
+ * const element = document.getElementById('app');
181
+ * new Router({ root: element })
182
+ * ```
183
+ */
184
+ root?: string | HTMLElement;
185
+ context?: Record<string | symbol, unknown>;
186
+ routes?: RouteConfig[];
187
+ mode?: RouterMode;
188
+ /** Optional in browser, but required on server side */
189
+ base?: URL;
190
+ req?: IncomingMessage | null;
191
+ res?: ServerResponse | null;
192
+ apps?: RouterMicroApp;
193
+ normalizeURL?: (to: URL, from: URL | null) => URL;
194
+ fallback?: RouteHandleHook;
195
+ rootStyle?: Partial<CSSStyleDeclaration> | false;
196
+ layer?: boolean;
197
+ zIndex?: number;
198
+ handleBackBoundary?: (router: Router) => void;
199
+ handleLayerClose?: (router: Router, data?: any) => void;
200
+ }
201
+ export interface RouterParsedOptions extends Readonly<Required<RouterOptions>> {
202
+ readonly matcher: RouteMatcher;
203
+ }
204
+ /**
205
+ * Router link navigation types
206
+ */
207
+ export type RouterLinkType = 'push' | 'replace' | 'pushWindow' | 'replaceWindow' | 'pushLayer';
208
+ /**
209
+ * Router link attributes generated by the source code
210
+ */
211
+ export interface RouterLinkAttributes {
212
+ href: string;
213
+ class: string;
214
+ target?: '_blank';
215
+ rel?: string;
216
+ }
217
+ /**
218
+ * Framework-agnostic link configuration interface
219
+ */
220
+ export interface RouterLinkProps {
221
+ to: RouteLocationInput;
222
+ type?: RouterLinkType;
223
+ /**
224
+ * @deprecated Use type='replace' instead
225
+ */
226
+ replace?: boolean;
227
+ exact?: RouteMatchType;
228
+ activeClass?: string;
229
+ event?: string | string[];
230
+ tag?: string;
231
+ layerOptions?: RouteLayerOptions;
232
+ }
233
+ /**
234
+ * Framework-agnostic link resolution result
235
+ */
236
+ export interface RouterLinkResolved {
237
+ route: Route;
238
+ type: RouterLinkType;
239
+ isActive: boolean;
240
+ isExactActive: boolean;
241
+ isExternal: boolean;
242
+ tag: string;
243
+ attributes: RouterLinkAttributes;
244
+ navigate: (e?: MouseEvent) => Promise<void>;
245
+ getEventHandlers: (nameTransform?: (eventType: string) => string) => Record<string, (e: MouseEvent) => Promise<void>>;
246
+ }
package/dist/types.mjs ADDED
@@ -0,0 +1,18 @@
1
+ export var RouterMode = /* @__PURE__ */ ((RouterMode2) => {
2
+ RouterMode2["history"] = "history";
3
+ RouterMode2["memory"] = "memory";
4
+ return RouterMode2;
5
+ })(RouterMode || {});
6
+ export var RouteType = /* @__PURE__ */ ((RouteType2) => {
7
+ RouteType2["push"] = "push";
8
+ RouteType2["replace"] = "replace";
9
+ RouteType2["restartApp"] = "restartApp";
10
+ RouteType2["go"] = "go";
11
+ RouteType2["forward"] = "forward";
12
+ RouteType2["back"] = "back";
13
+ RouteType2["unknown"] = "unknown";
14
+ RouteType2["pushWindow"] = "pushWindow";
15
+ RouteType2["replaceWindow"] = "replaceWindow";
16
+ RouteType2["pushLayer"] = "pushLayer";
17
+ return RouteType2;
18
+ })(RouteType || {});
package/dist/util.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import type { Route, RouteConfirmHookResult, RouteMatchType } from './types';
2
+ export declare const isBrowser: boolean;
3
+ export declare function isNotNullish(value: unknown): boolean;
4
+ export declare function isPlainObject(o: unknown): o is Record<string, any>;
5
+ /**
6
+ * Check if value is a valid non-empty plain object
7
+ * Only check enumerable string keys to ensure it's a proper plain object
8
+ * @param value Value to check
9
+ * @returns true if it's a valid non-empty plain object
10
+ */
11
+ export declare function isNonEmptyPlainObject(value: unknown): value is Record<string, any>;
12
+ export declare const removeFromArray: <T>(arr: T[], ele: T) => void;
13
+ export declare function isValidConfirmHookResult(result: unknown): result is Exclude<RouteConfirmHookResult, void>;
14
+ export declare function isUrlEqual(url1: URL, url2?: URL | null): boolean;
15
+ /**
16
+ * Compare if two routes match
17
+ *
18
+ * @param route1 First route object
19
+ * @param route2 Second route object, may be null
20
+ * @param matchType Match type
21
+ * - 'route': Route-level matching, compare if route configurations are the same
22
+ * - 'exact': Exact matching, compare if full paths are the same
23
+ * - 'include': Include matching, check if route1 path starts with route2 path
24
+ * @returns Whether they match
25
+ */
26
+ export declare function isRouteMatched(route1: Route, route2: Route | null, matchType: RouteMatchType): boolean;
package/dist/util.mjs ADDED
@@ -0,0 +1,53 @@
1
+ export const isBrowser = typeof window === "object";
2
+ export function isNotNullish(value) {
3
+ return value !== void 0 && value !== null && !Number.isNaN(
4
+ value instanceof Number ? value.valueOf() : value
5
+ );
6
+ }
7
+ export function isPlainObject(o) {
8
+ return (o == null ? void 0 : o.constructor) === Object || Object.prototype.toString.call(o) === "[object Object]";
9
+ }
10
+ export function isNonEmptyPlainObject(value) {
11
+ if (!isPlainObject(value)) {
12
+ return false;
13
+ }
14
+ return Object.keys(value).length > 0;
15
+ }
16
+ export const removeFromArray = (arr, ele) => {
17
+ if (!Array.isArray(arr) || arr.length === 0) return;
18
+ const i = Number.isNaN(ele) ? (
19
+ // If ele is NaN, use findIndex to search for NaN, because NaN !== NaN, so we can't use indexOf directly
20
+ arr.findIndex((item) => Number.isNaN(item))
21
+ ) : arr.indexOf(ele);
22
+ if (i === -1) return;
23
+ arr.splice(i, 1);
24
+ };
25
+ export function isValidConfirmHookResult(result) {
26
+ return result === false || typeof result === "function" || typeof result === "string" || isPlainObject(result);
27
+ }
28
+ export function isUrlEqual(url1, url2) {
29
+ if (!url2) {
30
+ return false;
31
+ }
32
+ if (url1 === url2) {
33
+ return true;
34
+ }
35
+ (url1 = new URL(url1)).searchParams.sort();
36
+ (url2 = new URL(url2)).searchParams.sort();
37
+ url1.hash = url1.hash;
38
+ url2.hash = url2.hash;
39
+ return url1.href === url2.href;
40
+ }
41
+ export function isRouteMatched(route1, route2, matchType) {
42
+ if (!route2) return false;
43
+ switch (matchType) {
44
+ case "route":
45
+ return route1.config === route2.config;
46
+ case "exact":
47
+ return route1.fullPath === route2.fullPath;
48
+ case "include":
49
+ return route1.fullPath.startsWith(route2.fullPath);
50
+ default:
51
+ return false;
52
+ }
53
+ }
@@ -0,0 +1 @@
1
+ export {};