@esmx/router 3.0.0-rc.42 → 3.0.0-rc.44

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/dist/index.d.ts CHANGED
@@ -3,10 +3,12 @@ export { Route } from './route';
3
3
  export { RouterMode, RouteType, type RouteConfirmHook, type RouteConfirmHookResult, type RouteVerifyHook, type RouteHandleHook, type RouteNotifyHook, type RouteMeta, type RouteState, type RouteHandleResult, type RouteMatchType, type RouteLocation, type RouteLocationInput, type RouteConfig, type RouteParsedConfig, type RouteMatchResult, type RouteMatcher, type RouteOptions, type RouteLayerOptions, type RouteLayerResult, type RouterLayerOptions, type RouterMicroApp, type RouterMicroAppCallback, type RouterMicroAppOptions, type RouterOptions, type RouterParsedOptions, type RouterLinkType, type RouterLinkAttributes, type RouterLinkProps, type RouterLinkResolved } from './types';
4
4
  export { RouteError, RouteTaskCancelledError, RouteTaskExecutionError, RouteNavigationAbortedError, RouteSelfRedirectionError } from './error';
5
5
  import type { Router } from './router';
6
+ import type { Route, RouteLocation, RouteLocationInput } from './types';
6
7
  /** @deprecated Use `Router` directly instead of `RouterInstance`. */
7
8
  export type RouterInstance = Router;
8
- import type { Route, RouteLocationInput } from './types';
9
9
  /** @deprecated Use `RouteLocationInput` directly instead of `RouterRawLocation`. */
10
10
  export type RouterRawLocation = RouteLocationInput;
11
- /** @deprecated Use `Route` directly instead of `RouterLocation`. */
12
- export type RouterLocation = Route;
11
+ /** @deprecated Use `RouteLocation` directly instead of `RouterLocation`. */
12
+ export type RouterLocation = RouteLocation;
13
+ /** @deprecated Use `Route` directly instead of `RouteRecord`. */
14
+ export type RouteRecord = Route;
@@ -1,4 +1,4 @@
1
- import type { RouteLocationInput } from './types';
1
+ import type { RouteLocation, RouteLocationInput } from './types';
2
2
  /**
3
3
  * Normalizes a URL input into a URL object.
4
4
  * @param url - The URL or string to normalize.
@@ -13,3 +13,10 @@ export declare function normalizeURL(url: string | URL, base: URL): URL;
13
13
  * @returns The parsed URL object.
14
14
  */
15
15
  export declare function parseLocation(toInput: RouteLocationInput, baseURL: URL): URL;
16
+ /**
17
+ * Resolves RouteLocationInput with fallback from previous route
18
+ * @param toInput - The route location input
19
+ * @param from - The previous route URL (optional)
20
+ * @returns Resolved RouteLocation object
21
+ */
22
+ export declare function resolveRouteLocationInput(toInput?: RouteLocationInput, from?: URL | null): RouteLocation;
package/dist/location.mjs CHANGED
@@ -52,3 +52,12 @@ export function parseLocation(toInput, baseURL) {
52
52
  }
53
53
  return url;
54
54
  }
55
+ export function resolveRouteLocationInput(toInput = "/", from = null) {
56
+ if (typeof toInput === "string") {
57
+ return { path: toInput };
58
+ }
59
+ if (toInput && typeof toInput === "object" && typeof toInput.path !== "string" && typeof toInput.url !== "string" && from !== null) {
60
+ return { ...toInput, url: from.href };
61
+ }
62
+ return toInput;
63
+ }
package/dist/route.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { parseLocation } from "./location.mjs";
4
+ import { parseLocation, resolveRouteLocationInput } from "./location.mjs";
5
5
  import { parsedOptions } from "./options.mjs";
