@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
@@ -1,228 +0,0 @@
1
- import type { RouterInstance, RouterRawLocation } from '../types';
2
- import {
3
- computeScrollPosition,
4
- getKeepScrollPosition,
5
- getSavedScrollPosition,
6
- isPathWithProtocolOrDomain,
7
- normalizeLocation,
8
- openWindow,
9
- saveScrollPosition,
10
- scrollToPosition
11
- } from '../utils';
12
- import { BaseRouterHistory } from './base';
13
-
14
- export class HtmlHistory extends BaseRouterHistory {
15
- constructor(router: RouterInstance) {
16
- super(router);
17
-
18
- if ('scrollRestoration' in window.history) {
19
- // 只有在 html 模式下才需要修改历史滚动模式
20
- window.history.scrollRestoration = 'manual';
21
- }
22
- }
23
-
24
- // 获取当前地址,包括 path query hash
25
- getCurrentLocation() {
26
- const { href } = window.location;
27
- const { state } = window.history;
28
- const { path, base, ...rest } = normalizeLocation(
29
- href,
30
- this.router.base
31
- );
32
- return {
33
- path: path.replace(new RegExp(`^(${base})`), ''),
34
- base,
35
- ...rest,
36
- state
37
- };
38
- }
39
-
40
- onPopState = (e: PopStateEvent) => {
41
- if (this.isFrozen) return;
42
- if (this.router.checkLayerState(e.state)) return;
43
-
44
- const current = Object.assign({}, this.current);
45
-
46
- // 当路由变化时触发跳转事件
47
- this.transitionTo(this.getCurrentLocation(), async (route) => {
48
- const { state } = window.history;
49
- saveScrollPosition(current.fullPath, computeScrollPosition());
50
- setTimeout(async () => {
51
- const keepScrollPosition = state.keepScrollPosition;
52
- if (keepScrollPosition) {
53
- return;
54
- }
55
- const savedPosition = getSavedScrollPosition(route.fullPath);
56
- const position = await this.router.scrollBehavior(
57
- current,
58
- route,
59
- savedPosition
60
- );
61
-
62
- const { nextTick } = this.router.options;
63
- if (position) {
64
- nextTick && (await nextTick());
65
- scrollToPosition(position);
66
- }
67
- });
68
- });
69
- };
70
-
71
- async init({ replace }: { replace?: boolean } = { replace: true }) {
72
- const { initUrl } = this.router.options;
73
- let route = this.getCurrentLocation();
74
- if (initUrl !== undefined) {
75
- // 存在 initUrl 则用 initUrl 进行初始化
76
- route = this.resolve(initUrl) as any;
77
- } else {
78
- const state = history.state || {};
79
- route.state = {
80
- ...state,
81
- _ancientRoute: state._ancientRoute ?? true // 最古历史的标记, 在调用返回事件时如果有这个标记则直接调用没有历史记录的钩子
82
- };
83
- }
84
- if (replace) {
85
- await this.replace(route as RouterRawLocation);
86
- } else {
87
- await this.push(route as RouterRawLocation);
88
- }
89
- this.setupListeners();
90
- }
91
-
92
- // 设置监听函数
93
- setupListeners() {
94
- window.addEventListener('popstate', this.onPopState);
95
- }
96
-
97
- destroy() {
98
- window.removeEventListener('popstate', this.onPopState);
99
- }
100
-
101
- pushWindow(location: RouterRawLocation) {
102
- if (this.isFrozen) return;
103
- this.handleOutside(location, false, true);
104
- }
105
-
106
- replaceWindow(location: RouterRawLocation) {
107
- if (this.isFrozen) return;
108
- this.handleOutside(location, true, true);
109
- }
110
-
111
- // 处理外站跳转逻辑
112
- handleOutside(
113
- location: RouterRawLocation,
114
- replace = false,
115
- // 是否是 pushWindow/replaceWindow 触发的
116
- isTriggerWithWindow = false
117
- ) {
118
- const base = this.router.base;
119
- const { flag, route } = isPathWithProtocolOrDomain(location, base);
120
- const router = this.router;
121
- const { handleOutside, validateOutside } = router.options;
122
-
123
- // 不以域名开头 或 域名相同 都认为是同域
124
- const isSameHost = !flag || window.location.hostname === route.hostname;
125
-
126
- // 如果 不是 pushWindow/replaceWindow 触发的
127
- if (!isTriggerWithWindow) {
128
- // 如果域名相同 和 非外站(存在就算同域也会被视为外站的情况) 则跳出
129
- if (isSameHost && !validateOutside?.({ router, location, route })) {
130
- return false;
131
- }
132
- }
133
-
134
- // 如果有配置跳转外站函数,则执行配置函数
135
- // 如果配置函数返回 true 则认为其处理了打开逻辑,跳出
136
- const res = handleOutside?.({
137
- router,
138
- route,
139
- replace,
140
- isTriggerWithWindow,
141
- isSameHost
142
- });
143
- if (res === false) {
144
- // 如果配置函数返回 false 则跳出
145
- return true;
146
- }
147
-
148
- if (replace) {
149
- window.location.replace(route.href);
150
- } else {
151
- const { hostname, href } = route;
152
- openWindow(href, hostname);
153
- }
154
-
155
- return true;
156
- }
157
-
158
- // 新增路由记录跳转
159
- async push(location: RouterRawLocation) {
160
- await this.jump(location, false);
161
- }
162
-
163
- // 替换当前路由记录跳转
164
- async replace(location: RouterRawLocation) {
165
- await this.jump(location, true);
166
- }
167
-
168
- // 跳转方法
169
- async jump(location: RouterRawLocation, replace = false) {
170
- if (this.isFrozen) return;
171
- if (this.handleOutside(location, replace)) {
172
- return;
173
- }
174
-
175
- const current = Object.assign({}, this.current);
176
- await this.transitionTo(location, (route) => {
177
- const keepScrollPosition = getKeepScrollPosition(location);
178
- if (!keepScrollPosition) {
179
- saveScrollPosition(current.fullPath, computeScrollPosition());
180
- scrollToPosition({ left: 0, top: 0 });
181
- }
182
-
183
- const state = Object.assign(
184
- replace
185
- ? { ...history.state, ...route.state }
186
- : { ...route.state, _ancientRoute: false },
187
- { keepScrollPosition }
188
- );
189
- window.history[replace ? 'replaceState' : 'pushState'](
190
- state,
191
- '',
192
- route.fullPath
193
- );
194
-
195
- this.router.updateLayerState(route);
196
- });
197
- }
198
-
199
- go(delta: number): void {
200
- if (this.isFrozen) return;
201
- window.history.go(delta);
202
- }
203
-
204
- forward(): void {
205
- if (this.isFrozen) return;
206
- window.history.forward();
207
- }
208
-
209
- protected timer: NodeJS.Timeout | null = null;
210
-
211
- back(): void {
212
- if (this.isFrozen) return;
213
- const oldState = history.state;
214
- const noBackNavigation = this.router.options.noBackNavigation;
215
- if (oldState._ancientRoute === true) {
216
- noBackNavigation && noBackNavigation(this.router);
217
- return;
218
- }
219
-
220
- window.history.back();
221
- this.timer = setTimeout(() => {
222
- if (history.state === oldState) {
223
- noBackNavigation && noBackNavigation(this.router);
224
- }
225
- this.timer = null;
226
- }, 80);
227
- }
228
- }
@@ -1,20 +0,0 @@
1
- import { type RouterInstance, RouterMode } from '../types';
2
- import { AbstractHistory } from './abstract';
3
- import { HtmlHistory } from './html';
4
-
5
- export function createHistory({
6
- router,
7
- mode
8
- }: {
9
- router: RouterInstance;
10
- mode: RouterMode;
11
- }) {
12
- switch (mode) {
13
- case RouterMode.HISTORY:
14
- return new HtmlHistory(router);
15
- case RouterMode.ABSTRACT:
16
- return new AbstractHistory(router);
17
- default:
18
- throw new Error('not support mode');
19
- }
20
- }
@@ -1,3 +0,0 @@
1
- import { describe, it } from 'vitest';
2
-
3
- import { createRouterMatcher } from './create-matcher';
@@ -1,292 +0,0 @@
1
- import { compile, match, pathToRegexp } from 'path-to-regexp';
2
-
3
- import type {
4
- HistoryState,
5
- RouteConfig,
6
- RouteMatch,
7
- RouteRecord,
8
- RouterLocation,
9
- RouterMatcher
10
- } from '../types';
11
- import {
12
- decode,
13
- encodePath,
14
- normalizeLocation,
15
- normalizePath,
16
- parsePath,
17
- stringifyPath
18
- } from '../utils';
19
-
20
- /**
21
- * 路由匹配器
22
- */
23
- class RouteMatcher {
24
- /*
25
- * 路由匹配规则
26
- */
27
- protected routeMatches: RouteMatch[];
28
-
29
- /*
30
- * 原始路由配置
31
- */
32
- // protected routes: RouteConfig[];
33
-
34
- constructor(routes: RouteConfig[]) {
35
- // this.routes = routes;
36
- this.routeMatches = createRouteMatches(routes);
37
- }
38
-
39
- /*
40
- * 根据配置匹配对应的路由
41
- */
42
- public match(
43
- rawLocation: RouterLocation,
44
- {
45
- base,
46
- redirectedFrom
47
- }: { base: string; redirectedFrom?: RouteRecord } = { base: '' }
48
- ): RouteRecord | null {
49
- let path = '';
50
- /* 按 Hanson 要求加入 undefined 类型 */
51
- let query: Record<string, string | undefined> = {};
52
- let queryArray: Record<string, string[]> = {};
53
- let params: Record<string, string> = {};
54
- let hash = '';
55
- let state: HistoryState = {};
56
-
57
- const parsedOption = parsePath(rawLocation.path);
58
- path = parsedOption.pathname;
59
- query = rawLocation.query || parsedOption.query || {};
60
- queryArray = rawLocation.queryArray || parsedOption.queryArray || {};
61
- hash = rawLocation.hash || parsedOption.hash || '';
62
- state = rawLocation.state || {};
63
-
64
- const routeMatch = this.routeMatches.find(({ match }) => {
65
- return match(path);
66
- });
67
-
68
- if (routeMatch) {
69
- const {
70
- component,
71
- asyncComponent,
72
- compile,
73
- meta,
74
- redirect,
75
- matched,
76
- parse
77
- } = routeMatch.internalRedirect || routeMatch; // 优先使用内部重定向
78
-
79
- params = rawLocation.params || parse(path).params || {};
80
-
81
- const realPath = normalizePath(
82
- compile({
83
- query,
84
- queryArray,
85
- params,
86
- hash
87
- })
88
- );
89
-
90
- const {
91
- params: realParams,
92
- query: realQuery,
93
- queryArray: realQueryArray,
94
- hash: realHash
95
- } = parse(realPath);
96
-
97
- const routeRecord = {
98
- base,
99
- path: normalizePath(
100
- compile({
101
- params: realParams
102
- })
103
- ),
104
- fullPath: realPath,
105
- params: realParams,
106
- query: realQuery,
107
- queryArray: realQueryArray,
108
- hash: realHash,
109
- state,
110
- component,
111
- asyncComponent,
112
- meta,
113
- redirect,
114
- redirectedFrom,
115
- matched
116
- };
117
-
118
- if (redirect) {
119
- const normalizedLocation = normalizeLocation(
120
- typeof redirect === 'function'
121
- ? redirect(routeRecord)
122
- : redirect,
123
- base
124
- );
125
- return this.match(normalizedLocation, {
126
- base,
127
- redirectedFrom: routeRecord
128
- });
129
- }
130
- return routeRecord;
131
- }
132
- return null;
133
- }
134
-
135
- /*
136
- * 获取当前路由匹配规则
137
- */
138
- public getRoutes(): RouteMatch[] {
139
- return this.routeMatches;
140
- }
141
-
142
- /**
143
- * 新增单个路由匹配规则
144
- */
145
- // public addRoute(route: RouteConfig) {
146
- // this.routes.push(route);
147
- // this.routeMatches = createRouteMatches(this.routes);
148
- // }
149
-
150
- /**
151
- * 新增多个路由匹配规则
152
- */
153
- // public addRoutes(routes: RouteConfig[]) {
154
- // this.routes.push(...routes);
155
- // this.routeMatches = createRouteMatches(this.routes);
156
- // }
157
- }
158
-
159
- /**
160
- * 创建路由匹配器
161
- */
162
- export function createRouterMatcher(routes: RouteConfig[]): RouterMatcher {
163
- return new RouteMatcher(routes);
164
- }
165
-
166
- /**
167
- * 生成打平的路由匹配规则
168
- */
169
- function createRouteMatches(
170
- routes: RouteConfig[],
171
- parent?: RouteMatch
172
- ): RouteMatch[] {
173
- const routeMatches: RouteMatch[] = [];
174
- for (const route of routes) {
175
- routeMatches.push(
176
- ...createRouteMatch(
177
- {
178
- ...route,
179
- path: Array.isArray(route.path) ? route.path : [route.path]
180
- },
181
- parent
182
- )
183
- );
184
- }
185
- return routeMatches;
186
- }
187
-
188
- /**
189
- * 生成单个路由匹配规则
190
- */
191
- function createRouteMatch(
192
- route: RouteConfig & { path: string },
193
- parent?: RouteMatch
194
- ): RouteMatch;
195
- function createRouteMatch(
196
- route: RouteConfig & { path: string[] },
197
- parent?: RouteMatch
198
- ): RouteMatch[];
199
- function createRouteMatch(
200
- route: RouteConfig,
201
- parent?: RouteMatch
202
- ): RouteMatch | RouteMatch[] {
203
- const pathList = Array.isArray(route.path) ? route.path : [route.path];
204
- const routeMatches: RouteMatch[] = pathList.reduce<RouteMatch[]>(
205
- (acc, item, index) => {
206
- const { children } = route;
207
- const path = normalizePath(item, parent?.path);
208
- let regex: RegExp;
209
- try {
210
- regex = pathToRegexp(path);
211
- } catch (error) {
212
- console.warn(
213
- `@create route rule failed on path: ${path}`,
214
- route
215
- );
216
- return acc;
217
- }
218
- const toPath = compile(path, { encode: encodePath });
219
- const parseParams = match(path, { decode });
220
- const current: RouteMatch = {
221
- regex,
222
- match: (path: string) => {
223
- return regex.test(path);
224
- },
225
- parse: (
226
- path: string
227
- ): {
228
- params: Record<string, string>;
229
- query: Record<string, string>;
230
- queryArray: Record<string, string[]>;
231
- hash: string;
232
- } => {
233
- const { pathname, query, queryArray, hash } =
234
- parsePath(path);
235
- const { params } = parseParams(pathname) || { params: {} };
236
- return {
237
- params: Object.assign({}, params), // parse的 params 是使用 Object.create(null) 创建的没有原型的对象,需要进行包装处理
238
- query,
239
- queryArray,
240
- hash
241
- };
242
- },
243
- compile: (
244
- { params = {}, query = {}, queryArray = {}, hash = '' } = {
245
- params: {},
246
- query: {},
247
- queryArray: {},
248
- hash: ''
249
- }
250
- ) => {
251
- const pathString = toPath(params);
252
- return stringifyPath({
253
- pathname: pathString,
254
- query,
255
- queryArray,
256
- hash
257
- });
258
- },
259
- path,
260
- appType: route.appType || parent?.appType || '',
261
- component: route.component,
262
- asyncComponent: route.asyncComponent,
263
- meta: route.meta || {},
264
- redirect: route.redirect,
265
- /**
266
- * 第一个 path 作为基准,后续 path 会内部重定向到第一个 path
267
- * 同时如果父路由存在内部跳转,子路由也需要处理内部跳转
268
- */
269
- internalRedirect:
270
- index > 0 || parent?.internalRedirect
271
- ? createRouteMatch(
272
- {
273
- ...route,
274
- path: pathList[0]
275
- },
276
- parent?.internalRedirect || parent
277
- )
278
- : undefined,
279
- matched: [...(parent?.matched || []), route]
280
- };
281
- if (children && children.length > 0) {
282
- acc.push(...createRouteMatches(children, current));
283
- }
284
- acc.push(current);
285
- return acc;
286
- },
287
- []
288
- );
289
- return Array.isArray(route.path)
290
- ? routeMatches
291
- : routeMatches[routeMatches.length - 1];
292
- }
@@ -1 +0,0 @@
1
- export { createRouterMatcher } from './create-matcher';
@@ -1 +0,0 @@
1
- export { Tasks, createTasks } from './task';
@@ -1,97 +0,0 @@
1
- import type { Awaitable } from '../types';
2
- import { warn } from '../utils';
3
-
4
- /**
5
- * 创建可操作的任务队列
6
- */
7
-
8
- type func = (...args: any) => any;
9
-
10
- /**
11
- * 任务状态
12
- */
13
- export enum TaskStatus {
14
- INITIAL = 'initial',
15
- RUNNING = 'running',
16
- FINISHED = 'finished',
17
- ERROR = 'error',
18
- ABORTED = 'aborted'
19
- }
20
-
21
- export class Tasks<T extends func = func> {
22
- protected handlers: T[] = [];
23
-
24
- public add(handler: T | T[]) {
25
- const params: T[] = Array.isArray(handler) ? handler : [handler];
26
- this.handlers.push(...params);
27
- }
28
-
29
- public reset() {
30
- this.handlers = [];
31
- }
32
-
33
- get list() {
34
- return this.handlers;
35
- }
36
-
37
- get length() {
38
- return this.handlers.length;
39
- }
40
-
41
- status: TaskStatus = TaskStatus.INITIAL;
42
-
43
- public async run({
44
- cb,
45
- final
46
- }: {
47
- cb?: (res: Awaited<ReturnType<T>>) => Awaitable<void>;
48
- final?: () => Awaitable<void>;
49
- } = {}) {
50
- if (this.status !== 'initial') {
51
- if (process.env.NODE_ENV !== 'production') {
52
- warn(`task start failed in status ${this.status}`);
53
- }
54
- return;
55
- }
56
-
57
- this.status = TaskStatus.RUNNING;
58
-
59
- for await (const handler of this.list) {
60
- if ((this.status as TaskStatus) === TaskStatus.ABORTED) {
61
- return;
62
- }
63
- if (typeof handler === 'function') {
64
- try {
65
- const res = await handler();
66
- cb && (await cb(res));
67
- } catch (error) {
68
- // if (process.env.NODE_ENV !== 'production') {
69
- warn('task error:', error);
70
- // }
71
- this.status = TaskStatus.ERROR;
72
- }
73
- } else {
74
- // if (process.env.NODE_ENV !== 'production') {
75
- warn('task is not a function', handler);
76
- // }
77
- }
78
- }
79
- if ((this.status as TaskStatus) !== TaskStatus.RUNNING) return;
80
- final && (await final());
81
- this.status = TaskStatus.FINISHED;
82
- }
83
-
84
- public abort() {
85
- if (
86
- process.env.NODE_ENV !== 'production' &&
87
- this.status === TaskStatus.RUNNING
88
- ) {
89
- warn('abort task when task is running');
90
- }
91
- this.status = TaskStatus.ABORTED;
92
- }
93
- }
94
-
95
- export function createTasks<T extends func = func>() {
96
- return new Tasks<T>();
97
- }