@esmx/router 3.0.0-rc.12 → 3.0.0-rc.120
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 +158 -0
- package/README.zh-CN.md +158 -0
- package/dist/error.d.ts +23 -0
- package/dist/error.mjs +64 -0
- package/dist/increment-id.d.ts +7 -0
- package/dist/increment-id.mjs +16 -0
- package/dist/index.d.ts +14 -3
- package/dist/index.mjs +13 -3
- package/dist/location.d.ts +22 -0
- package/dist/location.mjs +64 -0
- package/dist/matcher.d.ts +4 -0
- package/dist/matcher.mjs +49 -0
- package/dist/micro-app.d.ts +20 -0
- package/dist/micro-app.mjs +132 -0
- package/dist/navigation.d.ts +45 -0
- package/dist/navigation.mjs +153 -0
- package/dist/options.d.ts +4 -0
- package/dist/options.mjs +95 -0
- package/dist/route-task.d.ts +40 -0
- package/dist/route-task.mjs +77 -0
- package/dist/route-transition.d.ts +54 -0
- package/dist/route-transition.mjs +362 -0
- package/dist/route.d.ts +77 -0
- package/dist/route.mjs +223 -0
- package/dist/router-link.d.ts +10 -0
- package/dist/router-link.mjs +142 -0
- package/dist/router.d.ts +113 -102
- package/dist/router.mjs +321 -354
- package/dist/scroll.d.ts +33 -0
- package/dist/scroll.mjs +50 -0
- package/dist/types.d.ts +312 -0
- package/dist/types.mjs +18 -0
- package/dist/util.d.ts +32 -0
- package/dist/util.mjs +100 -0
- package/package.json +42 -15
- package/src/error.ts +84 -0
- package/src/increment-id.ts +12 -0
- package/src/index.ts +67 -3
- package/src/location.ts +124 -0
- package/src/matcher.ts +71 -0
- package/src/micro-app.ts +153 -0
- package/src/navigation.ts +202 -0
- package/src/options.ts +136 -0
- package/src/route-task.ts +102 -0
- package/src/route-transition.ts +480 -0
- package/src/route.ts +335 -0
- package/src/router-link.ts +241 -0
- package/src/router.ts +351 -467
- package/src/scroll.ts +106 -0
- package/src/types.ts +415 -0
- package/src/util.ts +184 -0
- package/dist/history/abstract.d.ts +0 -29
- package/dist/history/abstract.mjs +0 -107
- package/dist/history/base.d.ts +0 -79
- package/dist/history/base.mjs +0 -275
- package/dist/history/html.d.ts +0 -22
- package/dist/history/html.mjs +0 -181
- package/dist/history/index.d.ts +0 -7
- package/dist/history/index.mjs +0 -16
- package/dist/matcher/create-matcher.d.ts +0 -5
- package/dist/matcher/create-matcher.mjs +0 -218
- package/dist/matcher/create-matcher.spec.d.ts +0 -1
- package/dist/matcher/create-matcher.spec.mjs +0 -0
- package/dist/matcher/index.d.ts +0 -1
- package/dist/matcher/index.mjs +0 -1
- package/dist/task-pipe/index.d.ts +0 -1
- package/dist/task-pipe/index.mjs +0 -1
- package/dist/task-pipe/task.d.ts +0 -30
- package/dist/task-pipe/task.mjs +0 -66
- package/dist/utils/bom.d.ts +0 -5
- package/dist/utils/bom.mjs +0 -10
- package/dist/utils/encoding.d.ts +0 -48
- package/dist/utils/encoding.mjs +0 -44
- package/dist/utils/guards.d.ts +0 -9
- package/dist/utils/guards.mjs +0 -12
- package/dist/utils/index.d.ts +0 -7
- package/dist/utils/index.mjs +0 -27
- package/dist/utils/path.d.ts +0 -60
- package/dist/utils/path.mjs +0 -264
- package/dist/utils/path.spec.d.ts +0 -1
- package/dist/utils/path.spec.mjs +0 -30
- package/dist/utils/scroll.d.ts +0 -25
- package/dist/utils/scroll.mjs +0 -59
- package/dist/utils/utils.d.ts +0 -16
- package/dist/utils/utils.mjs +0 -11
- package/dist/utils/warn.d.ts +0 -2
- package/dist/utils/warn.mjs +0 -12
- package/src/history/abstract.ts +0 -149
- package/src/history/base.ts +0 -408
- package/src/history/html.ts +0 -231
- package/src/history/index.ts +0 -20
- package/src/matcher/create-matcher.spec.ts +0 -3
- package/src/matcher/create-matcher.ts +0 -293
- package/src/matcher/index.ts +0 -1
- package/src/task-pipe/index.ts +0 -1
- package/src/task-pipe/task.ts +0 -97
- package/src/utils/bom.ts +0 -14
- package/src/utils/encoding.ts +0 -153
- package/src/utils/guards.ts +0 -25
- package/src/utils/index.ts +0 -27
- package/src/utils/path.spec.ts +0 -44
- package/src/utils/path.ts +0 -397
- package/src/utils/scroll.ts +0 -120
- package/src/utils/utils.ts +0 -30
- package/src/utils/warn.ts +0 -13
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
import { isBrowser, isPlainObject } from "./util.mjs";
|
|
5
|
+
export function getRootElement(appId) {
|
|
6
|
+
const el = document.getElementById(appId);
|
|
7
|
+
if (el) {
|
|
8
|
+
return el;
|
|
9
|
+
}
|
|
10
|
+
const newEl = document.createElement("div");
|
|
11
|
+
newEl.id = appId;
|
|
12
|
+
document.body.appendChild(newEl);
|
|
13
|
+
return newEl;
|
|
14
|
+
}
|
|
15
|
+
export class MicroApp {
|
|
16
|
+
constructor() {
|
|
17
|
+
__publicField(this, "app", null);
|
|
18
|
+
__publicField(this, "root", null);
|
|
19
|
+
__publicField(this, "_factory", null);
|
|
20
|
+
__publicField(this, "destroyed", false);
|
|
21
|
+
}
|
|
22
|
+
_update(router, force = false) {
|
|
23
|
+
if (this.destroyed) {
|
|
24
|
+
throw new Error("MicroApp has been destroyed");
|
|
25
|
+
}
|
|
26
|
+
const factory = this._getNextFactory(router);
|
|
27
|
+
if (!force && factory === this._factory) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const oldApp = this.app;
|
|
31
|
+
const app = factory ? factory(router) : null;
|
|
32
|
+
if (isBrowser && app) {
|
|
33
|
+
let root = this.root;
|
|
34
|
+
if (root === null) {
|
|
35
|
+
root = getRootElement(router.appId);
|
|
36
|
+
const { rootStyle } = router.parsedOptions;
|
|
37
|
+
if (root && isPlainObject(rootStyle)) {
|
|
38
|
+
Object.assign(root.style, router.parsedOptions.rootStyle);
|
|
39
|
+
}
|
|
40
|
+
this.root = root;
|
|
41
|
+
}
|
|
42
|
+
if (root) {
|
|
43
|
+
const isHydration = root.hasAttribute("data-ssr");
|
|
44
|
+
if (isHydration) {
|
|
45
|
+
const appRoot = root.firstElementChild;
|
|
46
|
+
if (appRoot) {
|
|
47
|
+
if (app.hydration) {
|
|
48
|
+
app.hydration(appRoot);
|
|
49
|
+
} else {
|
|
50
|
+
throw new Error(
|
|
51
|
+
"SSR content detected but hydration function not provided"
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
const el = document.createElement("div");
|
|
56
|
+
root.appendChild(el);
|
|
57
|
+
try {
|
|
58
|
+
app.mount(el);
|
|
59
|
+
} catch (e) {
|
|
60
|
+
el.remove();
|
|
61
|
+
throw e;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
root.removeAttribute("data-ssr");
|
|
65
|
+
} else {
|
|
66
|
+
const oldChildren = Array.from(root.childNodes);
|
|
67
|
+
const el = document.createElement("div");
|
|
68
|
+
root.appendChild(el);
|
|
69
|
+
try {
|
|
70
|
+
app.mount(el);
|
|
71
|
+
} catch (e) {
|
|
72
|
+
el.remove();
|
|
73
|
+
throw e;
|
|
74
|
+
}
|
|
75
|
+
if (oldApp) {
|
|
76
|
+
try {
|
|
77
|
+
oldApp.unmount();
|
|
78
|
+
} catch (e) {
|
|
79
|
+
console.error(
|
|
80
|
+
"[@esmx/router] MicroApp unmount failed during route transition. Check the framework unmount hook returned by your render function (Vue: app.unmount, React: root.unmount, etc.).",
|
|
81
|
+
e
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
oldChildren.forEach((child) => {
|
|
86
|
+
if (child.parentNode) {
|
|
87
|
+
child.remove();
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
this.app = app;
|
|
94
|
+
this._factory = factory;
|
|
95
|
+
}
|
|
96
|
+
_getNextFactory({
|
|
97
|
+
route,
|
|
98
|
+
options
|
|
99
|
+
}) {
|
|
100
|
+
if (!route.matched || route.matched.length === 0) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
const name = route.matched[0].app;
|
|
104
|
+
if (typeof name === "string" && options.apps && typeof options.apps === "object") {
|
|
105
|
+
return options.apps[name] || null;
|
|
106
|
+
}
|
|
107
|
+
if (typeof name === "function") {
|
|
108
|
+
return name;
|
|
109
|
+
}
|
|
110
|
+
if (typeof options.apps === "function") {
|
|
111
|
+
return options.apps;
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
destroy() {
|
|
116
|
+
var _a;
|
|
117
|
+
(_a = this.app) == null ? void 0 : _a.unmount();
|
|
118
|
+
this._clearRoot();
|
|
119
|
+
this.app = null;
|
|
120
|
+
this.root = null;
|
|
121
|
+
this._factory = null;
|
|
122
|
+
this.destroyed = true;
|
|
123
|
+
}
|
|
124
|
+
_clearRoot() {
|
|
125
|
+
if (!this.root) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
Array.from(this.root.childNodes).forEach((child) => {
|
|
129
|
+
child.remove();
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { RouterParsedOptions, RouteState } from './types';
|
|
2
|
+
type NavigationSubscribe = (url: string, state: RouteState) => void;
|
|
3
|
+
type NavigationGoResult = null | {
|
|
4
|
+
type: 'success';
|
|
5
|
+
url: string;
|
|
6
|
+
state: RouteState;
|
|
7
|
+
};
|
|
8
|
+
export declare class Navigation {
|
|
9
|
+
readonly options: RouterParsedOptions;
|
|
10
|
+
private readonly _history;
|
|
11
|
+
private readonly _unSubscribePopState;
|
|
12
|
+
private _promiseResolve;
|
|
13
|
+
constructor(options: RouterParsedOptions, onUpdated?: NavigationSubscribe);
|
|
14
|
+
get length(): number;
|
|
15
|
+
private _push;
|
|
16
|
+
private _replace;
|
|
17
|
+
push(data: any, url?: string | URL | null): RouteState;
|
|
18
|
+
replace(data: any, url?: string | URL | null): RouteState;
|
|
19
|
+
pushHistoryState(data: any, url?: string | URL | null): void;
|
|
20
|
+
replaceHistoryState(data: any, url?: string | URL | null): void;
|
|
21
|
+
backHistoryState(): Promise<NavigationGoResult>;
|
|
22
|
+
private _go;
|
|
23
|
+
go(delta?: number): Promise<NavigationGoResult>;
|
|
24
|
+
forward(): Promise<NavigationGoResult>;
|
|
25
|
+
back(): Promise<NavigationGoResult>;
|
|
26
|
+
destroy(): void;
|
|
27
|
+
}
|
|
28
|
+
export declare class MemoryHistory implements History {
|
|
29
|
+
private _entries;
|
|
30
|
+
private _index;
|
|
31
|
+
private get _curEntry();
|
|
32
|
+
private readonly _popStateCbs;
|
|
33
|
+
scrollRestoration: ScrollRestoration;
|
|
34
|
+
get state(): any;
|
|
35
|
+
get url(): string;
|
|
36
|
+
constructor();
|
|
37
|
+
get length(): number;
|
|
38
|
+
pushState(data: any, unused: string, url?: string | URL | null): void;
|
|
39
|
+
replaceState(data: any, unused: string, url?: string | URL | null): void;
|
|
40
|
+
back(): void;
|
|
41
|
+
forward(): void;
|
|
42
|
+
go(delta?: number): void;
|
|
43
|
+
onPopState(cb: NavigationSubscribe): () => void;
|
|
44
|
+
}
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
import { PAGE_ID } from "./increment-id.mjs";
|
|
5
|
+
import { RouterMode } from "./types.mjs";
|
|
6
|
+
const PAGE_ID_KEY = "__pageId__";
|
|
7
|
+
export class Navigation {
|
|
8
|
+
constructor(options, onUpdated) {
|
|
9
|
+
__publicField(this, "options");
|
|
10
|
+
__publicField(this, "_history");
|
|
11
|
+
__publicField(this, "_unSubscribePopState");
|
|
12
|
+
__publicField(this, "_promiseResolve", null);
|
|
13
|
+
const history2 = options.mode === RouterMode.history ? window.history : new MemoryHistory();
|
|
14
|
+
const onPopStateChange = (url, state) => {
|
|
15
|
+
const dispatchEvent = this._promiseResolve || onUpdated;
|
|
16
|
+
dispatchEvent == null ? void 0 : dispatchEvent(url, state);
|
|
17
|
+
};
|
|
18
|
+
const subscribePopState = history2 instanceof MemoryHistory ? history2.onPopState(onPopStateChange) : subscribeHtmlHistory(onPopStateChange);
|
|
19
|
+
this.options = options;
|
|
20
|
+
this._history = history2;
|
|
21
|
+
this._unSubscribePopState = subscribePopState;
|
|
22
|
+
}
|
|
23
|
+
get length() {
|
|
24
|
+
return this._history.length;
|
|
25
|
+
}
|
|
26
|
+
_push(history2, data, url) {
|
|
27
|
+
const state = {
|
|
28
|
+
...data || {},
|
|
29
|
+
[PAGE_ID_KEY]: PAGE_ID.next()
|
|
30
|
+
};
|
|
31
|
+
history2.pushState(state, "", url);
|
|
32
|
+
return state;
|
|
33
|
+
}
|
|
34
|
+
_replace(history2, data, url) {
|
|
35
|
+
var _a;
|
|
36
|
+
const oldId = (_a = history2.state) == null ? void 0 : _a[PAGE_ID_KEY];
|
|
37
|
+
const state = {
|
|
38
|
+
...data || {},
|
|
39
|
+
[PAGE_ID_KEY]: typeof oldId === "number" ? oldId : PAGE_ID.next()
|
|
40
|
+
};
|
|
41
|
+
history2.replaceState(state, "", url);
|
|
42
|
+
return state;
|
|
43
|
+
}
|
|
44
|
+
push(data, url) {
|
|
45
|
+
return this._push(this._history, data, url);
|
|
46
|
+
}
|
|
47
|
+
replace(data, url) {
|
|
48
|
+
return this._replace(this._history, data, url);
|
|
49
|
+
}
|
|
50
|
+
pushHistoryState(data, url) {
|
|
51
|
+
this._push(history, data, url);
|
|
52
|
+
}
|
|
53
|
+
replaceHistoryState(data, url) {
|
|
54
|
+
this._replace(history, data, url);
|
|
55
|
+
}
|
|
56
|
+
backHistoryState() {
|
|
57
|
+
return this._go(history, -1);
|
|
58
|
+
}
|
|
59
|
+
_go(history2, index) {
|
|
60
|
+
if (this._promiseResolve) {
|
|
61
|
+
return Promise.resolve(null);
|
|
62
|
+
}
|
|
63
|
+
return new Promise((resolve) => {
|
|
64
|
+
this._promiseResolve = (url, state) => {
|
|
65
|
+
this._promiseResolve = null;
|
|
66
|
+
if (typeof url !== "string") return resolve(null);
|
|
67
|
+
resolve({ type: "success", url, state: state || {} });
|
|
68
|
+
};
|
|
69
|
+
setTimeout(this._promiseResolve, 80);
|
|
70
|
+
history2.go(index);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
go(delta) {
|
|
74
|
+
return this._go(this._history, delta || 0);
|
|
75
|
+
}
|
|
76
|
+
forward() {
|
|
77
|
+
return this.go(1);
|
|
78
|
+
}
|
|
79
|
+
back() {
|
|
80
|
+
return this.go(-1);
|
|
81
|
+
}
|
|
82
|
+
destroy() {
|
|
83
|
+
var _a;
|
|
84
|
+
(_a = this._promiseResolve) == null ? void 0 : _a.call(this);
|
|
85
|
+
this._unSubscribePopState();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export class MemoryHistory {
|
|
89
|
+
constructor() {
|
|
90
|
+
__publicField(this, "_entries", []);
|
|
91
|
+
__publicField(this, "_index", -1);
|
|
92
|
+
__publicField(this, "_popStateCbs", /* @__PURE__ */ new Set());
|
|
93
|
+
__publicField(this, "scrollRestoration", "auto");
|
|
94
|
+
this.pushState(null, "", "/");
|
|
95
|
+
}
|
|
96
|
+
get _curEntry() {
|
|
97
|
+
const idx = this._index;
|
|
98
|
+
if (idx < 0 || idx >= this.length) return null;
|
|
99
|
+
return this._entries[idx];
|
|
100
|
+
}
|
|
101
|
+
// Return null when no current entry to align with browser history.state behavior
|
|
102
|
+
// Browser history.state can be null when no state was provided
|
|
103
|
+
get state() {
|
|
104
|
+
var _a, _b;
|
|
105
|
+
return (_b = (_a = this._curEntry) == null ? void 0 : _a.state) != null ? _b : null;
|
|
106
|
+
}
|
|
107
|
+
get url() {
|
|
108
|
+
var _a, _b;
|
|
109
|
+
return (_b = (_a = this._curEntry) == null ? void 0 : _a.url) != null ? _b : "";
|
|
110
|
+
}
|
|
111
|
+
get length() {
|
|
112
|
+
return this._entries.length;
|
|
113
|
+
}
|
|
114
|
+
pushState(data, unused, url) {
|
|
115
|
+
var _a;
|
|
116
|
+
this._entries.splice(this._index + 1);
|
|
117
|
+
this._entries.push({ state: data, url: (_a = url == null ? void 0 : url.toString()) != null ? _a : this.url });
|
|
118
|
+
this._index = this._entries.length - 1;
|
|
119
|
+
}
|
|
120
|
+
replaceState(data, unused, url) {
|
|
121
|
+
const curEntry = this._curEntry;
|
|
122
|
+
if (!curEntry) return;
|
|
123
|
+
curEntry.state = { ...data };
|
|
124
|
+
if (url) curEntry.url = url.toString();
|
|
125
|
+
}
|
|
126
|
+
back() {
|
|
127
|
+
this.go(-1);
|
|
128
|
+
}
|
|
129
|
+
forward() {
|
|
130
|
+
this.go(1);
|
|
131
|
+
}
|
|
132
|
+
go(delta) {
|
|
133
|
+
if (!delta) return;
|
|
134
|
+
const newIdx = this._index + delta;
|
|
135
|
+
if (newIdx < 0 || newIdx >= this.length) return;
|
|
136
|
+
this._index = newIdx;
|
|
137
|
+
const entry = this._curEntry;
|
|
138
|
+
setTimeout(() => {
|
|
139
|
+
this._popStateCbs.forEach((cb) => cb(entry.url, entry.state));
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
onPopState(cb) {
|
|
143
|
+
if (typeof cb !== "function") return () => {
|
|
144
|
+
};
|
|
145
|
+
this._popStateCbs.add(cb);
|
|
146
|
+
return () => this._popStateCbs.delete(cb);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function subscribeHtmlHistory(cb) {
|
|
150
|
+
const wrapper = () => cb(location.href, history.state || {});
|
|
151
|
+
window.addEventListener("popstate", wrapper);
|
|
152
|
+
return () => window.removeEventListener("popstate", wrapper);
|
|
153
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Router } from './router';
|
|
2
|
+
import type { Route, RouterOptions, RouterParsedOptions } from './types';
|
|
3
|
+
export declare function parsedOptions(options?: RouterOptions): RouterParsedOptions;
|
|
4
|
+
export declare function fallback(to: Route, from: Route | null, router: Router): Window | null | undefined;
|
package/dist/options.mjs
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { createMatcher, createRouteMatches } from "./matcher.mjs";
|
|
2
|
+
import { RouterMode } from "./types.mjs";
|
|
3
|
+
import { isBrowser } from "./util.mjs";
|
|
4
|
+
function getBaseUrl(options) {
|
|
5
|
+
let sourceUrl;
|
|
6
|
+
if (options.base) {
|
|
7
|
+
sourceUrl = options.base;
|
|
8
|
+
} else if (isBrowser) {
|
|
9
|
+
sourceUrl = location.origin;
|
|
10
|
+
} else if (options.req) {
|
|
11
|
+
const { req } = options;
|
|
12
|
+
const protocol = req.headers["x-forwarded-proto"] || req.headers["x-forwarded-protocol"] || (req.socket && "encrypted" in req.socket && req.socket.encrypted ? "https" : "http");
|
|
13
|
+
const host = req.headers["x-forwarded-host"] || req.headers.host || req.headers["x-real-ip"] || "localhost";
|
|
14
|
+
const port = req.headers["x-forwarded-port"];
|
|
15
|
+
const path = req.url || "";
|
|
16
|
+
sourceUrl = "".concat(protocol, "://").concat(host).concat(port ? ":".concat(port) : "").concat(path);
|
|
17
|
+
} else {
|
|
18
|
+
sourceUrl = "https://esmx.dev/";
|
|
19
|
+
}
|
|
20
|
+
let base;
|
|
21
|
+
try {
|
|
22
|
+
base = new URL(".", sourceUrl);
|
|
23
|
+
} catch (e) {
|
|
24
|
+
console.warn(
|
|
25
|
+
"Failed to parse base URL '".concat(sourceUrl, "', using default: https://esmx.dev/")
|
|
26
|
+
);
|
|
27
|
+
base = new URL("https://esmx.dev/");
|
|
28
|
+
}
|
|
29
|
+
base.search = base.hash = "";
|
|
30
|
+
return base;
|
|
31
|
+
}
|
|
32
|
+
export function parsedOptions(options = {}) {
|
|
33
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
34
|
+
const base = getBaseUrl(options);
|
|
35
|
+
const routes = (_a = options.routes) != null ? _a : [];
|
|
36
|
+
const compiledRoutes = createRouteMatches(routes);
|
|
37
|
+
return Object.freeze({
|
|
38
|
+
rootStyle: options.rootStyle || false,
|
|
39
|
+
appId: options.appId || "app",
|
|
40
|
+
context: options.context || {},
|
|
41
|
+
data: options.data || {},
|
|
42
|
+
req: options.req || null,
|
|
43
|
+
res: options.res || null,
|
|
44
|
+
layer: options.layer || false,
|
|
45
|
+
zIndex: options.zIndex || 1e4,
|
|
46
|
+
base,
|
|
47
|
+
mode: isBrowser ? (_b = options.mode) != null ? _b : RouterMode.history : RouterMode.memory,
|
|
48
|
+
routes,
|
|
49
|
+
apps: typeof options.apps === "function" ? options.apps : Object.assign({}, options.apps),
|
|
50
|
+
compiledRoutes,
|
|
51
|
+
matcher: createMatcher(routes, compiledRoutes),
|
|
52
|
+
normalizeURL: (_c = options.normalizeURL) != null ? _c : ((url) => url),
|
|
53
|
+
fallback: (_d = options.fallback) != null ? _d : fallback,
|
|
54
|
+
nextTick: (_e = options.nextTick) != null ? _e : (() => {
|
|
55
|
+
}),
|
|
56
|
+
handleBackBoundary: (_f = options.handleBackBoundary) != null ? _f : (() => {
|
|
57
|
+
}),
|
|
58
|
+
handleLayerClose: (_g = options.handleLayerClose) != null ? _g : (() => {
|
|
59
|
+
}),
|
|
60
|
+
resolveLink: (_h = options.resolveLink) != null ? _h : ((link) => link)
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
export function fallback(to, from, router) {
|
|
64
|
+
const href = to.url.href;
|
|
65
|
+
if (!isBrowser && (router == null ? void 0 : router.res)) {
|
|
66
|
+
let statusCode = 302;
|
|
67
|
+
const validRedirectCodes = [300, 301, 302, 303, 304, 307, 308];
|
|
68
|
+
if (to.statusCode && validRedirectCodes.includes(to.statusCode)) {
|
|
69
|
+
statusCode = to.statusCode;
|
|
70
|
+
} else if (to.statusCode) {
|
|
71
|
+
console.warn(
|
|
72
|
+
"Invalid redirect status code ".concat(to.statusCode, ", using default 302")
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
router.res.statusCode = statusCode;
|
|
76
|
+
router.res.setHeader("Location", href);
|
|
77
|
+
router.res.end();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (isBrowser) {
|
|
81
|
+
if (to.isPush) {
|
|
82
|
+
try {
|
|
83
|
+
const newWindow = window.open(href);
|
|
84
|
+
if (!newWindow) {
|
|
85
|
+
location.href = href;
|
|
86
|
+
} else {
|
|
87
|
+
newWindow.opener = null;
|
|
88
|
+
}
|
|
89
|
+
return newWindow;
|
|
90
|
+
} catch (e) {
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
location.href = href;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Route } from './route';
|
|
2
|
+
import type { Router } from './router';
|
|
3
|
+
import type { RouteConfirmHook } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* Controls the execution and cancellation of a route task.
|
|
6
|
+
*/
|
|
7
|
+
export declare class RouteTaskController {
|
|
8
|
+
private _aborted;
|
|
9
|
+
/**
|
|
10
|
+
* Aborts the current task.
|
|
11
|
+
*/
|
|
12
|
+
abort(): void;
|
|
13
|
+
shouldCancel(name: string): boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface RouteTaskOptions {
|
|
16
|
+
to: Route;
|
|
17
|
+
from: Route | null;
|
|
18
|
+
tasks: RouteTask[];
|
|
19
|
+
router: Router;
|
|
20
|
+
/**
|
|
21
|
+
* Optional route task controller.
|
|
22
|
+
* Used to control the execution and cancellation of the task.
|
|
23
|
+
*/
|
|
24
|
+
controller?: RouteTaskController;
|
|
25
|
+
}
|
|
26
|
+
export declare function createRouteTask(opts: RouteTaskOptions): Promise<Route>;
|
|
27
|
+
export declare enum RouteTaskType {
|
|
28
|
+
fallback = "fallback",
|
|
29
|
+
override = "override",
|
|
30
|
+
asyncComponent = "asyncComponent",
|
|
31
|
+
beforeEach = "beforeEach",
|
|
32
|
+
beforeEnter = "beforeEnter",
|
|
33
|
+
beforeUpdate = "beforeUpdate",
|
|
34
|
+
beforeLeave = "beforeLeave",
|
|
35
|
+
confirm = "confirm"
|
|
36
|
+
}
|
|
37
|
+
export interface RouteTask {
|
|
38
|
+
name: string;
|
|
39
|
+
task: RouteConfirmHook;
|
|
40
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
import {
|
|
5
|
+
RouteNavigationAbortedError,
|
|
6
|
+
RouteSelfRedirectionError,
|
|
7
|
+
RouteTaskCancelledError,
|
|
8
|
+
RouteTaskExecutionError
|
|
9
|
+
} from "./error.mjs";
|
|
10
|
+
import { Route } from "./route.mjs";
|
|
11
|
+
import { isUrlEqual, isValidConfirmHookResult } from "./util.mjs";
|
|
12
|
+
export class RouteTaskController {
|
|
13
|
+
constructor() {
|
|
14
|
+
__publicField(this, "_aborted", false);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Aborts the current task.
|
|
18
|
+
*/
|
|
19
|
+
abort() {
|
|
20
|
+
this._aborted = true;
|
|
21
|
+
}
|
|
22
|
+
shouldCancel(name) {
|
|
23
|
+
return this._aborted;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export async function createRouteTask(opts) {
|
|
27
|
+
const { to, from, tasks, controller, router } = opts;
|
|
28
|
+
for (const task of tasks) {
|
|
29
|
+
if (controller == null ? void 0 : controller.shouldCancel(task.name)) {
|
|
30
|
+
throw new RouteTaskCancelledError(task.name, to, from);
|
|
31
|
+
}
|
|
32
|
+
let result = null;
|
|
33
|
+
try {
|
|
34
|
+
result = await task.task(to, from, router);
|
|
35
|
+
} catch (e) {
|
|
36
|
+
throw new RouteTaskExecutionError(task.name, to, from, e);
|
|
37
|
+
}
|
|
38
|
+
if (controller == null ? void 0 : controller.shouldCancel(task.name)) {
|
|
39
|
+
throw new RouteTaskCancelledError(task.name, to, from);
|
|
40
|
+
}
|
|
41
|
+
if (!isValidConfirmHookResult(result)) continue;
|
|
42
|
+
if (typeof result === "function") {
|
|
43
|
+
to.handle = result;
|
|
44
|
+
return to;
|
|
45
|
+
}
|
|
46
|
+
if (result === false) {
|
|
47
|
+
throw new RouteNavigationAbortedError(task.name, to, from);
|
|
48
|
+
}
|
|
49
|
+
const nextTo = new Route({
|
|
50
|
+
options: router.parsedOptions,
|
|
51
|
+
toType: to.type,
|
|
52
|
+
toInput: result,
|
|
53
|
+
from: to.url
|
|
54
|
+
});
|
|
55
|
+
if (isUrlEqual(nextTo.url, to.url)) {
|
|
56
|
+
throw new RouteSelfRedirectionError(to.fullPath, to, from);
|
|
57
|
+
}
|
|
58
|
+
return createRouteTask({
|
|
59
|
+
...opts,
|
|
60
|
+
to: nextTo,
|
|
61
|
+
from: to,
|
|
62
|
+
controller
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return to;
|
|
66
|
+
}
|
|
67
|
+
export var RouteTaskType = /* @__PURE__ */ ((RouteTaskType2) => {
|
|
68
|
+
RouteTaskType2["fallback"] = "fallback";
|
|
69
|
+
RouteTaskType2["override"] = "override";
|
|
70
|
+
RouteTaskType2["asyncComponent"] = "asyncComponent";
|
|
71
|
+
RouteTaskType2["beforeEach"] = "beforeEach";
|
|
72
|
+
RouteTaskType2["beforeEnter"] = "beforeEnter";
|
|
73
|
+
RouteTaskType2["beforeUpdate"] = "beforeUpdate";
|
|
74
|
+
RouteTaskType2["beforeLeave"] = "beforeLeave";
|
|
75
|
+
RouteTaskType2["confirm"] = "confirm";
|
|
76
|
+
return RouteTaskType2;
|
|
77
|
+
})(RouteTaskType || {});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Route } from './route';
|
|
2
|
+
import type { Router } from './router';
|
|
3
|
+
import type { RouteConfirmHook, RouteConfirmHookResult, RouteLocationInput, RouteNotifyHook } from './types';
|
|
4
|
+
import { RouteType } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* Route transition hooks responsible for handling different stages of the navigation process.
|
|
7
|
+
* Each hook is responsible for a specific aspect of route transition.
|
|
8
|
+
*/
|
|
9
|
+
export declare const ROUTE_TRANSITION_HOOKS: {
|
|
10
|
+
fallback(to: Route, from: Route | null, router: Router): Promise<RouteConfirmHookResult>;
|
|
11
|
+
override(to: Route, from: Route | null, router: Router): Promise<RouteConfirmHookResult>;
|
|
12
|
+
asyncComponent(to: Route, from: Route | null, router: Router): Promise<RouteConfirmHookResult>;
|
|
13
|
+
beforeLeave(to: Route, from: Route | null, router: Router): Promise<RouteConfirmHookResult>;
|
|
14
|
+
beforeEnter(to: Route, from: Route | null, router: Router): Promise<RouteConfirmHookResult>;
|
|
15
|
+
beforeUpdate(to: Route, from: Route | null, router: Router): Promise<RouteConfirmHookResult>;
|
|
16
|
+
beforeEach(to: Route, from: Route | null, router: Router): Promise<RouteConfirmHookResult>;
|
|
17
|
+
confirm(to: Route, from: Route | null, router: Router): Promise<RouteConfirmHookResult>;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Route type handlers configuration.
|
|
21
|
+
* Maps each route type to its corresponding navigation handler function.
|
|
22
|
+
* These handlers perform the actual navigation operations like updating browser state,
|
|
23
|
+
* managing micro-app updates, and handling different navigation patterns.
|
|
24
|
+
*/
|
|
25
|
+
export declare const ROUTE_TYPE_HANDLERS: {
|
|
26
|
+
push(to: Route, from: Route | null, router: Router): void;
|
|
27
|
+
replace(to: Route, from: Route | null, router: Router): void;
|
|
28
|
+
restartApp(to: Route, from: Route | null, router: Router): void;
|
|
29
|
+
pushWindow(to: Route, from: Route | null, router: Router): unknown;
|
|
30
|
+
replaceWindow(to: Route, from: Route | null, router: Router): unknown;
|
|
31
|
+
pushLayer(to: Route, from: Route | null, router: Router): Promise<import("./types").RouteLayerResult>;
|
|
32
|
+
default(to: Route, from: Route | null, router: Router): void;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Route Transition Manager
|
|
36
|
+
* Responsible for managing all route transition logic, including guard execution,
|
|
37
|
+
* task processing, and status updates.
|
|
38
|
+
*/
|
|
39
|
+
export declare class RouteTransition {
|
|
40
|
+
private readonly router;
|
|
41
|
+
route: Route | null;
|
|
42
|
+
private _controller;
|
|
43
|
+
readonly guards: {
|
|
44
|
+
beforeEach: RouteConfirmHook[];
|
|
45
|
+
afterEach: RouteNotifyHook[];
|
|
46
|
+
};
|
|
47
|
+
private destroyed;
|
|
48
|
+
constructor(router: Router);
|
|
49
|
+
beforeEach(guard: RouteConfirmHook): () => void;
|
|
50
|
+
afterEach(guard: RouteNotifyHook): () => void;
|
|
51
|
+
destroy(): void;
|
|
52
|
+
to(toType: RouteType, toInput: RouteLocationInput): Promise<Route>;
|
|
53
|
+
private _runTask;
|
|
54
|
+
}
|