@wot-ui/router 0.0.4 → 0.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023-PRESENT KeJun
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.cjs CHANGED
@@ -68,21 +68,16 @@ function createRouter(options) {
68
68
  if (typeof to === "string") return resolvePath(to);
69
69
  if (to.name) {
70
70
  const route = routes.find((r) => r.name === to.name);
71
- if (!route) {
72
- console.warn(`[router] Route with name '${to.name}' not found`);
73
- return {
74
- ...START_LOCATION_NORMALIZED,
75
- path: "/"
76
- };
77
- }
71
+ if (!route) throw new Error(`您正在尝试访问的路由 '${to.name}' 未在路由表中定义。请检查您的路由配置。`);
78
72
  const path = fillParams(route.path, to.params);
73
+ const finalQuery = to.params || {};
79
74
  return {
80
75
  path,
81
76
  name: to.name,
82
77
  params: to.params || {},
83
- query: to.query || {},
78
+ query: finalQuery,
84
79
  hash: to.hash || "",
85
- fullPath: stringifyQuery(path, to.query || {}),
80
+ fullPath: stringifyQuery(path, finalQuery),
86
81
  meta: route.meta || {}
87
82
  };
88
83
  }
@@ -92,6 +87,7 @@ function createRouter(options) {
92
87
  function resolvePath(path, query) {
93
88
  const normalizedPath = normalizeUrl(path.split("?")[0]);
94
89
  const route = routes.find((r) => r.path === normalizedPath || r.aliasPath === normalizedPath);
90
+ if (!route) throw new Error(`您正在尝试访问的路由 '${normalizedPath}' 未在路由表中定义。请检查您的路由配置。`);
95
91
  const finalQuery = {
96
92
  ...getUrlParams(path),
97
93
  ...query || {}
@@ -128,57 +124,82 @@ function createRouter(options) {
128
124
  if (back$1 === void 0 || typeof back$1 === "number") uni.navigateBack({ delta: back$1 ?? 1 });
129
125
  else uni.navigateBack(back$1);
130
126
  }
131
- async function navigate(to, type) {
127
+ async function navigate(to, type, skipGuards = false) {
132
128
  const targetLocation = resolve(to);
133
129
  const fromLocation = (0, vue.unref)(currentRoute);
134
- try {
130
+ if (!skipGuards) try {
135
131
  await runGuardQueue(beforeGuards, targetLocation, fromLocation);
136
132
  } catch (error) {
137
133
  if (error && (error.message === "NavigationCancelled" || error.message === "NavigationRedirect")) {
138
- if (error.message === "NavigationRedirect" && error.to) return navigate(error.to, type);
134
+ if (error.message === "NavigationRedirect" && error.to) return navigate(error.to, type, true);
139
135
  return Promise.reject(error);
140
136
  }
141
137
  return Promise.reject(error);
142
138
  }
143
139
  const url = targetLocation.fullPath;
144
- performUniNavigate(typeof to === "object" && to.navType || type || "push", url);
145
- currentRoute.value = targetLocation;
146
- afterGuards.forEach((guard) => guard(targetLocation, fromLocation));
147
- return Promise.resolve();
140
+ const finalType = typeof to === "object" && to.navType || type || "push";
141
+ try {
142
+ await performUniNavigate(finalType, url);
143
+ currentRoute.value = targetLocation;
144
+ afterGuards.forEach((guard) => guard(targetLocation, fromLocation));
145
+ return Promise.resolve();
146
+ } catch (error) {
147
+ return Promise.reject(error);
148
+ }
148
149
  }
149
150
  function performUniNavigate(type, url) {
150
- switch (type) {
151
- case "push":
152
- uni.navigateTo({ url });
153
- break;
154
- case "replace":
155
- uni.redirectTo({ url });
156
- break;
157
- case "pushTab":
158
- uni.switchTab({ url });
159
- break;
160
- case "replaceAll":
161
- uni.reLaunch({ url });
162
- break;
163
- case "back":
164
- uni.navigateBack({});
165
- break;
166
- default: uni.navigateTo({ url });
167
- }
151
+ return new Promise((resolve$1, reject) => {
152
+ const success = () => resolve$1();
153
+ const fail = (error) => {
154
+ reject(/* @__PURE__ */ new Error(`Navigation failed: ${error.message || error.errMsg || "Unknown error"}`));
155
+ };
156
+ switch (type) {
157
+ case "push":
158
+ uni.navigateTo({
159
+ url,
160
+ success,
161
+ fail
162
+ });
163
+ break;
164
+ case "replace":
165
+ uni.redirectTo({
166
+ url,
167
+ success,
168
+ fail
169
+ });
170
+ break;
171
+ case "pushTab":
172
+ uni.switchTab({
173
+ url,
174
+ success,
175
+ fail
176
+ });
177
+ break;
178
+ case "replaceAll":
179
+ uni.reLaunch({
180
+ url,
181
+ success,
182
+ fail
183
+ });
184
+ break;
185
+ case "back":
186
+ uni.navigateBack({
187
+ success,
188
+ fail
189
+ });
190
+ break;
191
+ default: uni.navigateTo({
192
+ url,
193
+ success,
194
+ fail
195
+ });
196
+ }
197
+ });
168
198
  }
169
199
  async function runGuardQueue(guards, to, from) {
170
200
  for (const guard of guards) await new Promise((resolve$1, reject) => {
171
201
  const next = (val) => {
172
- if (val === false) reject(/* @__PURE__ */ new Error("NavigationCancelled"));
173
- else if (val === void 0) resolve$1();
174
- else {
175
- const error = /* @__PURE__ */ new Error("NavigationRedirect");
176
- error.to = val;
177
- reject(error);
178
- }
179
- };
180
- const res = guard(to, from, next);
181
- if (res instanceof Promise) res.then((val) => {
202
+ next._called = true;
182
203
  if (val === false) reject(/* @__PURE__ */ new Error("NavigationCancelled"));
183
204
  else if (val === void 0 || val === true) resolve$1();
184
205
  else {
@@ -186,14 +207,26 @@ function createRouter(options) {
186
207
  error.to = val;
187
208
  reject(error);
188
209
  }
189
- }).catch(reject);
190
- else if (res !== void 0 && typeof res !== "function") if (res === false) reject(/* @__PURE__ */ new Error("NavigationCancelled"));
191
- else if (res === true) resolve$1();
210
+ };
211
+ const guardReturn = guard(to, from, next);
212
+ let guardCall = Promise.resolve(guardReturn);
213
+ if (guard.length < 3) guardCall = guardCall.then(next);
192
214
  else {
193
- const error = /* @__PURE__ */ new Error("NavigationRedirect");
194
- error.to = res;
195
- reject(error);
215
+ const message = `The "next" callback was never called inside of ${guard.name ? `"${guard.name}"` : ""}:\n${guard.toString()}\n. If you are returning a value instead of calling "next", make sure to remove the "next" parameter from your function.`;
216
+ if (guardReturn !== null && typeof guardReturn === "object" && "then" in guardReturn) guardCall = guardCall.then((resolvedValue) => {
217
+ if (!next._called) {
218
+ console.warn(message);
219
+ return Promise.reject(/* @__PURE__ */ new Error("Invalid navigation guard"));
220
+ }
221
+ return resolvedValue;
222
+ });
223
+ else if (!next._called) {
224
+ console.warn(message);
225
+ reject(/* @__PURE__ */ new Error("Invalid navigation guard"));
226
+ return;
227
+ }
196
228
  }
229
+ guardCall.catch((err) => reject(err));
197
230
  });
198
231
  }
199
232
  function beforeEach(guard) {
@@ -237,6 +270,7 @@ function createRouter(options) {
237
270
  if (router$1.currentRoute.value.path === newPath) return;
238
271
  const from = (0, vue.unref)(router$1.currentRoute);
239
272
  const matched = router$1.routes.find((r) => r.path === newPath || r.aliasPath === newPath);
273
+ if (!matched) console.warn(`[router] 路由 '${newPath}' 未在路由表中定义,但页面已加载。请检查您的路由配置。`);
240
274
  const to = {
241
275
  path: newPath,
242
276
  name: matched?.name,
package/dist/index.d.cts CHANGED
@@ -43,7 +43,7 @@ type RouteLocationRaw = string | {
43
43
  interface RouterOptions {
44
44
  routes: RouteRecordRaw[];
45
45
  }
46
- type NavigationGuardNext = (to?: RouteLocationRaw | false | void) => void;
46
+ type NavigationGuardNext = (to?: RouteLocationRaw | false | true | void) => void;
47
47
  type NavigationGuard = (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => Promise<void | RouteLocationRaw | false | boolean> | void | RouteLocationRaw | false | boolean;
48
48
  type NavigationHookAfter = (to: RouteLocationNormalized, from: RouteLocationNormalized) => void;
49
49
  type NavType = 'push' | 'replace' | 'replaceAll' | 'pushTab' | 'back';
package/dist/index.d.mts CHANGED
@@ -43,7 +43,7 @@ type RouteLocationRaw = string | {
43
43
  interface RouterOptions {
44
44
  routes: RouteRecordRaw[];
45
45
  }
46
- type NavigationGuardNext = (to?: RouteLocationRaw | false | void) => void;
46
+ type NavigationGuardNext = (to?: RouteLocationRaw | false | true | void) => void;
47
47
  type NavigationGuard = (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => Promise<void | RouteLocationRaw | false | boolean> | void | RouteLocationRaw | false | boolean;
48
48
  type NavigationHookAfter = (to: RouteLocationNormalized, from: RouteLocationNormalized) => void;
49
49
  type NavType = 'push' | 'replace' | 'replaceAll' | 'pushTab' | 'back';
package/dist/index.mjs CHANGED
@@ -68,21 +68,16 @@ function createRouter(options) {
68
68
  if (typeof to === "string") return resolvePath(to);
69
69
  if (to.name) {
70
70
  const route = routes.find((r) => r.name === to.name);
71
- if (!route) {
72
- console.warn(`[router] Route with name '${to.name}' not found`);
73
- return {
74
- ...START_LOCATION_NORMALIZED,
75
- path: "/"
76
- };
77
- }
71
+ if (!route) throw new Error(`您正在尝试访问的路由 '${to.name}' 未在路由表中定义。请检查您的路由配置。`);
78
72
  const path = fillParams(route.path, to.params);
73
+ const finalQuery = to.params || {};
79
74
  return {
80
75
  path,
81
76
  name: to.name,
82
77
  params: to.params || {},
83
- query: to.query || {},
78
+ query: finalQuery,
84
79
  hash: to.hash || "",
85
- fullPath: stringifyQuery(path, to.query || {}),
80
+ fullPath: stringifyQuery(path, finalQuery),
86
81
  meta: route.meta || {}
87
82
  };
88
83
  }
@@ -92,6 +87,7 @@ function createRouter(options) {
92
87
  function resolvePath(path, query) {
93
88
  const normalizedPath = normalizeUrl(path.split("?")[0]);
94
89
  const route = routes.find((r) => r.path === normalizedPath || r.aliasPath === normalizedPath);
90
+ if (!route) throw new Error(`您正在尝试访问的路由 '${normalizedPath}' 未在路由表中定义。请检查您的路由配置。`);
95
91
  const finalQuery = {
96
92
  ...getUrlParams(path),
97
93
  ...query || {}
@@ -128,57 +124,82 @@ function createRouter(options) {
128
124
  if (back$1 === void 0 || typeof back$1 === "number") uni.navigateBack({ delta: back$1 ?? 1 });
129
125
  else uni.navigateBack(back$1);
130
126
  }
131
- async function navigate(to, type) {
127
+ async function navigate(to, type, skipGuards = false) {
132
128
  const targetLocation = resolve(to);
133
129
  const fromLocation = unref(currentRoute);
134
- try {
130
+ if (!skipGuards) try {
135
131
  await runGuardQueue(beforeGuards, targetLocation, fromLocation);
136
132
  } catch (error) {
137
133
  if (error && (error.message === "NavigationCancelled" || error.message === "NavigationRedirect")) {
138
- if (error.message === "NavigationRedirect" && error.to) return navigate(error.to, type);
134
+ if (error.message === "NavigationRedirect" && error.to) return navigate(error.to, type, true);
139
135
  return Promise.reject(error);
140
136
  }
141
137
  return Promise.reject(error);
142
138
  }
143
139
  const url = targetLocation.fullPath;
144
- performUniNavigate(typeof to === "object" && to.navType || type || "push", url);
145
- currentRoute.value = targetLocation;
146
- afterGuards.forEach((guard) => guard(targetLocation, fromLocation));
147
- return Promise.resolve();
140
+ const finalType = typeof to === "object" && to.navType || type || "push";
141
+ try {
142
+ await performUniNavigate(finalType, url);
143
+ currentRoute.value = targetLocation;
144
+ afterGuards.forEach((guard) => guard(targetLocation, fromLocation));
145
+ return Promise.resolve();
146
+ } catch (error) {
147
+ return Promise.reject(error);
148
+ }
148
149
  }
149
150
  function performUniNavigate(type, url) {
150
- switch (type) {
151
- case "push":
152
- uni.navigateTo({ url });
153
- break;
154
- case "replace":
155
- uni.redirectTo({ url });
156
- break;
157
- case "pushTab":
158
- uni.switchTab({ url });
159
- break;
160
- case "replaceAll":
161
- uni.reLaunch({ url });
162
- break;
163
- case "back":
164
- uni.navigateBack({});
165
- break;
166
- default: uni.navigateTo({ url });
167
- }
151
+ return new Promise((resolve$1, reject) => {
152
+ const success = () => resolve$1();
153
+ const fail = (error) => {
154
+ reject(/* @__PURE__ */ new Error(`Navigation failed: ${error.message || error.errMsg || "Unknown error"}`));
155
+ };
156
+ switch (type) {
157
+ case "push":
158
+ uni.navigateTo({
159
+ url,
160
+ success,
161
+ fail
162
+ });
163
+ break;
164
+ case "replace":
165
+ uni.redirectTo({
166
+ url,
167
+ success,
168
+ fail
169
+ });
170
+ break;
171
+ case "pushTab":
172
+ uni.switchTab({
173
+ url,
174
+ success,
175
+ fail
176
+ });
177
+ break;
178
+ case "replaceAll":
179
+ uni.reLaunch({
180
+ url,
181
+ success,
182
+ fail
183
+ });
184
+ break;
185
+ case "back":
186
+ uni.navigateBack({
187
+ success,
188
+ fail
189
+ });
190
+ break;
191
+ default: uni.navigateTo({
192
+ url,
193
+ success,
194
+ fail
195
+ });
196
+ }
197
+ });
168
198
  }
169
199
  async function runGuardQueue(guards, to, from) {
170
200
  for (const guard of guards) await new Promise((resolve$1, reject) => {
171
201
  const next = (val) => {
172
- if (val === false) reject(/* @__PURE__ */ new Error("NavigationCancelled"));
173
- else if (val === void 0) resolve$1();
174
- else {
175
- const error = /* @__PURE__ */ new Error("NavigationRedirect");
176
- error.to = val;
177
- reject(error);
178
- }
179
- };
180
- const res = guard(to, from, next);
181
- if (res instanceof Promise) res.then((val) => {
202
+ next._called = true;
182
203
  if (val === false) reject(/* @__PURE__ */ new Error("NavigationCancelled"));
183
204
  else if (val === void 0 || val === true) resolve$1();
184
205
  else {
@@ -186,14 +207,26 @@ function createRouter(options) {
186
207
  error.to = val;
187
208
  reject(error);
188
209
  }
189
- }).catch(reject);
190
- else if (res !== void 0 && typeof res !== "function") if (res === false) reject(/* @__PURE__ */ new Error("NavigationCancelled"));
191
- else if (res === true) resolve$1();
210
+ };
211
+ const guardReturn = guard(to, from, next);
212
+ let guardCall = Promise.resolve(guardReturn);
213
+ if (guard.length < 3) guardCall = guardCall.then(next);
192
214
  else {
193
- const error = /* @__PURE__ */ new Error("NavigationRedirect");
194
- error.to = res;
195
- reject(error);
215
+ const message = `The "next" callback was never called inside of ${guard.name ? `"${guard.name}"` : ""}:\n${guard.toString()}\n. If you are returning a value instead of calling "next", make sure to remove the "next" parameter from your function.`;
216
+ if (guardReturn !== null && typeof guardReturn === "object" && "then" in guardReturn) guardCall = guardCall.then((resolvedValue) => {
217
+ if (!next._called) {
218
+ console.warn(message);
219
+ return Promise.reject(/* @__PURE__ */ new Error("Invalid navigation guard"));
220
+ }
221
+ return resolvedValue;
222
+ });
223
+ else if (!next._called) {
224
+ console.warn(message);
225
+ reject(/* @__PURE__ */ new Error("Invalid navigation guard"));
226
+ return;
227
+ }
196
228
  }
229
+ guardCall.catch((err) => reject(err));
197
230
  });
198
231
  }
199
232
  function beforeEach(guard) {
@@ -237,6 +270,7 @@ function createRouter(options) {
237
270
  if (router$1.currentRoute.value.path === newPath) return;
238
271
  const from = unref(router$1.currentRoute);
239
272
  const matched = router$1.routes.find((r) => r.path === newPath || r.aliasPath === newPath);
273
+ if (!matched) console.warn(`[router] 路由 '${newPath}' 未在路由表中定义,但页面已加载。请检查您的路由配置。`);
240
274
  const to = {
241
275
  path: newPath,
242
276
  name: matched?.name,
package/package.json CHANGED
@@ -1,7 +1,12 @@
1
1
  {
2
2
  "name": "@wot-ui/router",
3
- "version": "0.0.4",
3
+ "version": "0.0.19",
4
4
  "description": "轻量级 uni-app vue3 路由库",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/wot-ui/my-uni.git",
8
+ "directory": "packages/router"
9
+ },
5
10
  "type": "module",
6
11
  "main": "dist/index.js",
7
12
  "module": "dist/index.mjs",
@@ -15,16 +20,9 @@
15
20
  },
16
21
  "unpkg": "dist/index.global.js",
17
22
  "jsdelivr": "dist/index.global.js",
18
- "packageManager": "pnpm@9.9.0",
19
23
  "files": [
20
24
  "dist"
21
25
  ],
22
- "scripts": {
23
- "clean": "rimraf dist",
24
- "build": "tsdown",
25
- "dev": "tsdown --watch",
26
- "lint": "eslint --fix --ext .json,.js,.ts src"
27
- },
28
26
  "license": "MIT",
29
27
  "keywords": [
30
28
  "uni-app",
@@ -42,19 +40,34 @@
42
40
  "@types/node": "^20.16.2",
43
41
  "@typescript-eslint/eslint-plugin": "^5.54.1",
44
42
  "@typescript-eslint/parser": "^5.54.1",
43
+ "@vitejs/plugin-vue": "^6.0.3",
44
+ "@vitest/ui": "^4.0.16",
45
+ "@vue/test-utils": "^2.4.6",
45
46
  "eslint": "^8.57.0",
46
47
  "eslint-config-prettier": "^8.7.0",
47
48
  "eslint-plugin-import": "^2.25.2",
48
49
  "eslint-plugin-n": "^15.0.0",
49
50
  "eslint-plugin-prettier": "^4.2.1",
50
51
  "git-cz": "^4.9.0",
52
+ "happy-dom": "^20.0.11",
51
53
  "husky": "^8.0.3",
54
+ "jsdom": "^27.3.0",
52
55
  "lint-staged": "^13.1.2",
53
56
  "prettier": "^2.8.4",
54
57
  "rimraf": "^4.4.0",
55
58
  "standard-version": "^9.5.0",
56
59
  "ts-jest": "^29.0.5",
57
60
  "tsdown": "^0.18.2",
58
- "typescript": "~5.5.4"
61
+ "typescript": "~5.5.4",
62
+ "vitest": "^4.0.16"
63
+ },
64
+ "scripts": {
65
+ "clean": "rimraf dist",
66
+ "build": "tsdown",
67
+ "dev": "tsdown --watch",
68
+ "lint": "eslint --fix --ext .json,.js,.ts src",
69
+ "test": "vitest",
70
+ "test:ui": "vitest --ui",
71
+ "test:coverage": "vitest --coverage"
59
72
  }
60
- }
73
+ }