6
6
  import {
7
7
  RouteType
@@ -74,7 +74,6 @@ export class Route {
74
74
  var _a;
75
75
  const {
76
76
  toType = RouteType.push,
77
- toInput = "/",
78
77
  from = null,
79
78
  options = parsedOptions()
80
79
  } = routeOptions;
@@ -84,6 +83,7 @@ export class Route {
84
83
  this.res = options.res;
85
84
  this.context = options.context;
86
85
  const base = options.base;
86
+ const toInput = resolveRouteLocationInput(routeOptions.toInput, from);
87
87
  const to = options.normalizeURL(parseLocation(toInput, base), from);
88
88
  const isSameOrigin = to.origin === base.origin;
89
89
  const isSameBase = to.pathname.startsWith(base.pathname);
@@ -92,13 +92,13 @@ export class Route {
92
92
  this.path = match ? to.pathname.substring(base.pathname.length - 1) : to.pathname;
93
93
  this.fullPath = (match ? this.path : to.pathname) + to.search + to.hash;
94
94
  this.matched = match ? match.matches : Object.freeze([]);
95
- this.keepScrollPosition = isPlainObject(toInput) ? Boolean(toInput.keepScrollPosition) : false;
96
- this.confirm = isPlainObject(toInput) && toInput.confirm ? toInput.confirm : null;
97
- this.layer = toType === RouteType.pushLayer && isPlainObject(toInput) && toInput.layer ? toInput.layer : null;
95
+ this.keepScrollPosition = Boolean(toInput.keepScrollPosition);
96
+ this.confirm = toInput.confirm || null;
97
+ this.layer = toType === RouteType.pushLayer && toInput.layer ? toInput.layer : null;
98
98
  this.config = this.matched.length > 0 ? this.matched[this.matched.length - 1] : null;
99
99
  this.meta = ((_a = this.config) == null ? void 0 : _a.meta) || {};
100
100
  const state = {};
101
- if (isPlainObject(toInput) && toInput.state) {
101
+ if (toInput.state) {
102
102
  Object.assign(state, toInput.state);
103
103
  }
104
104
  this.state = state;
@@ -111,7 +111,7 @@ export class Route {
111
111
  applyRouteParams(match, toInput, base, to);
112
112
  Object.assign(this.params, match.params);
113
113
  }
114
- if (isPlainObject(toInput) && typeof toInput.statusCode === "number") {
114
+ if (typeof toInput.statusCode === "number") {
115
115
  this.statusCode = toInput.statusCode;
116
116
  }
117
117
  for (const property of NON_ENUMERABLE_PROPERTIES) {
package/package.json CHANGED
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "devDependencies": {
34
34
  "@biomejs/biome": "1.9.4",
35
- "@esmx/lint": "3.0.0-rc.42",
35
+ "@esmx/lint": "3.0.0-rc.44",
36
36
  "@types/node": "^24.0.0",
37
37
  "@vitest/coverage-v8": "3.2.4",
38
38
  "happy-dom": "^18.0.1",
@@ -41,7 +41,7 @@
41
41
  "unbuild": "3.5.0",
42
42
  "vitest": "3.2.4"
43
43
  },
44
- "version": "3.0.0-rc.42",
44
+ "version": "3.0.0-rc.44",
45
45
  "type": "module",
46
46
  "private": false,
47
47
  "exports": {
@@ -60,5 +60,5 @@
60
60
  "template",
61
61
  "public"
62
62
  ],
63
- "gitHead": "b7baaff3dcd8cb6ebde635f8bee88ba1e343ff1f"
63
+ "gitHead": "c83ac6a9b183e5f1a98884d9ae18ff99aacf1a54"
64
64
  }
package/src/index.ts CHANGED
@@ -52,18 +52,17 @@ export {
52
52
 
53
53
  // =================== Re-exporting deprecated types ===================
54
54
 
55
- // Cannot propagate deprecated JSDoc when re-export due to TypeScript bug: https://github.com/microsoft/TypeScript/issues/53960
56
- // export type {
57
- // /** @deprecated Use `Router` directly instead of `RouterInstance`. */
58
- // Router as RouterInstance
59
- // } from './router';
60
-
61
55
  import type { Router } from './router';
56
+ import type { Route, RouteLocation, RouteLocationInput } from './types';
57
+
62
58
  /** @deprecated Use `Router` directly instead of `RouterInstance`. */
63
59
  export type RouterInstance = Router;
64
60
 
65
- import type { Route, RouteLocationInput } from './types';
66
61
  /** @deprecated Use `RouteLocationInput` directly instead of `RouterRawLocation`. */
67
62
  export type RouterRawLocation = RouteLocationInput;
68
- /** @deprecated Use `Route` directly instead of `RouterLocation`. */
69
- export type RouterLocation = Route;
63
+
64
+ /** @deprecated Use `RouteLocation` directly instead of `RouterLocation`. */
65
+ export type RouterLocation = RouteLocation;
66
+
67
+ /** @deprecated Use `Route` directly instead of `RouteRecord`. */
68
+ export type RouteRecord = Route;
package/src/location.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { RouteLocationInput } from './types';
1
+ import type { RouteLocation, RouteLocationInput } from './types';
2
2
  import { isNotNullish } from './util';
3
3
 
4
4
  /**
@@ -94,3 +94,30 @@ export function parseLocation(toInput: RouteLocationInput, baseURL: URL): URL {
94
94
 
95
95
  return url;
96
96
  }
97
+
98
+ /**
99
+ * Resolves RouteLocationInput with fallback from previous route
100
+ * @param toInput - The route location input
101
+ * @param from - The previous route URL (optional)
102
+ * @returns Resolved RouteLocation object
103
+ */
104
+ export function resolveRouteLocationInput(
105
+ toInput: RouteLocationInput = '/',
106
+ from: URL | null = null
107
+ ): RouteLocation {
108
+ if (typeof toInput === 'string') {
109
+ return { path: toInput };
110
+ }
111
+
112
+ if (
113
+ toInput &&
114
+ typeof toInput === 'object' &&
115
+ typeof toInput.path !== 'string' &&
116
+ typeof toInput.url !== 'string' &&
117
+ from !== null
118
+ ) {
119
+ return { ...toInput, url: from.href };
120
+ }
121
+
122
+ return toInput;
123
+ }
package/src/route.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { IncomingMessage, ServerResponse } from 'node:http';
2
- import { parseLocation } from './location';
2
+ import { parseLocation, resolveRouteLocationInput } from './location';
3
3
  import { parsedOptions } from './options';
4
4
  import type { Router } from './router';
5
5
 
@@ -140,7 +140,6 @@ export class Route {
140
140
  constructor(routeOptions: Partial<RouteOptions> = {}) {
141
141
  const {
142
142
  toType = RouteType.push,
143
- toInput = '/',
144
143
  from = null,
145
144
  options = parsedOptions()
146
145
  } = routeOptions;
@@ -152,6 +151,7 @@ export class Route {
152
151
  this.context = options.context;
153
152
 
154
153
  const base = options.base;
154
+ const toInput = resolveRouteLocationInput(routeOptions.toInput, from);
155
155
  const to = options.normalizeURL(parseLocation(toInput, base), from);
156
156
  const isSameOrigin = to.origin === base.origin;
157
157
  const isSameBase = to.pathname.startsWith(base.pathname);
@@ -164,15 +164,10 @@ export class Route {
164
164
  : to.pathname;
165
165
  this.fullPath = (match ? this.path : to.pathname) + to.search + to.hash;
166
166
  this.matched = match ? match.matches : Object.freeze([]);
167
- this.keepScrollPosition = isPlainObject(toInput)
168
- ? Boolean(toInput.keepScrollPosition)
169
- : false;
170
- this.confirm =
171
- isPlainObject(toInput) && toInput.confirm ? toInput.confirm : null;
167
+ this.keepScrollPosition = Boolean(toInput.keepScrollPosition);
168
+ this.confirm = toInput.confirm || null;
172
169
  this.layer =
173
- toType === RouteType.pushLayer &&
174
- isPlainObject(toInput) &&
175
- toInput.layer
170
+ toType === RouteType.pushLayer && toInput.layer
176
171
  ? toInput.layer
177
172
  : null;
178
173
  this.config =
@@ -183,7 +178,7 @@ export class Route {
183
178
 
184
179
  // Initialize state object - create new local object, merge externally passed state
185
180
  const state: RouteState = {};
186
- if (isPlainObject(toInput) && toInput.state) {
181
+ if (toInput.state) {
187
182
  Object.assign(state, toInput.state);
188
183
  }
189
184
  this.state = state;
@@ -204,7 +199,7 @@ export class Route {
204
199
 
205
200
  // Set status code
206
201
  // Prioritize user-provided statusCode
207
- if (isPlainObject(toInput) && typeof toInput.statusCode === 'number') {
202
+ if (typeof toInput.statusCode === 'number') {
208
203
  this.statusCode = toInput.statusCode;
209
204
  }
210
205
  // If statusCode is not provided, keep default null value