@native-router/core 1.0.3 → 1.2.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.
- package/README.md +7 -3
- package/dist/index.cjs +107 -25
- package/dist/index.mjs +106 -26
- package/dist/types/errors.d.ts +0 -0
- package/dist/types/index.d.ts +0 -0
- package/dist/types/router.d.ts +35 -7
- package/dist/types/types.d.ts +36 -2
- package/dist/types/util.d.ts +1 -1
- package/dist/util.cjs +0 -0
- package/dist/util.mjs +0 -0
- package/package.json +18 -29
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[](https://www.npmjs.com/package/@native-router/core)
|
|
2
|
-
[](https://github.com/native-router/core/actions)
|
|
3
|
+
[](https://codecov.io/gh/native-router/core)
|
|
4
4
|
[](https://packagephobia.now.sh/result?p=@native-router/core)
|
|
5
5
|
|
|
6
6
|
# Native Router React
|
|
@@ -18,6 +18,10 @@ English | [简体中文](./README-zh_CN.md)
|
|
|
18
18
|
- Most unused features can be tree-shaking
|
|
19
19
|
- SSR support
|
|
20
20
|
|
|
21
|
+
## Matching semantics
|
|
22
|
+
|
|
23
|
+
Routes are matched in declaration order and the first match wins — there is no sorting by specificity. Trailing slashes are significant (`/users/` does not match `/users`). Matching is case-sensitive.
|
|
24
|
+
|
|
21
25
|
## Install
|
|
22
26
|
|
|
23
27
|
```bash
|
|
@@ -76,4 +80,4 @@ See [demos](/demos/) for a complete example.
|
|
|
76
80
|
|
|
77
81
|
## Documentation
|
|
78
82
|
|
|
79
|
-
[API](https://
|
|
83
|
+
[API](https://native-router.github.io/core/modules.html)
|
package/dist/index.cjs
CHANGED
|
@@ -13,6 +13,8 @@ class NotFoundError extends NativeRouterError {
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
const DEFAULT_MAX_STACK_DEPTH = 100;
|
|
17
|
+
|
|
16
18
|
/**
|
|
17
19
|
* Create a router instance.
|
|
18
20
|
* @group Methods
|
|
@@ -26,12 +28,15 @@ class NotFoundError extends NativeRouterError {
|
|
|
26
28
|
function create(routes, history, resolveView, options) {
|
|
27
29
|
const [currentGuard, cancelAll] = util.createCurrentGuard();
|
|
28
30
|
const {
|
|
29
|
-
index
|
|
30
|
-
locationStack
|
|
31
|
+
index
|
|
31
32
|
} = getHistoryState({
|
|
32
33
|
history: history
|
|
33
34
|
});
|
|
34
|
-
|
|
35
|
+
// Restore the session stack from the bounded window serialized in the
|
|
36
|
+
// current entry state; entries before the window become placeholders.
|
|
37
|
+
// Legacy index-only state(1.x) degrades to a single-entry stack.
|
|
38
|
+
const locationStack = restoreLocationStack(history);
|
|
39
|
+
const viewStack = new Array(Math.max(index + 1, locationStack.length)).fill(null);
|
|
35
40
|
if (options?.currentView) {
|
|
36
41
|
viewStack[index] = options.currentView;
|
|
37
42
|
}
|
|
@@ -45,7 +50,8 @@ function create(routes, history, resolveView, options) {
|
|
|
45
50
|
cancelAll,
|
|
46
51
|
errorHandler: util.reject,
|
|
47
52
|
...options,
|
|
48
|
-
baseUrl: options?.baseUrl || ''
|
|
53
|
+
baseUrl: options?.baseUrl || '',
|
|
54
|
+
maxStackDepth: options?.maxStackDepth || DEFAULT_MAX_STACK_DEPTH
|
|
49
55
|
};
|
|
50
56
|
}
|
|
51
57
|
function setOptions(router, options) {
|
|
@@ -60,14 +66,43 @@ function getLocation({
|
|
|
60
66
|
state: state.state
|
|
61
67
|
};
|
|
62
68
|
}
|
|
63
|
-
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Restore the in-memory location stack from the bounded window in the
|
|
72
|
+
* current history entry state. Slots before the window become
|
|
73
|
+
* placeholders(`undefined`) so {@link initHistoryStack} can skip them
|
|
74
|
+
* and a POP onto them still falls back to a lazy refresh.
|
|
75
|
+
*/
|
|
76
|
+
function restoreLocationStack(history) {
|
|
77
|
+
const state = history.location.state || {};
|
|
64
78
|
const {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
79
|
+
locationStack,
|
|
80
|
+
base
|
|
81
|
+
} = state;
|
|
82
|
+
return locationStack?.length ? [...new Array(base || 0), ...locationStack] : [getLocation({
|
|
83
|
+
history
|
|
84
|
+
})];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Serialize the tail window of the in-memory stack, bounded by
|
|
89
|
+
* `maxStackDepth`, together with the absolute index of its first entry.
|
|
90
|
+
*/
|
|
91
|
+
function serializeStack(router) {
|
|
92
|
+
const {
|
|
93
|
+
locationStack,
|
|
94
|
+
maxStackDepth
|
|
95
|
+
} = router;
|
|
96
|
+
const windowed = locationStack.slice(-maxStackDepth);
|
|
97
|
+
return {
|
|
98
|
+
base: locationStack.length - windowed.length,
|
|
99
|
+
locationStack: windowed
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function getHistoryState(router) {
|
|
103
|
+
const state = router.history.location.state || {};
|
|
68
104
|
return {
|
|
69
|
-
index: state.index || 0
|
|
70
|
-
locationStack: state.locationStack || [getLocation(router)]
|
|
105
|
+
index: state.index || 0
|
|
71
106
|
};
|
|
72
107
|
}
|
|
73
108
|
function getCurrentView(router) {
|
|
@@ -189,8 +224,8 @@ function commit(router, resolvePromise, location) {
|
|
|
189
224
|
router.viewStack = [...router.viewStack.slice(0, nextIndex), resolvedView];
|
|
190
225
|
history.push(location, {
|
|
191
226
|
index: nextIndex,
|
|
192
|
-
|
|
193
|
-
|
|
227
|
+
state: location.state,
|
|
228
|
+
...serializeStack(router)
|
|
194
229
|
});
|
|
195
230
|
});
|
|
196
231
|
}
|
|
@@ -215,8 +250,8 @@ function commitReplace(router, resolvePromise, location) {
|
|
|
215
250
|
router.viewStack[index] = resolvedView;
|
|
216
251
|
history.replace(location, {
|
|
217
252
|
index,
|
|
218
|
-
|
|
219
|
-
|
|
253
|
+
state: location.state,
|
|
254
|
+
...serializeStack(router)
|
|
220
255
|
});
|
|
221
256
|
});
|
|
222
257
|
}
|
|
@@ -324,16 +359,21 @@ function cancel({
|
|
|
324
359
|
cancelAll();
|
|
325
360
|
onLoadingChange();
|
|
326
361
|
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Restore/warm up the view stack by re-resolving every reachable entry
|
|
365
|
+
* of the in-memory location stack. Call it after a refresh: in-window
|
|
366
|
+
* back/forward then switch views without new resolves.
|
|
367
|
+
*
|
|
368
|
+
* 恢复/预热内存栈中的可达条目(窗口内有 location 的槽位),刷新后调用
|
|
369
|
+
* 可让窗口内前进/后退零请求。
|
|
370
|
+
* @group Methods
|
|
371
|
+
* @category Router
|
|
372
|
+
* @param router router instance
|
|
373
|
+
*/
|
|
327
374
|
function initHistoryStack(router) {
|
|
328
|
-
|
|
329
|
-
history: history$1
|
|
330
|
-
} = router;
|
|
331
|
-
const {
|
|
332
|
-
locationStack
|
|
333
|
-
} = getHistoryState(router);
|
|
334
|
-
return Promise.all(locationStack.map(l => resolve(router, l))).then(views => {
|
|
375
|
+
return Promise.all(router.locationStack.map(location => location ? resolve(router, location) : Promise.resolve(null))).then(views => {
|
|
335
376
|
router.viewStack = views;
|
|
336
|
-
history$1.replace(history.createPath(history$1.location), history$1.location.state);
|
|
337
377
|
});
|
|
338
378
|
}
|
|
339
379
|
|
|
@@ -358,11 +398,18 @@ function listen(router, onViewChange) {
|
|
|
358
398
|
const index = state?.index || 0;
|
|
359
399
|
const view = router.viewStack[index];
|
|
360
400
|
onViewChange(view);
|
|
361
|
-
if (!view)
|
|
362
|
-
|
|
401
|
+
if (!view) {
|
|
402
|
+
// Lazy fallback for placeholder slots and legacy-shaped state:
|
|
403
|
+
// re-resolving the landed entry also re-serializes the window
|
|
404
|
+
// into it via the replace commit.
|
|
405
|
+
refresh(router);
|
|
406
|
+
} else if (action === 'POP') {
|
|
407
|
+
// Sync the current window into the landed entry so a later
|
|
408
|
+
// refresh("refresh → back → refresh again") still restores it.
|
|
363
409
|
history$1.replace(history.createPath(history$1.location), {
|
|
364
410
|
...state,
|
|
365
|
-
|
|
411
|
+
index,
|
|
412
|
+
...serializeStack(router)
|
|
366
413
|
});
|
|
367
414
|
}
|
|
368
415
|
});
|
|
@@ -373,6 +420,39 @@ function listen(router, onViewChange) {
|
|
|
373
420
|
};
|
|
374
421
|
}
|
|
375
422
|
|
|
423
|
+
/**
|
|
424
|
+
* Merge params of all matched levels. Params of deeper levels override
|
|
425
|
+
* the same keys of shallower ones.
|
|
426
|
+
* @group Methods
|
|
427
|
+
* @category Router
|
|
428
|
+
* @param matched matched route levels, see {@link match}
|
|
429
|
+
* @returns the merged params object
|
|
430
|
+
*/
|
|
431
|
+
function mergeMatchedParams(matched) {
|
|
432
|
+
return matched.reduce((params, {
|
|
433
|
+
params: levelParams
|
|
434
|
+
}) => ({
|
|
435
|
+
...params,
|
|
436
|
+
...levelParams
|
|
437
|
+
}), {});
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Get current route params from router. Merges params of all matched levels.
|
|
442
|
+
* @group Methods
|
|
443
|
+
* @category Router
|
|
444
|
+
* @param router router instance
|
|
445
|
+
* @returns the params object
|
|
446
|
+
*/
|
|
447
|
+
function getParams(router) {
|
|
448
|
+
const {
|
|
449
|
+
index
|
|
450
|
+
} = getHistoryState(router);
|
|
451
|
+
const matched = router.viewStack[index];
|
|
452
|
+
if (!matched || !matched.length) return {};
|
|
453
|
+
return mergeMatchedParams(matched);
|
|
454
|
+
}
|
|
455
|
+
|
|
376
456
|
exports.NativeRouterError = NativeRouterError;
|
|
377
457
|
exports.NotFoundError = NotFoundError;
|
|
378
458
|
exports.back = back;
|
|
@@ -384,10 +464,12 @@ exports.createHref = createHref;
|
|
|
384
464
|
exports.forward = forward;
|
|
385
465
|
exports.getCurrentView = getCurrentView;
|
|
386
466
|
exports.getLocation = getLocation;
|
|
467
|
+
exports.getParams = getParams;
|
|
387
468
|
exports.go = go;
|
|
388
469
|
exports.initHistoryStack = initHistoryStack;
|
|
389
470
|
exports.listen = listen;
|
|
390
471
|
exports.match = match;
|
|
472
|
+
exports.mergeMatchedParams = mergeMatchedParams;
|
|
391
473
|
exports.navigate = navigate;
|
|
392
474
|
exports.refresh = refresh;
|
|
393
475
|
exports.resolve = resolve;
|
package/dist/index.mjs
CHANGED
|
@@ -11,6 +11,8 @@ class NotFoundError extends NativeRouterError {
|
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
const DEFAULT_MAX_STACK_DEPTH = 100;
|
|
15
|
+
|
|
14
16
|
/**
|
|
15
17
|
* Create a router instance.
|
|
16
18
|
* @group Methods
|
|
@@ -24,12 +26,15 @@ class NotFoundError extends NativeRouterError {
|
|
|
24
26
|
function create(routes, history, resolveView, options) {
|
|
25
27
|
const [currentGuard, cancelAll] = createCurrentGuard();
|
|
26
28
|
const {
|
|
27
|
-
index
|
|
28
|
-
locationStack
|
|
29
|
+
index
|
|
29
30
|
} = getHistoryState({
|
|
30
31
|
history: history
|
|
31
32
|
});
|
|
32
|
-
|
|
33
|
+
// Restore the session stack from the bounded window serialized in the
|
|
34
|
+
// current entry state; entries before the window become placeholders.
|
|
35
|
+
// Legacy index-only state(1.x) degrades to a single-entry stack.
|
|
36
|
+
const locationStack = restoreLocationStack(history);
|
|
37
|
+
const viewStack = new Array(Math.max(index + 1, locationStack.length)).fill(null);
|
|
33
38
|
if (options?.currentView) {
|
|
34
39
|
viewStack[index] = options.currentView;
|
|
35
40
|
}
|
|
@@ -43,7 +48,8 @@ function create(routes, history, resolveView, options) {
|
|
|
43
48
|
cancelAll,
|
|
44
49
|
errorHandler: reject,
|
|
45
50
|
...options,
|
|
46
|
-
baseUrl: options?.baseUrl || ''
|
|
51
|
+
baseUrl: options?.baseUrl || '',
|
|
52
|
+
maxStackDepth: options?.maxStackDepth || DEFAULT_MAX_STACK_DEPTH
|
|
47
53
|
};
|
|
48
54
|
}
|
|
49
55
|
function setOptions(router, options) {
|
|
@@ -58,14 +64,43 @@ function getLocation({
|
|
|
58
64
|
state: state.state
|
|
59
65
|
};
|
|
60
66
|
}
|
|
61
|
-
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Restore the in-memory location stack from the bounded window in the
|
|
70
|
+
* current history entry state. Slots before the window become
|
|
71
|
+
* placeholders(`undefined`) so {@link initHistoryStack} can skip them
|
|
72
|
+
* and a POP onto them still falls back to a lazy refresh.
|
|
73
|
+
*/
|
|
74
|
+
function restoreLocationStack(history) {
|
|
75
|
+
const state = history.location.state || {};
|
|
62
76
|
const {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
77
|
+
locationStack,
|
|
78
|
+
base
|
|
79
|
+
} = state;
|
|
80
|
+
return locationStack?.length ? [...new Array(base || 0), ...locationStack] : [getLocation({
|
|
81
|
+
history
|
|
82
|
+
})];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Serialize the tail window of the in-memory stack, bounded by
|
|
87
|
+
* `maxStackDepth`, together with the absolute index of its first entry.
|
|
88
|
+
*/
|
|
89
|
+
function serializeStack(router) {
|
|
90
|
+
const {
|
|
91
|
+
locationStack,
|
|
92
|
+
maxStackDepth
|
|
93
|
+
} = router;
|
|
94
|
+
const windowed = locationStack.slice(-maxStackDepth);
|
|
95
|
+
return {
|
|
96
|
+
base: locationStack.length - windowed.length,
|
|
97
|
+
locationStack: windowed
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function getHistoryState(router) {
|
|
101
|
+
const state = router.history.location.state || {};
|
|
66
102
|
return {
|
|
67
|
-
index: state.index || 0
|
|
68
|
-
locationStack: state.locationStack || [getLocation(router)]
|
|
103
|
+
index: state.index || 0
|
|
69
104
|
};
|
|
70
105
|
}
|
|
71
106
|
function getCurrentView(router) {
|
|
@@ -187,8 +222,8 @@ function commit(router, resolvePromise, location) {
|
|
|
187
222
|
router.viewStack = [...router.viewStack.slice(0, nextIndex), resolvedView];
|
|
188
223
|
history.push(location, {
|
|
189
224
|
index: nextIndex,
|
|
190
|
-
|
|
191
|
-
|
|
225
|
+
state: location.state,
|
|
226
|
+
...serializeStack(router)
|
|
192
227
|
});
|
|
193
228
|
});
|
|
194
229
|
}
|
|
@@ -213,8 +248,8 @@ function commitReplace(router, resolvePromise, location) {
|
|
|
213
248
|
router.viewStack[index] = resolvedView;
|
|
214
249
|
history.replace(location, {
|
|
215
250
|
index,
|
|
216
|
-
|
|
217
|
-
|
|
251
|
+
state: location.state,
|
|
252
|
+
...serializeStack(router)
|
|
218
253
|
});
|
|
219
254
|
});
|
|
220
255
|
}
|
|
@@ -322,16 +357,21 @@ function cancel({
|
|
|
322
357
|
cancelAll();
|
|
323
358
|
onLoadingChange();
|
|
324
359
|
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Restore/warm up the view stack by re-resolving every reachable entry
|
|
363
|
+
* of the in-memory location stack. Call it after a refresh: in-window
|
|
364
|
+
* back/forward then switch views without new resolves.
|
|
365
|
+
*
|
|
366
|
+
* 恢复/预热内存栈中的可达条目(窗口内有 location 的槽位),刷新后调用
|
|
367
|
+
* 可让窗口内前进/后退零请求。
|
|
368
|
+
* @group Methods
|
|
369
|
+
* @category Router
|
|
370
|
+
* @param router router instance
|
|
371
|
+
*/
|
|
325
372
|
function initHistoryStack(router) {
|
|
326
|
-
|
|
327
|
-
history
|
|
328
|
-
} = router;
|
|
329
|
-
const {
|
|
330
|
-
locationStack
|
|
331
|
-
} = getHistoryState(router);
|
|
332
|
-
return Promise.all(locationStack.map(l => resolve(router, l))).then(views => {
|
|
373
|
+
return Promise.all(router.locationStack.map(location => location ? resolve(router, location) : Promise.resolve(null))).then(views => {
|
|
333
374
|
router.viewStack = views;
|
|
334
|
-
history.replace(createPath(history.location), history.location.state);
|
|
335
375
|
});
|
|
336
376
|
}
|
|
337
377
|
|
|
@@ -356,11 +396,18 @@ function listen(router, onViewChange) {
|
|
|
356
396
|
const index = state?.index || 0;
|
|
357
397
|
const view = router.viewStack[index];
|
|
358
398
|
onViewChange(view);
|
|
359
|
-
if (!view)
|
|
360
|
-
|
|
399
|
+
if (!view) {
|
|
400
|
+
// Lazy fallback for placeholder slots and legacy-shaped state:
|
|
401
|
+
// re-resolving the landed entry also re-serializes the window
|
|
402
|
+
// into it via the replace commit.
|
|
403
|
+
refresh(router);
|
|
404
|
+
} else if (action === 'POP') {
|
|
405
|
+
// Sync the current window into the landed entry so a later
|
|
406
|
+
// refresh("refresh → back → refresh again") still restores it.
|
|
361
407
|
history.replace(createPath(history.location), {
|
|
362
408
|
...state,
|
|
363
|
-
|
|
409
|
+
index,
|
|
410
|
+
...serializeStack(router)
|
|
364
411
|
});
|
|
365
412
|
}
|
|
366
413
|
});
|
|
@@ -371,4 +418,37 @@ function listen(router, onViewChange) {
|
|
|
371
418
|
};
|
|
372
419
|
}
|
|
373
420
|
|
|
374
|
-
|
|
421
|
+
/**
|
|
422
|
+
* Merge params of all matched levels. Params of deeper levels override
|
|
423
|
+
* the same keys of shallower ones.
|
|
424
|
+
* @group Methods
|
|
425
|
+
* @category Router
|
|
426
|
+
* @param matched matched route levels, see {@link match}
|
|
427
|
+
* @returns the merged params object
|
|
428
|
+
*/
|
|
429
|
+
function mergeMatchedParams(matched) {
|
|
430
|
+
return matched.reduce((params, {
|
|
431
|
+
params: levelParams
|
|
432
|
+
}) => ({
|
|
433
|
+
...params,
|
|
434
|
+
...levelParams
|
|
435
|
+
}), {});
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Get current route params from router. Merges params of all matched levels.
|
|
440
|
+
* @group Methods
|
|
441
|
+
* @category Router
|
|
442
|
+
* @param router router instance
|
|
443
|
+
* @returns the params object
|
|
444
|
+
*/
|
|
445
|
+
function getParams(router) {
|
|
446
|
+
const {
|
|
447
|
+
index
|
|
448
|
+
} = getHistoryState(router);
|
|
449
|
+
const matched = router.viewStack[index];
|
|
450
|
+
if (!matched || !matched.length) return {};
|
|
451
|
+
return mergeMatchedParams(matched);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
export { NativeRouterError, NotFoundError, back, cancel, commit, commitReplace, create, createHref, forward, getCurrentView, getLocation, getParams, go, initHistoryStack, listen, match, mergeMatchedParams, navigate, refresh, resolve, resolveTo, setOptions, toLocation };
|
package/dist/types/errors.d.ts
CHANGED
|
File without changes
|
package/dist/types/index.d.ts
CHANGED
|
File without changes
|
package/dist/types/router.d.ts
CHANGED
|
@@ -18,18 +18,18 @@ export declare function setOptions<R extends BaseRoute = BaseRoute, V = any>(rou
|
|
|
18
18
|
location: import("./types").WrappedLocation;
|
|
19
19
|
};
|
|
20
20
|
viewStack: V[];
|
|
21
|
-
locationStack: Location
|
|
21
|
+
locationStack: Location[];
|
|
22
22
|
resolveView: ResolveView<R, V>;
|
|
23
23
|
currentGuard<T>(promise: Promise<T>): Promise<T>;
|
|
24
24
|
cancelAll(): void;
|
|
25
|
-
resolving?: Location
|
|
26
|
-
} & Required<Pick<Options<V>, "baseUrl">> & Omit<Options<V>, "baseUrl"> & Omit<Options<V>, "currentView">;
|
|
25
|
+
resolving?: Location;
|
|
26
|
+
} & Required<Pick<Options<V>, "baseUrl" | "maxStackDepth">> & Omit<Options<V>, "baseUrl" | "maxStackDepth"> & Omit<Options<V>, "currentView">;
|
|
27
27
|
export declare function getLocation({ history }: Pick<RouterInstance<any>, 'history'>): {
|
|
28
28
|
state: any;
|
|
29
|
-
key:
|
|
30
|
-
pathname:
|
|
31
|
-
search:
|
|
32
|
-
hash:
|
|
29
|
+
key: import("history").Key;
|
|
30
|
+
pathname: import("history").Pathname;
|
|
31
|
+
search: import("history").Search;
|
|
32
|
+
hash: import("history").Hash;
|
|
33
33
|
};
|
|
34
34
|
export declare function getCurrentView<R extends BaseRoute = BaseRoute>(router: RouterInstance<R>): any;
|
|
35
35
|
/**
|
|
@@ -142,6 +142,17 @@ export declare function createHref<R extends BaseRoute = BaseRoute, V = any>({ b
|
|
|
142
142
|
* @param router router instance
|
|
143
143
|
*/
|
|
144
144
|
export declare function cancel<R extends BaseRoute = BaseRoute, V = any>({ cancelAll, onLoadingChange }: RouterInstance<R, V>): void;
|
|
145
|
+
/**
|
|
146
|
+
* Restore/warm up the view stack by re-resolving every reachable entry
|
|
147
|
+
* of the in-memory location stack. Call it after a refresh: in-window
|
|
148
|
+
* back/forward then switch views without new resolves.
|
|
149
|
+
*
|
|
150
|
+
* 恢复/预热内存栈中的可达条目(窗口内有 location 的槽位),刷新后调用
|
|
151
|
+
* 可让窗口内前进/后退零请求。
|
|
152
|
+
* @group Methods
|
|
153
|
+
* @category Router
|
|
154
|
+
* @param router router instance
|
|
155
|
+
*/
|
|
145
156
|
export declare function initHistoryStack<R extends BaseRoute = BaseRoute, V = any>(router: RouterInstance<R, V>): Promise<void>;
|
|
146
157
|
/**
|
|
147
158
|
* Listen the history change.
|
|
@@ -152,3 +163,20 @@ export declare function initHistoryStack<R extends BaseRoute = BaseRoute, V = an
|
|
|
152
163
|
* @returns unlisten - A function that may be used to stop listening
|
|
153
164
|
*/
|
|
154
165
|
export declare function listen<R extends BaseRoute = BaseRoute, V = any>(router: RouterInstance<R, V>, onViewChange: (v: V) => void): () => void;
|
|
166
|
+
/**
|
|
167
|
+
* Merge params of all matched levels. Params of deeper levels override
|
|
168
|
+
* the same keys of shallower ones.
|
|
169
|
+
* @group Methods
|
|
170
|
+
* @category Router
|
|
171
|
+
* @param matched matched route levels, see {@link match}
|
|
172
|
+
* @returns the merged params object
|
|
173
|
+
*/
|
|
174
|
+
export declare function mergeMatchedParams<R extends BaseRoute = BaseRoute>(matched: Matched<R>[]): Record<string, string>;
|
|
175
|
+
/**
|
|
176
|
+
* Get current route params from router. Merges params of all matched levels.
|
|
177
|
+
* @group Methods
|
|
178
|
+
* @category Router
|
|
179
|
+
* @param router router instance
|
|
180
|
+
* @returns the params object
|
|
181
|
+
*/
|
|
182
|
+
export declare function getParams<R extends BaseRoute = BaseRoute>(router: RouterInstance<R>): Record<string, string>;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -4,9 +4,21 @@ export type Location<T = any> = HPath & {
|
|
|
4
4
|
state?: T;
|
|
5
5
|
};
|
|
6
6
|
export type HistoryState = {
|
|
7
|
-
locationStack: Location[];
|
|
8
7
|
index: number;
|
|
9
8
|
state?: any;
|
|
9
|
+
/**
|
|
10
|
+
* Bounded window(tail entries) of the session location stack,
|
|
11
|
+
* serialized into the history entry so {@link create} can restore it
|
|
12
|
+
* after a refresh. Its length never exceeds `maxStackDepth`.
|
|
13
|
+
* 有界窗口:会话 locationStack 的尾部条目,刷新后据此恢复内存栈。
|
|
14
|
+
*/
|
|
15
|
+
locationStack?: Location[];
|
|
16
|
+
/**
|
|
17
|
+
* Absolute stack index of `locationStack[0]`; omitted(or 0) means the
|
|
18
|
+
* window starts at the session root.
|
|
19
|
+
* locationStack[0] 对应的绝对 index,省略时为 0。
|
|
20
|
+
*/
|
|
21
|
+
base?: number;
|
|
10
22
|
};
|
|
11
23
|
export type WrappedLocation = Location<HistoryState>;
|
|
12
24
|
export type Awaitable<T> = T | Promise<T>;
|
|
@@ -27,6 +39,22 @@ export type Options<V> = {
|
|
|
27
39
|
currentView?: V;
|
|
28
40
|
errorHandler?(e: Error): V | Promise<V>;
|
|
29
41
|
onLoadingChange?(status?: 'pending' | 'resolved' | 'rejected'): void;
|
|
42
|
+
/**
|
|
43
|
+
* Max number of locations serialized into the history state window,
|
|
44
|
+
* see {@link HistoryState.locationStack}.
|
|
45
|
+
*
|
|
46
|
+
* Defaults to 100, at or above the per-tab history caps of mainstream
|
|
47
|
+
* browsers(Chromium/Gecko ~50, WebKit ~100). The window boundary can
|
|
48
|
+
* therefore only appear after the browser itself has already evicted
|
|
49
|
+
* entries: anything outside the window is unreachable to the user, so
|
|
50
|
+
* a bounded window is observationally equivalent to full serialization.
|
|
51
|
+
*
|
|
52
|
+
* 序列化进 history state 的栈窗口上限,默认 100,不低于主流浏览器
|
|
53
|
+
* 单标签历史上限(Chromium/Gecko 约 50、WebKit 约 100)。窗口边界只会在
|
|
54
|
+
* 浏览器自身裁剪历史之后才可能出现,用户不可达窗口外条目,行为与
|
|
55
|
+
* 全量序列化无可观察差异。
|
|
56
|
+
*/
|
|
57
|
+
maxStackDepth?: number;
|
|
30
58
|
};
|
|
31
59
|
export type RequiredOf<T, K extends keyof T> = Required<Pick<T, K>> & Omit<T, K>;
|
|
32
60
|
export type RouterInstance<R extends BaseRoute, V = any> = {
|
|
@@ -36,9 +64,15 @@ export type RouterInstance<R extends BaseRoute, V = any> = {
|
|
|
36
64
|
location: WrappedLocation;
|
|
37
65
|
};
|
|
38
66
|
viewStack: V[];
|
|
67
|
+
/**
|
|
68
|
+
* In-memory location stack of the current session. On creation it is
|
|
69
|
+
* restored from the bounded window serialized in the history state,
|
|
70
|
+
* so in-window back/forward survive a refresh.
|
|
71
|
+
* 会话内存栈;create 时从 history state 的有界窗口恢复。
|
|
72
|
+
*/
|
|
39
73
|
locationStack: Location[];
|
|
40
74
|
resolveView: ResolveView<R, V>;
|
|
41
75
|
currentGuard<T>(promise: Promise<T>): Promise<T>;
|
|
42
76
|
cancelAll(): void;
|
|
43
77
|
resolving?: Location;
|
|
44
|
-
} & RequiredOf<Options<V>, 'baseUrl'>;
|
|
78
|
+
} & RequiredOf<Options<V>, 'baseUrl' | 'maxStackDepth'>;
|
package/dist/types/util.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export declare function noop(): void;
|
|
|
3
3
|
export declare const resolve: {
|
|
4
4
|
(): Promise<void>;
|
|
5
5
|
<T>(value: T): Promise<Awaited<T>>;
|
|
6
|
-
<
|
|
6
|
+
<T>(value: T | PromiseLike<T>): Promise<Awaited<T>>;
|
|
7
7
|
};
|
|
8
8
|
export declare const reject: <T = never>(reason?: any) => Promise<T>;
|
|
9
9
|
export declare function cancelPromise(): Promise<unknown>;
|
package/dist/util.cjs
CHANGED
|
File without changes
|
package/dist/util.mjs
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@native-router/core",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"exports": {
|
|
5
5
|
".": {
|
|
6
|
+
"types": "./dist/types/index.d.ts",
|
|
6
7
|
"import": "./dist/index.mjs",
|
|
7
|
-
"require": "./dist/index.cjs"
|
|
8
|
-
"types": "./dist/types/index.d.ts"
|
|
8
|
+
"require": "./dist/index.cjs"
|
|
9
9
|
},
|
|
10
10
|
"./util": {
|
|
11
|
+
"types": "./dist/types/util.d.ts",
|
|
11
12
|
"import": "./dist/util.mjs",
|
|
12
|
-
"require": "./dist/util.cjs"
|
|
13
|
-
"types": "./dist/types/util.d.ts"
|
|
13
|
+
"require": "./dist/util.cjs"
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"types": "./dist/types/index.d.ts",
|
|
@@ -27,31 +27,28 @@
|
|
|
27
27
|
"dist"
|
|
28
28
|
],
|
|
29
29
|
"scripts": {
|
|
30
|
-
"start": "
|
|
30
|
+
"start": "vitest",
|
|
31
31
|
"build": "rm -rf dist && rollup -c && tsc -p tsconfig.production.json && tsc-alias -p tsconfig.production.json",
|
|
32
32
|
"commit": "lint-staged && git-cz -n",
|
|
33
|
-
"coverage": "
|
|
34
|
-
"lint": "eslint --fix src test
|
|
33
|
+
"coverage": "vitest run --coverage",
|
|
34
|
+
"lint": "eslint --fix src test *.js --ext .js,.jsx,.ts,.tsx",
|
|
35
35
|
"doc:gen": "typedoc",
|
|
36
36
|
"deploy": "npm run doc:gen && gh-pages -d dist",
|
|
37
|
-
"test": "
|
|
38
|
-
"preversion": "npm run build",
|
|
39
|
-
"postversion": "npm publish",
|
|
40
|
-
"postpublish": "git push --follow-tags && npm run deploy"
|
|
37
|
+
"test": "vitest run"
|
|
41
38
|
},
|
|
42
39
|
"repository": {
|
|
43
40
|
"type": "git",
|
|
44
|
-
"url": "https://github.com/
|
|
41
|
+
"url": "git+https://github.com/native-router/core.git"
|
|
45
42
|
},
|
|
46
43
|
"sideEffects": false,
|
|
47
44
|
"author": "wmzy",
|
|
48
45
|
"license": "MIT",
|
|
49
46
|
"bugs": {
|
|
50
|
-
"url": "https://github.com/
|
|
47
|
+
"url": "https://github.com/native-router/core/issues"
|
|
51
48
|
},
|
|
52
|
-
"homepage": "https://github.com/
|
|
49
|
+
"homepage": "https://github.com/native-router/core",
|
|
53
50
|
"engines": {
|
|
54
|
-
"node": ">=
|
|
51
|
+
"node": ">=18"
|
|
55
52
|
},
|
|
56
53
|
"dependencies": {
|
|
57
54
|
"history": "^5.3.0",
|
|
@@ -61,24 +58,19 @@
|
|
|
61
58
|
"@babel/core": "^7.22.9",
|
|
62
59
|
"@babel/preset-env": "^7.22.9",
|
|
63
60
|
"@babel/preset-typescript": "^7.22.5",
|
|
64
|
-
"@babel/register": "^7.22.5",
|
|
65
|
-
"@linaria/babel-preset": "^4.5.4",
|
|
66
|
-
"@linaria/core": "^4.5.4",
|
|
67
61
|
"@rollup/plugin-babel": "^6.0.3",
|
|
68
62
|
"@rollup/plugin-commonjs": "^25.0.4",
|
|
69
63
|
"@rollup/plugin-node-resolve": "^15.1.0",
|
|
70
64
|
"@rollup/plugin-replace": "^5.0.2",
|
|
71
|
-
"@types/mocha": "^10.0.1",
|
|
72
65
|
"@types/node": "^20.4.5",
|
|
73
66
|
"@types/sinon": "^10.0.15",
|
|
74
67
|
"@typescript-eslint/eslint-plugin": "^6.2.0",
|
|
75
68
|
"@typescript-eslint/parser": "^6.2.0",
|
|
76
|
-
"
|
|
69
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
77
70
|
"commitizen": "^4.3.0",
|
|
78
71
|
"core-js": "^3.31.1",
|
|
79
|
-
"coveralls": "^3.1.1",
|
|
80
72
|
"cross-env": "^7.0.3",
|
|
81
|
-
"eslint": "^8.
|
|
73
|
+
"eslint": "^8.50.0",
|
|
82
74
|
"eslint-config-airbnb": "^19.0.4",
|
|
83
75
|
"eslint-config-airbnb-typescript": "^17.1.0",
|
|
84
76
|
"eslint-config-prettier": "^8.8.0",
|
|
@@ -86,17 +78,12 @@
|
|
|
86
78
|
"eslint-plugin-compat": "^4.1.4",
|
|
87
79
|
"eslint-plugin-import": "^2.27.5",
|
|
88
80
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
|
89
|
-
"eslint-plugin-mocha": "^10.1.0",
|
|
90
81
|
"eslint-plugin-prettier": "^5.0.0",
|
|
91
82
|
"eslint-plugin-react": "^7.33.0",
|
|
92
83
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
93
84
|
"gh-pages": "^5.0.0",
|
|
94
|
-
"global-jsdom": "^9.0.1",
|
|
95
85
|
"husky": "^8.0.3",
|
|
96
|
-
"jsdom": "^22.1.0",
|
|
97
86
|
"lint-staged": "^13.2.3",
|
|
98
|
-
"mocha": "^10.2.0",
|
|
99
|
-
"nyc": "^15.1.0",
|
|
100
87
|
"prettier": "^3.0.0",
|
|
101
88
|
"rollup": "^3.28.0",
|
|
102
89
|
"should": "^13.2.3",
|
|
@@ -107,6 +94,8 @@
|
|
|
107
94
|
"typedoc": "^0.24.8",
|
|
108
95
|
"typedoc-plugin-mark-react-functional-components": "^0.2.2",
|
|
109
96
|
"typedoc-plugin-missing-exports": "^2.0.0",
|
|
110
|
-
"typescript": "^5.
|
|
97
|
+
"typescript": "^5.9.3",
|
|
98
|
+
"vitest": "^4.0.18",
|
|
99
|
+
"semantic-release": "^25.0.3"
|
|
111
100
|
}
|
|
112
101
|
}
|