@real-router/types 0.11.0 → 0.13.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/dist/cjs/index.d.ts +38 -9
- package/dist/cjs/metafile-cjs.json +1 -1
- package/dist/esm/index.d.mts +38 -9
- package/dist/esm/metafile-esm.json +1 -1
- package/package.json +4 -2
- package/src/base.ts +259 -0
- package/src/constants.ts +104 -0
- package/src/index.ts +62 -0
- package/src/limits.ts +61 -0
- package/src/route-node-types.ts +73 -0
- package/src/router.ts +302 -0
package/dist/cjs/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* This module exports ONLY the essential types used by real-router:
|
|
5
5
|
* - QueryParamsMode, QueryParamsOptions
|
|
6
|
-
* - RouteTreeState
|
|
6
|
+
* - RouteParams, RouteTreeState
|
|
7
7
|
*
|
|
8
8
|
* These types are copied from route-node to avoid circular dependencies.
|
|
9
9
|
*
|
|
@@ -44,18 +44,30 @@ interface SimpleState<P extends Params = Params> {
|
|
|
44
44
|
name: string;
|
|
45
45
|
params: P;
|
|
46
46
|
}
|
|
47
|
+
type TransitionPhase = "deactivating" | "activating" | "middleware";
|
|
48
|
+
type TransitionReason = "success" | "blocked" | "cancelled" | "error";
|
|
49
|
+
interface TransitionMeta {
|
|
50
|
+
phase: TransitionPhase;
|
|
51
|
+
from?: string;
|
|
52
|
+
reason: TransitionReason;
|
|
53
|
+
blocker?: string;
|
|
54
|
+
segments: {
|
|
55
|
+
deactivated: string[];
|
|
56
|
+
activated: string[];
|
|
57
|
+
intersection: string;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
47
60
|
interface State<P extends Params = Params, MP extends Params = Params> {
|
|
48
61
|
name: string;
|
|
49
62
|
params: P;
|
|
50
63
|
path: string;
|
|
51
64
|
meta?: StateMeta<MP> | undefined;
|
|
65
|
+
transition?: TransitionMeta | undefined;
|
|
52
66
|
}
|
|
53
67
|
interface StateMeta<P extends Params = Params> {
|
|
54
68
|
id: number;
|
|
55
69
|
params: P;
|
|
56
70
|
options: NavigationOptions;
|
|
57
|
-
redirected: boolean;
|
|
58
|
-
source?: string | undefined;
|
|
59
71
|
}
|
|
60
72
|
/**
|
|
61
73
|
* Input type for makeState meta parameter.
|
|
@@ -216,7 +228,7 @@ interface NavigationOptions {
|
|
|
216
228
|
* @description
|
|
217
229
|
* Automatically set by the router when a navigation is triggered by a redirect from
|
|
218
230
|
* middleware or lifecycle hooks. This flag is used internally to track redirect chains
|
|
219
|
-
* and is stored in state.meta.redirected.
|
|
231
|
+
* and is stored in state.meta.options.redirected.
|
|
220
232
|
*
|
|
221
233
|
* @default false (auto-set by router during redirects)
|
|
222
234
|
*
|
|
@@ -232,14 +244,14 @@ interface NavigationOptions {
|
|
|
232
244
|
* @example
|
|
233
245
|
* // Accessing redirect flag in lifecycle
|
|
234
246
|
* router.addActivateGuard('dashboard', (toState, fromState) => {
|
|
235
|
-
* if (toState.meta?.redirected) {
|
|
247
|
+
* if (toState.meta?.options?.redirected) {
|
|
236
248
|
* console.log('This navigation is from a redirect');
|
|
237
249
|
* }
|
|
238
250
|
* return true;
|
|
239
251
|
* });
|
|
240
252
|
*
|
|
241
253
|
* @see {@link Router.navigate} for redirect handling implementation
|
|
242
|
-
* @see {@link
|
|
254
|
+
* @see {@link NavigationOptions.redirected} for the input mechanism
|
|
243
255
|
*/
|
|
244
256
|
redirected?: boolean | undefined;
|
|
245
257
|
}
|
|
@@ -280,6 +292,13 @@ interface LimitsConfig {
|
|
|
280
292
|
* @default 10000
|
|
281
293
|
*/
|
|
282
294
|
maxListeners: number;
|
|
295
|
+
/**
|
|
296
|
+
* Listener count at which a memory leak warning is logged per event type.
|
|
297
|
+
* Set to 0 to disable the warning.
|
|
298
|
+
*
|
|
299
|
+
* @default 1000
|
|
300
|
+
*/
|
|
301
|
+
warnListeners: number;
|
|
283
302
|
/**
|
|
284
303
|
* Maximum depth of nested event propagation.
|
|
285
304
|
* Prevents infinite recursion in event handling chains.
|
|
@@ -511,6 +530,15 @@ interface Router {
|
|
|
511
530
|
* @returns true if navigation is allowed, false otherwise
|
|
512
531
|
*/
|
|
513
532
|
canNavigateTo: (name: string, params?: Params) => boolean;
|
|
533
|
+
/**
|
|
534
|
+
* Dispose the router and release all resources.
|
|
535
|
+
*
|
|
536
|
+
* Stops the router if active, calls plugin teardown, clears all event
|
|
537
|
+
* listeners, middleware, routes, and dependencies. After disposal, all
|
|
538
|
+
* mutating methods throw a ROUTER_DISPOSED error. Idempotent — safe to
|
|
539
|
+
* call multiple times.
|
|
540
|
+
*/
|
|
541
|
+
dispose: () => void;
|
|
514
542
|
}
|
|
515
543
|
|
|
516
544
|
/**
|
|
@@ -528,11 +556,11 @@ type EventsKeys = "ROUTER_START" | "ROUTER_STOP" | "TRANSITION_START" | "TRANSIT
|
|
|
528
556
|
/**
|
|
529
557
|
* Error code values
|
|
530
558
|
*/
|
|
531
|
-
type ErrorCodeValues = "NOT_STARTED" | "NO_START_PATH_OR_STATE" | "ALREADY_STARTED" | "ROUTE_NOT_FOUND" | "SAME_STATES" | "CANNOT_DEACTIVATE" | "CANNOT_ACTIVATE" | "TRANSITION_ERR" | "CANCELLED";
|
|
559
|
+
type ErrorCodeValues = "NOT_STARTED" | "NO_START_PATH_OR_STATE" | "ALREADY_STARTED" | "ROUTE_NOT_FOUND" | "SAME_STATES" | "CANNOT_DEACTIVATE" | "CANNOT_ACTIVATE" | "TRANSITION_ERR" | "CANCELLED" | "DISPOSED";
|
|
532
560
|
/**
|
|
533
561
|
* Error code keys
|
|
534
562
|
*/
|
|
535
|
-
type ErrorCodeKeys = "ROUTER_NOT_STARTED" | "NO_START_PATH_OR_STATE" | "ROUTER_ALREADY_STARTED" | "ROUTE_NOT_FOUND" | "SAME_STATES" | "CANNOT_DEACTIVATE" | "CANNOT_ACTIVATE" | "TRANSITION_ERR" | "TRANSITION_CANCELLED";
|
|
563
|
+
type ErrorCodeKeys = "ROUTER_NOT_STARTED" | "NO_START_PATH_OR_STATE" | "ROUTER_ALREADY_STARTED" | "ROUTE_NOT_FOUND" | "SAME_STATES" | "CANNOT_DEACTIVATE" | "CANNOT_ACTIVATE" | "TRANSITION_ERR" | "TRANSITION_CANCELLED" | "ROUTER_DISPOSED";
|
|
536
564
|
/**
|
|
537
565
|
* Mapping of event keys to plugin methods
|
|
538
566
|
*/
|
|
@@ -568,6 +596,7 @@ interface ErrorCodeToValueMap {
|
|
|
568
596
|
CANNOT_ACTIVATE: "CANNOT_ACTIVATE";
|
|
569
597
|
TRANSITION_ERR: "TRANSITION_ERR";
|
|
570
598
|
TRANSITION_CANCELLED: "CANCELLED";
|
|
599
|
+
ROUTER_DISPOSED: "DISPOSED";
|
|
571
600
|
}
|
|
572
601
|
|
|
573
|
-
export type { ActivationFn, Config, DefaultDependencies, DefaultParamsCallback, DefaultRouteCallback, ErrorCodeKeys, ErrorCodeToValueMap, ErrorCodeValues, EventName, EventToNameMap, EventToPluginMap, EventsKeys, ForwardToCallback, LimitsConfig, Listener, Middleware, NavigationOptions, Navigator, Options, Params, Plugin, PluginMethod, QueryParamsMode, QueryParamsOptions, RouteTreeState, Router, RouterError, SimpleState, State, StateMeta, StateMetaInput, SubscribeFn, SubscribeState, Subscription, Unsubscribe };
|
|
602
|
+
export type { ActivationFn, Config, DefaultDependencies, DefaultParamsCallback, DefaultRouteCallback, ErrorCodeKeys, ErrorCodeToValueMap, ErrorCodeValues, EventName, EventToNameMap, EventToPluginMap, EventsKeys, ForwardToCallback, LimitsConfig, Listener, Middleware, NavigationOptions, Navigator, Options, Params, Plugin, PluginMethod, QueryParamsMode, QueryParamsOptions, RouteParams, RouteTreeState, Router, RouterError, SimpleState, State, StateMeta, StateMetaInput, SubscribeFn, SubscribeState, Subscription, TransitionMeta, TransitionPhase, TransitionReason, Unsubscribe };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js":{"bytes":569,"imports":[],"format":"esm"},"src/index.ts":{"bytes":
|
|
1
|
+
{"inputs":{"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js":{"bytes":569,"imports":[],"format":"esm"},"src/index.ts":{"bytes":1298,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"dist/cjs/index.js":{"imports":[],"exports":[],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":0}},"bytes":0}}}
|
package/dist/esm/index.d.mts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* This module exports ONLY the essential types used by real-router:
|
|
5
5
|
* - QueryParamsMode, QueryParamsOptions
|
|
6
|
-
* - RouteTreeState
|
|
6
|
+
* - RouteParams, RouteTreeState
|
|
7
7
|
*
|
|
8
8
|
* These types are copied from route-node to avoid circular dependencies.
|
|
9
9
|
*
|
|
@@ -44,18 +44,30 @@ interface SimpleState<P extends Params = Params> {
|
|
|
44
44
|
name: string;
|
|
45
45
|
params: P;
|
|
46
46
|
}
|
|
47
|
+
type TransitionPhase = "deactivating" | "activating" | "middleware";
|
|
48
|
+
type TransitionReason = "success" | "blocked" | "cancelled" | "error";
|
|
49
|
+
interface TransitionMeta {
|
|
50
|
+
phase: TransitionPhase;
|
|
51
|
+
from?: string;
|
|
52
|
+
reason: TransitionReason;
|
|
53
|
+
blocker?: string;
|
|
54
|
+
segments: {
|
|
55
|
+
deactivated: string[];
|
|
56
|
+
activated: string[];
|
|
57
|
+
intersection: string;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
47
60
|
interface State<P extends Params = Params, MP extends Params = Params> {
|
|
48
61
|
name: string;
|
|
49
62
|
params: P;
|
|
50
63
|
path: string;
|
|
51
64
|
meta?: StateMeta<MP> | undefined;
|
|
65
|
+
transition?: TransitionMeta | undefined;
|
|
52
66
|
}
|
|
53
67
|
interface StateMeta<P extends Params = Params> {
|
|
54
68
|
id: number;
|
|
55
69
|
params: P;
|
|
56
70
|
options: NavigationOptions;
|
|
57
|
-
redirected: boolean;
|
|
58
|
-
source?: string | undefined;
|
|
59
71
|
}
|
|
60
72
|
/**
|
|
61
73
|
* Input type for makeState meta parameter.
|
|
@@ -216,7 +228,7 @@ interface NavigationOptions {
|
|
|
216
228
|
* @description
|
|
217
229
|
* Automatically set by the router when a navigation is triggered by a redirect from
|
|
218
230
|
* middleware or lifecycle hooks. This flag is used internally to track redirect chains
|
|
219
|
-
* and is stored in state.meta.redirected.
|
|
231
|
+
* and is stored in state.meta.options.redirected.
|
|
220
232
|
*
|
|
221
233
|
* @default false (auto-set by router during redirects)
|
|
222
234
|
*
|
|
@@ -232,14 +244,14 @@ interface NavigationOptions {
|
|
|
232
244
|
* @example
|
|
233
245
|
* // Accessing redirect flag in lifecycle
|
|
234
246
|
* router.addActivateGuard('dashboard', (toState, fromState) => {
|
|
235
|
-
* if (toState.meta?.redirected) {
|
|
247
|
+
* if (toState.meta?.options?.redirected) {
|
|
236
248
|
* console.log('This navigation is from a redirect');
|
|
237
249
|
* }
|
|
238
250
|
* return true;
|
|
239
251
|
* });
|
|
240
252
|
*
|
|
241
253
|
* @see {@link Router.navigate} for redirect handling implementation
|
|
242
|
-
* @see {@link
|
|
254
|
+
* @see {@link NavigationOptions.redirected} for the input mechanism
|
|
243
255
|
*/
|
|
244
256
|
redirected?: boolean | undefined;
|
|
245
257
|
}
|
|
@@ -280,6 +292,13 @@ interface LimitsConfig {
|
|
|
280
292
|
* @default 10000
|
|
281
293
|
*/
|
|
282
294
|
maxListeners: number;
|
|
295
|
+
/**
|
|
296
|
+
* Listener count at which a memory leak warning is logged per event type.
|
|
297
|
+
* Set to 0 to disable the warning.
|
|
298
|
+
*
|
|
299
|
+
* @default 1000
|
|
300
|
+
*/
|
|
301
|
+
warnListeners: number;
|
|
283
302
|
/**
|
|
284
303
|
* Maximum depth of nested event propagation.
|
|
285
304
|
* Prevents infinite recursion in event handling chains.
|
|
@@ -511,6 +530,15 @@ interface Router {
|
|
|
511
530
|
* @returns true if navigation is allowed, false otherwise
|
|
512
531
|
*/
|
|
513
532
|
canNavigateTo: (name: string, params?: Params) => boolean;
|
|
533
|
+
/**
|
|
534
|
+
* Dispose the router and release all resources.
|
|
535
|
+
*
|
|
536
|
+
* Stops the router if active, calls plugin teardown, clears all event
|
|
537
|
+
* listeners, middleware, routes, and dependencies. After disposal, all
|
|
538
|
+
* mutating methods throw a ROUTER_DISPOSED error. Idempotent — safe to
|
|
539
|
+
* call multiple times.
|
|
540
|
+
*/
|
|
541
|
+
dispose: () => void;
|
|
514
542
|
}
|
|
515
543
|
|
|
516
544
|
/**
|
|
@@ -528,11 +556,11 @@ type EventsKeys = "ROUTER_START" | "ROUTER_STOP" | "TRANSITION_START" | "TRANSIT
|
|
|
528
556
|
/**
|
|
529
557
|
* Error code values
|
|
530
558
|
*/
|
|
531
|
-
type ErrorCodeValues = "NOT_STARTED" | "NO_START_PATH_OR_STATE" | "ALREADY_STARTED" | "ROUTE_NOT_FOUND" | "SAME_STATES" | "CANNOT_DEACTIVATE" | "CANNOT_ACTIVATE" | "TRANSITION_ERR" | "CANCELLED";
|
|
559
|
+
type ErrorCodeValues = "NOT_STARTED" | "NO_START_PATH_OR_STATE" | "ALREADY_STARTED" | "ROUTE_NOT_FOUND" | "SAME_STATES" | "CANNOT_DEACTIVATE" | "CANNOT_ACTIVATE" | "TRANSITION_ERR" | "CANCELLED" | "DISPOSED";
|
|
532
560
|
/**
|
|
533
561
|
* Error code keys
|
|
534
562
|
*/
|
|
535
|
-
type ErrorCodeKeys = "ROUTER_NOT_STARTED" | "NO_START_PATH_OR_STATE" | "ROUTER_ALREADY_STARTED" | "ROUTE_NOT_FOUND" | "SAME_STATES" | "CANNOT_DEACTIVATE" | "CANNOT_ACTIVATE" | "TRANSITION_ERR" | "TRANSITION_CANCELLED";
|
|
563
|
+
type ErrorCodeKeys = "ROUTER_NOT_STARTED" | "NO_START_PATH_OR_STATE" | "ROUTER_ALREADY_STARTED" | "ROUTE_NOT_FOUND" | "SAME_STATES" | "CANNOT_DEACTIVATE" | "CANNOT_ACTIVATE" | "TRANSITION_ERR" | "TRANSITION_CANCELLED" | "ROUTER_DISPOSED";
|
|
536
564
|
/**
|
|
537
565
|
* Mapping of event keys to plugin methods
|
|
538
566
|
*/
|
|
@@ -568,6 +596,7 @@ interface ErrorCodeToValueMap {
|
|
|
568
596
|
CANNOT_ACTIVATE: "CANNOT_ACTIVATE";
|
|
569
597
|
TRANSITION_ERR: "TRANSITION_ERR";
|
|
570
598
|
TRANSITION_CANCELLED: "CANCELLED";
|
|
599
|
+
ROUTER_DISPOSED: "DISPOSED";
|
|
571
600
|
}
|
|
572
601
|
|
|
573
|
-
export type { ActivationFn, Config, DefaultDependencies, DefaultParamsCallback, DefaultRouteCallback, ErrorCodeKeys, ErrorCodeToValueMap, ErrorCodeValues, EventName, EventToNameMap, EventToPluginMap, EventsKeys, ForwardToCallback, LimitsConfig, Listener, Middleware, NavigationOptions, Navigator, Options, Params, Plugin, PluginMethod, QueryParamsMode, QueryParamsOptions, RouteTreeState, Router, RouterError, SimpleState, State, StateMeta, StateMetaInput, SubscribeFn, SubscribeState, Subscription, Unsubscribe };
|
|
602
|
+
export type { ActivationFn, Config, DefaultDependencies, DefaultParamsCallback, DefaultRouteCallback, ErrorCodeKeys, ErrorCodeToValueMap, ErrorCodeValues, EventName, EventToNameMap, EventToPluginMap, EventsKeys, ForwardToCallback, LimitsConfig, Listener, Middleware, NavigationOptions, Navigator, Options, Params, Plugin, PluginMethod, QueryParamsMode, QueryParamsOptions, RouteParams, RouteTreeState, Router, RouterError, SimpleState, State, StateMeta, StateMetaInput, SubscribeFn, SubscribeState, Subscription, TransitionMeta, TransitionPhase, TransitionReason, Unsubscribe };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"src/index.ts":{"bytes":
|
|
1
|
+
{"inputs":{"src/index.ts":{"bytes":1298,"imports":[],"format":"esm"}},"outputs":{"dist/esm/index.mjs":{"imports":[],"exports":[],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":0}},"bytes":0}}}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@real-router/types",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"description": "Shared TypeScript types for Real Router ecosystem",
|
|
6
6
|
"types": "./dist/esm/index.d.mts",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": {
|
|
9
|
+
"development": "./src/index.ts",
|
|
9
10
|
"types": {
|
|
10
11
|
"import": "./dist/esm/index.d.mts",
|
|
11
12
|
"require": "./dist/cjs/index.d.ts"
|
|
@@ -13,7 +14,8 @@
|
|
|
13
14
|
}
|
|
14
15
|
},
|
|
15
16
|
"files": [
|
|
16
|
-
"dist"
|
|
17
|
+
"dist",
|
|
18
|
+
"src"
|
|
17
19
|
],
|
|
18
20
|
"repository": {
|
|
19
21
|
"type": "git",
|
package/src/base.ts
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
// packages/core-types/modules/base.ts
|
|
2
|
+
|
|
3
|
+
// Note: RouteTreeState is exported from route-node-types.ts
|
|
4
|
+
// It uses RouteParams as default type parameter.
|
|
5
|
+
// Real Router code should use RouteTreeState<Params> when needed.
|
|
6
|
+
|
|
7
|
+
export type Unsubscribe = () => void;
|
|
8
|
+
|
|
9
|
+
export interface SimpleState<P extends Params = Params> {
|
|
10
|
+
name: string;
|
|
11
|
+
params: P;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type TransitionPhase = "deactivating" | "activating" | "middleware";
|
|
15
|
+
|
|
16
|
+
export type TransitionReason = "success" | "blocked" | "cancelled" | "error";
|
|
17
|
+
|
|
18
|
+
export interface TransitionMeta {
|
|
19
|
+
phase: TransitionPhase;
|
|
20
|
+
from?: string;
|
|
21
|
+
reason: TransitionReason;
|
|
22
|
+
blocker?: string;
|
|
23
|
+
segments: {
|
|
24
|
+
deactivated: string[];
|
|
25
|
+
activated: string[];
|
|
26
|
+
intersection: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface State<P extends Params = Params, MP extends Params = Params> {
|
|
31
|
+
name: string;
|
|
32
|
+
params: P;
|
|
33
|
+
path: string;
|
|
34
|
+
meta?: StateMeta<MP> | undefined;
|
|
35
|
+
transition?: TransitionMeta | undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface StateMeta<P extends Params = Params> {
|
|
39
|
+
id: number;
|
|
40
|
+
params: P;
|
|
41
|
+
options: NavigationOptions;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Input type for makeState meta parameter.
|
|
46
|
+
* Omits `id` since it's auto-generated by makeState.
|
|
47
|
+
*/
|
|
48
|
+
export type StateMetaInput<P extends Params = Params> = Omit<
|
|
49
|
+
StateMeta<P>,
|
|
50
|
+
"id"
|
|
51
|
+
>;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* RouterError interface describing the public API of the RouterError class.
|
|
55
|
+
* The actual class implementation is in the real-router package.
|
|
56
|
+
* This interface enables structural typing compatibility between
|
|
57
|
+
* core-types and real-router packages.
|
|
58
|
+
*/
|
|
59
|
+
export interface RouterError extends Error {
|
|
60
|
+
[key: string]: unknown;
|
|
61
|
+
readonly code: string;
|
|
62
|
+
readonly segment: string | undefined;
|
|
63
|
+
readonly path: string | undefined;
|
|
64
|
+
readonly redirect: State | undefined;
|
|
65
|
+
setCode: (code: string) => void;
|
|
66
|
+
setErrorInstance: (err: Error) => void;
|
|
67
|
+
setAdditionalFields: (fields: Record<string, unknown>) => void;
|
|
68
|
+
hasField: (key: string) => boolean;
|
|
69
|
+
getField: (key: string) => unknown;
|
|
70
|
+
toJSON: () => Record<string, unknown>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Configuration options that control navigation transition behavior.
|
|
75
|
+
*
|
|
76
|
+
* @description
|
|
77
|
+
* NavigationOptions provides fine-grained control over how the router performs navigation
|
|
78
|
+
* transitions. These options affect history management, transition lifecycle execution,
|
|
79
|
+
* guard enforcement, and state comparison logic.
|
|
80
|
+
*
|
|
81
|
+
* All options are optional and have sensible defaults. Options can be combined to achieve
|
|
82
|
+
* complex navigation behaviors. The options object is stored in state.meta.options and is
|
|
83
|
+
* available to middleware, guards, and event listeners.
|
|
84
|
+
*
|
|
85
|
+
* @see {@link Router.navigate} for navigation method that accepts these options
|
|
86
|
+
* @see {@link State.meta} for where options are stored after navigation
|
|
87
|
+
*/
|
|
88
|
+
export interface NavigationOptions {
|
|
89
|
+
[key: string]:
|
|
90
|
+
| string
|
|
91
|
+
| number
|
|
92
|
+
| boolean
|
|
93
|
+
| Record<string, unknown>
|
|
94
|
+
| undefined;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Replace the current history entry instead of pushing a new one.
|
|
98
|
+
*
|
|
99
|
+
* @description
|
|
100
|
+
* When `true`, the navigation will replace the current entry in browser history instead
|
|
101
|
+
* of adding a new entry. This is typically used by history plugins (browser plugin) to
|
|
102
|
+
* control how navigation affects the browser's back/forward buttons.
|
|
103
|
+
*
|
|
104
|
+
* @default false
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* // Redirect after login - prevent back button to login page
|
|
108
|
+
* router.navigate('dashboard', {}, { replace: true });
|
|
109
|
+
*
|
|
110
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/History/replaceState}
|
|
111
|
+
*/
|
|
112
|
+
replace?: boolean | undefined;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Force reload of the current route even if states are equal.
|
|
116
|
+
*
|
|
117
|
+
* @description
|
|
118
|
+
* When `true`, bypasses the "same state" check that normally prevents navigation when
|
|
119
|
+
* the target state equals the current state. This forces a full transition lifecycle
|
|
120
|
+
* execution, allowing route components to reload with the same parameters.
|
|
121
|
+
*
|
|
122
|
+
* Without `reload`:
|
|
123
|
+
* - Navigation to current route throws SAME_STATES error
|
|
124
|
+
* - No lifecycle hooks or middleware execute
|
|
125
|
+
* - No events are fired
|
|
126
|
+
*
|
|
127
|
+
* With `reload`:
|
|
128
|
+
* - Full transition executes (deactivate → activate → middleware)
|
|
129
|
+
* - All lifecycle hooks run again
|
|
130
|
+
* - TRANSITION_SUCCESS event fires with same state
|
|
131
|
+
* - State object is recreated (new reference)
|
|
132
|
+
*
|
|
133
|
+
* @default false
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* // Refresh current page data
|
|
137
|
+
* router.navigate(currentRoute.name, currentRoute.params, { reload: true });
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* // Force re-fetch on same route with different query params
|
|
141
|
+
* // Note: query params are in path, not checked for equality
|
|
142
|
+
* router.navigate('search', { term: 'react' }, { reload: true });
|
|
143
|
+
*
|
|
144
|
+
* @see {@link force} for alternative that forces transition
|
|
145
|
+
* @see {@link Router.areStatesEqual} for state comparison logic
|
|
146
|
+
*/
|
|
147
|
+
reload?: boolean | undefined;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Force navigation even if target state equals current state.
|
|
151
|
+
*
|
|
152
|
+
* @description
|
|
153
|
+
* When `true`, bypasses the "same state" equality check but still executes the full
|
|
154
|
+
* transition lifecycle. Similar to `reload` but can be used
|
|
155
|
+
* for any forced navigation scenario.
|
|
156
|
+
*
|
|
157
|
+
* Difference from `reload`:
|
|
158
|
+
* - `reload`: semantic meaning is "refresh current route"
|
|
159
|
+
* - `force`: general-purpose bypass of equality check
|
|
160
|
+
* - Both have identical implementation effect
|
|
161
|
+
*
|
|
162
|
+
* The equality check compares:
|
|
163
|
+
* - state.name (route name)
|
|
164
|
+
* - state.params (route parameters, shallow comparison)
|
|
165
|
+
*
|
|
166
|
+
* @default false
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* // Force transition for tracking even if params didn't change
|
|
170
|
+
* router.navigate('analytics', { event: 'pageview' }, { force: true });
|
|
171
|
+
*
|
|
172
|
+
* @see {@link reload} for semantic equivalent (preferred for refresh scenarios)
|
|
173
|
+
*/
|
|
174
|
+
force?: boolean | undefined;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Skip canDeactivate guards during transition.
|
|
178
|
+
*
|
|
179
|
+
* @description
|
|
180
|
+
* When `true`, bypasses only the canDeactivate lifecycle hooks for segments being
|
|
181
|
+
* deactivated. canActivate guards and middleware still execute normally. This allows
|
|
182
|
+
* forcing navigation away from routes with confirmation dialogs or unsaved changes.
|
|
183
|
+
*
|
|
184
|
+
* Skipped vs executed:
|
|
185
|
+
* ```
|
|
186
|
+
* // Normal transition
|
|
187
|
+
* deactivate(fromSegments) → activate(toSegments) → middleware → success
|
|
188
|
+
*
|
|
189
|
+
* // With forceDeactivate: true
|
|
190
|
+
* [skip deactivate] → activate(toSegments) → middleware → success
|
|
191
|
+
* ```
|
|
192
|
+
*
|
|
193
|
+
* ⚠️ Data loss risk: Bypassing canDeactivate means unsaved changes will be lost
|
|
194
|
+
*
|
|
195
|
+
* @default false
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* // Force logout even with unsaved changes
|
|
199
|
+
* function forceLogout() {
|
|
200
|
+
* router.navigate('login', {}, {
|
|
201
|
+
* forceDeactivate: true,
|
|
202
|
+
* replace: true
|
|
203
|
+
* });
|
|
204
|
+
* }
|
|
205
|
+
*
|
|
206
|
+
* @see {@link Router.clearCanDeactivate} for programmatically clearing guards
|
|
207
|
+
*/
|
|
208
|
+
forceDeactivate?: boolean | undefined;
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Internal flag indicating navigation is result of a redirect.
|
|
212
|
+
*
|
|
213
|
+
* @internal
|
|
214
|
+
*
|
|
215
|
+
* @description
|
|
216
|
+
* Automatically set by the router when a navigation is triggered by a redirect from
|
|
217
|
+
* middleware or lifecycle hooks. This flag is used internally to track redirect chains
|
|
218
|
+
* and is stored in state.meta.options.redirected.
|
|
219
|
+
*
|
|
220
|
+
* @default false (auto-set by router during redirects)
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* // Middleware triggers automatic redirect
|
|
224
|
+
* router.useMiddleware((toState, fromState, opts) => {
|
|
225
|
+
* if (!isAuthenticated && toState.name !== 'login') {
|
|
226
|
+
* // Router will automatically set redirected: true
|
|
227
|
+
* return { name: 'login', params: { next: toState.path } };
|
|
228
|
+
* }
|
|
229
|
+
* });
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* // Accessing redirect flag in lifecycle
|
|
233
|
+
* router.addActivateGuard('dashboard', (toState, fromState) => {
|
|
234
|
+
* if (toState.meta?.options?.redirected) {
|
|
235
|
+
* console.log('This navigation is from a redirect');
|
|
236
|
+
* }
|
|
237
|
+
* return true;
|
|
238
|
+
* });
|
|
239
|
+
*
|
|
240
|
+
* @see {@link Router.navigate} for redirect handling implementation
|
|
241
|
+
* @see {@link NavigationOptions.redirected} for the input mechanism
|
|
242
|
+
*/
|
|
243
|
+
redirected?: boolean | undefined;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export interface Params {
|
|
247
|
+
[key: string]:
|
|
248
|
+
| string
|
|
249
|
+
| string[]
|
|
250
|
+
| number
|
|
251
|
+
| number[]
|
|
252
|
+
| boolean
|
|
253
|
+
| boolean[]
|
|
254
|
+
| Params
|
|
255
|
+
| Params[]
|
|
256
|
+
| Record<string, string | number | boolean>
|
|
257
|
+
| null
|
|
258
|
+
| undefined;
|
|
259
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// packages/core-types/modules/constants.ts
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Plugin lifecycle method names
|
|
5
|
+
*/
|
|
6
|
+
export type PluginMethod =
|
|
7
|
+
| "onStart"
|
|
8
|
+
| "onStop"
|
|
9
|
+
| "onTransitionStart"
|
|
10
|
+
| "onTransitionCancel"
|
|
11
|
+
| "onTransitionSuccess"
|
|
12
|
+
| "onTransitionError";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Router event names
|
|
16
|
+
*/
|
|
17
|
+
export type EventName =
|
|
18
|
+
| "$start"
|
|
19
|
+
| "$stop"
|
|
20
|
+
| "$$start"
|
|
21
|
+
| "$$cancel"
|
|
22
|
+
| "$$success"
|
|
23
|
+
| "$$error";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Event type keys
|
|
27
|
+
*/
|
|
28
|
+
export type EventsKeys =
|
|
29
|
+
| "ROUTER_START"
|
|
30
|
+
| "ROUTER_STOP"
|
|
31
|
+
| "TRANSITION_START"
|
|
32
|
+
| "TRANSITION_CANCEL"
|
|
33
|
+
| "TRANSITION_SUCCESS"
|
|
34
|
+
| "TRANSITION_ERROR";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Error code values
|
|
38
|
+
*/
|
|
39
|
+
export type ErrorCodeValues =
|
|
40
|
+
| "NOT_STARTED"
|
|
41
|
+
| "NO_START_PATH_OR_STATE"
|
|
42
|
+
| "ALREADY_STARTED"
|
|
43
|
+
| "ROUTE_NOT_FOUND"
|
|
44
|
+
| "SAME_STATES"
|
|
45
|
+
| "CANNOT_DEACTIVATE"
|
|
46
|
+
| "CANNOT_ACTIVATE"
|
|
47
|
+
| "TRANSITION_ERR"
|
|
48
|
+
| "CANCELLED"
|
|
49
|
+
| "DISPOSED";
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Error code keys
|
|
53
|
+
*/
|
|
54
|
+
export type ErrorCodeKeys =
|
|
55
|
+
| "ROUTER_NOT_STARTED"
|
|
56
|
+
| "NO_START_PATH_OR_STATE"
|
|
57
|
+
| "ROUTER_ALREADY_STARTED"
|
|
58
|
+
| "ROUTE_NOT_FOUND"
|
|
59
|
+
| "SAME_STATES"
|
|
60
|
+
| "CANNOT_DEACTIVATE"
|
|
61
|
+
| "CANNOT_ACTIVATE"
|
|
62
|
+
| "TRANSITION_ERR"
|
|
63
|
+
| "TRANSITION_CANCELLED"
|
|
64
|
+
| "ROUTER_DISPOSED";
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Mapping of event keys to plugin methods
|
|
68
|
+
*/
|
|
69
|
+
export interface EventToPluginMap {
|
|
70
|
+
readonly ROUTER_START: "onStart";
|
|
71
|
+
readonly ROUTER_STOP: "onStop";
|
|
72
|
+
readonly TRANSITION_START: "onTransitionStart";
|
|
73
|
+
readonly TRANSITION_CANCEL: "onTransitionCancel";
|
|
74
|
+
readonly TRANSITION_SUCCESS: "onTransitionSuccess";
|
|
75
|
+
readonly TRANSITION_ERROR: "onTransitionError";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Mapping of event keys to event names
|
|
80
|
+
*/
|
|
81
|
+
export interface EventToNameMap {
|
|
82
|
+
ROUTER_START: "$start";
|
|
83
|
+
ROUTER_STOP: "$stop";
|
|
84
|
+
TRANSITION_START: "$$start";
|
|
85
|
+
TRANSITION_CANCEL: "$$cancel";
|
|
86
|
+
TRANSITION_SUCCESS: "$$success";
|
|
87
|
+
TRANSITION_ERROR: "$$error";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Mapping of error code keys to their values
|
|
92
|
+
*/
|
|
93
|
+
export interface ErrorCodeToValueMap {
|
|
94
|
+
ROUTER_NOT_STARTED: "NOT_STARTED";
|
|
95
|
+
NO_START_PATH_OR_STATE: "NO_START_PATH_OR_STATE";
|
|
96
|
+
ROUTER_ALREADY_STARTED: "ALREADY_STARTED";
|
|
97
|
+
ROUTE_NOT_FOUND: "ROUTE_NOT_FOUND";
|
|
98
|
+
SAME_STATES: "SAME_STATES";
|
|
99
|
+
CANNOT_DEACTIVATE: "CANNOT_DEACTIVATE";
|
|
100
|
+
CANNOT_ACTIVATE: "CANNOT_ACTIVATE";
|
|
101
|
+
TRANSITION_ERR: "TRANSITION_ERR";
|
|
102
|
+
TRANSITION_CANCELLED: "CANCELLED";
|
|
103
|
+
ROUTER_DISPOSED: "DISPOSED";
|
|
104
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// packages/core-types/modules/index.ts
|
|
2
|
+
|
|
3
|
+
// Route node types
|
|
4
|
+
export type {
|
|
5
|
+
QueryParamsMode,
|
|
6
|
+
QueryParamsOptions,
|
|
7
|
+
RouteParams,
|
|
8
|
+
RouteTreeState,
|
|
9
|
+
} from "./route-node-types";
|
|
10
|
+
|
|
11
|
+
// Base types
|
|
12
|
+
export type {
|
|
13
|
+
Params,
|
|
14
|
+
State,
|
|
15
|
+
StateMeta,
|
|
16
|
+
StateMetaInput,
|
|
17
|
+
SimpleState,
|
|
18
|
+
NavigationOptions,
|
|
19
|
+
Unsubscribe,
|
|
20
|
+
RouterError,
|
|
21
|
+
TransitionPhase,
|
|
22
|
+
TransitionReason,
|
|
23
|
+
TransitionMeta,
|
|
24
|
+
} from "./base";
|
|
25
|
+
|
|
26
|
+
// Router types (base types without Router dependency)
|
|
27
|
+
// Note: Route, RouteConfigUpdate, ActivationFnFactory, MiddlewareFactory,
|
|
28
|
+
// PluginFactory, BuildStateResultWithSegments are in @real-router/core
|
|
29
|
+
export type {
|
|
30
|
+
Options,
|
|
31
|
+
DefaultRouteCallback,
|
|
32
|
+
ForwardToCallback,
|
|
33
|
+
DefaultParamsCallback,
|
|
34
|
+
ActivationFn,
|
|
35
|
+
DefaultDependencies,
|
|
36
|
+
Config,
|
|
37
|
+
Plugin,
|
|
38
|
+
Middleware,
|
|
39
|
+
SubscribeState,
|
|
40
|
+
SubscribeFn,
|
|
41
|
+
Listener,
|
|
42
|
+
Subscription,
|
|
43
|
+
Navigator,
|
|
44
|
+
Router,
|
|
45
|
+
} from "./router";
|
|
46
|
+
|
|
47
|
+
// Limits configuration
|
|
48
|
+
export type { LimitsConfig } from "./limits";
|
|
49
|
+
|
|
50
|
+
export type {
|
|
51
|
+
PluginMethod,
|
|
52
|
+
EventName,
|
|
53
|
+
EventsKeys,
|
|
54
|
+
ErrorCodeValues,
|
|
55
|
+
ErrorCodeKeys,
|
|
56
|
+
EventToPluginMap,
|
|
57
|
+
EventToNameMap,
|
|
58
|
+
ErrorCodeToValueMap,
|
|
59
|
+
} from "./constants";
|
|
60
|
+
|
|
61
|
+
// Note: RouterError type is a forward declaration matching the class in real-router package
|
|
62
|
+
// Use import { RouterError } from "real-router" for the actual class implementation
|
package/src/limits.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for router resource limits.
|
|
3
|
+
* Controls maximum allowed values for various router operations to prevent resource exhaustion.
|
|
4
|
+
*/
|
|
5
|
+
export interface LimitsConfig {
|
|
6
|
+
/**
|
|
7
|
+
* Maximum number of route dependencies allowed.
|
|
8
|
+
* Prevents circular dependency chains and excessive dependency graphs.
|
|
9
|
+
*
|
|
10
|
+
* @default 100
|
|
11
|
+
*/
|
|
12
|
+
maxDependencies: number;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Maximum number of plugins that can be registered.
|
|
16
|
+
* Limits plugin stack depth to prevent performance degradation.
|
|
17
|
+
*
|
|
18
|
+
* @default 50
|
|
19
|
+
*/
|
|
20
|
+
maxPlugins: number;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Maximum number of middleware functions in the navigation pipeline.
|
|
24
|
+
* Controls middleware chain length to prevent stack overflow and performance issues.
|
|
25
|
+
*
|
|
26
|
+
* @default 50
|
|
27
|
+
*/
|
|
28
|
+
maxMiddleware: number;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Maximum number of event listeners per event type.
|
|
32
|
+
* Prevents memory leaks from excessive listener registration.
|
|
33
|
+
*
|
|
34
|
+
* @default 10000
|
|
35
|
+
*/
|
|
36
|
+
maxListeners: number;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Listener count at which a memory leak warning is logged per event type.
|
|
40
|
+
* Set to 0 to disable the warning.
|
|
41
|
+
*
|
|
42
|
+
* @default 1000
|
|
43
|
+
*/
|
|
44
|
+
warnListeners: number;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Maximum depth of nested event propagation.
|
|
48
|
+
* Prevents infinite recursion in event handling chains.
|
|
49
|
+
*
|
|
50
|
+
* @default 5
|
|
51
|
+
*/
|
|
52
|
+
maxEventDepth: number;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Maximum number of lifecycle handlers (canActivate/canDeactivate) per route.
|
|
56
|
+
* Controls guard function stack to prevent excessive validation overhead.
|
|
57
|
+
*
|
|
58
|
+
* @default 200
|
|
59
|
+
*/
|
|
60
|
+
maxLifecycleHandlers: number;
|
|
61
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// packages/core-types/modules/route-node-types.ts
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Route Node Type Definitions — Minimal Public API.
|
|
5
|
+
*
|
|
6
|
+
* This module exports ONLY the essential types used by real-router:
|
|
7
|
+
* - QueryParamsMode, QueryParamsOptions
|
|
8
|
+
* - RouteParams, RouteTreeState
|
|
9
|
+
*
|
|
10
|
+
* These types are copied from route-node to avoid circular dependencies.
|
|
11
|
+
*
|
|
12
|
+
* @module route-node-types
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// Search Params Types
|
|
17
|
+
// =============================================================================
|
|
18
|
+
|
|
19
|
+
type ArrayFormat = "none" | "brackets" | "index" | "comma";
|
|
20
|
+
type BooleanFormat = "none" | "string" | "empty-true";
|
|
21
|
+
type NullFormat = "default" | "hidden";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Options for query parameter parsing and building.
|
|
25
|
+
*/
|
|
26
|
+
export interface QueryParamsOptions {
|
|
27
|
+
arrayFormat?: ArrayFormat;
|
|
28
|
+
booleanFormat?: BooleanFormat;
|
|
29
|
+
nullFormat?: NullFormat;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// =============================================================================
|
|
33
|
+
// Mode Types
|
|
34
|
+
// =============================================================================
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Controls how query parameters are handled during matching.
|
|
38
|
+
*/
|
|
39
|
+
export type QueryParamsMode = "default" | "strict" | "loose";
|
|
40
|
+
|
|
41
|
+
// =============================================================================
|
|
42
|
+
// Route State Types
|
|
43
|
+
// =============================================================================
|
|
44
|
+
|
|
45
|
+
type ParamSource = "url" | "query";
|
|
46
|
+
type ParamTypeMap = Record<string, ParamSource>;
|
|
47
|
+
type RouteTreeStateMeta = Record<string, ParamTypeMap>;
|
|
48
|
+
|
|
49
|
+
export interface RouteParams {
|
|
50
|
+
[key: string]:
|
|
51
|
+
| string
|
|
52
|
+
| string[]
|
|
53
|
+
| number
|
|
54
|
+
| number[]
|
|
55
|
+
| boolean
|
|
56
|
+
| boolean[]
|
|
57
|
+
| RouteParams
|
|
58
|
+
| RouteParams[]
|
|
59
|
+
| Record<string, string | number | boolean>
|
|
60
|
+
| null
|
|
61
|
+
| undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Complete state representation of a matched route.
|
|
66
|
+
*/
|
|
67
|
+
export interface RouteTreeState<
|
|
68
|
+
P extends Record<string, unknown> = RouteParams,
|
|
69
|
+
> {
|
|
70
|
+
name: string;
|
|
71
|
+
params: P;
|
|
72
|
+
meta: RouteTreeStateMeta;
|
|
73
|
+
}
|
package/src/router.ts
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
// packages/core-types/modules/router.ts
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base router types without Router class dependency.
|
|
5
|
+
*
|
|
6
|
+
* Router-dependent types (Route, RouteConfigUpdate, ActivationFnFactory,
|
|
7
|
+
* MiddlewareFactory, PluginFactory) are defined in @real-router/core
|
|
8
|
+
* to avoid circular dependencies.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type {
|
|
12
|
+
State,
|
|
13
|
+
Params,
|
|
14
|
+
NavigationOptions,
|
|
15
|
+
RouterError,
|
|
16
|
+
Unsubscribe,
|
|
17
|
+
} from "./base";
|
|
18
|
+
import type { LimitsConfig } from "./limits";
|
|
19
|
+
import type { QueryParamsMode, QueryParamsOptions } from "./route-node-types";
|
|
20
|
+
|
|
21
|
+
// Logger types (duplicated from @real-router/logger to avoid dependency)
|
|
22
|
+
type LogLevel = "log" | "warn" | "error";
|
|
23
|
+
type LogLevelConfig = "all" | "warn-error" | "error-only" | "none";
|
|
24
|
+
type LogCallback = (
|
|
25
|
+
level: LogLevel,
|
|
26
|
+
context: string,
|
|
27
|
+
message: string,
|
|
28
|
+
...args: unknown[]
|
|
29
|
+
) => void;
|
|
30
|
+
interface LoggerConfig {
|
|
31
|
+
level: LogLevelConfig;
|
|
32
|
+
callback?: LogCallback | undefined;
|
|
33
|
+
callbackIgnoresLevel?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Callback function for dynamically resolving the default route.
|
|
38
|
+
* Receives a dependency getter function to access router dependencies.
|
|
39
|
+
*/
|
|
40
|
+
export type DefaultRouteCallback<Dependencies = object> = (
|
|
41
|
+
getDependency: <K extends keyof Dependencies>(name: K) => Dependencies[K],
|
|
42
|
+
) => string;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Callback function for dynamically resolving the forward target route.
|
|
46
|
+
* Receives a dependency getter function and current route parameters.
|
|
47
|
+
*/
|
|
48
|
+
export type ForwardToCallback<Dependencies = object> = (
|
|
49
|
+
getDependency: <K extends keyof Dependencies>(name: K) => Dependencies[K],
|
|
50
|
+
params: Params,
|
|
51
|
+
) => string;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Callback function for dynamically resolving the default parameters.
|
|
55
|
+
* Receives a dependency getter function to access router dependencies.
|
|
56
|
+
*/
|
|
57
|
+
export type DefaultParamsCallback<Dependencies = object> = (
|
|
58
|
+
getDependency: <K extends keyof Dependencies>(name: K) => Dependencies[K],
|
|
59
|
+
) => Params;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Router configuration options.
|
|
63
|
+
*
|
|
64
|
+
* Note: For input, use `Partial<Options>` as all fields have defaults.
|
|
65
|
+
* After initialization, `getOptions()` returns resolved `Options` with all fields populated.
|
|
66
|
+
*/
|
|
67
|
+
export interface Options {
|
|
68
|
+
/**
|
|
69
|
+
* Default route to navigate to on start.
|
|
70
|
+
* Empty string means no default route.
|
|
71
|
+
*
|
|
72
|
+
* @default ""
|
|
73
|
+
*/
|
|
74
|
+
defaultRoute: string | DefaultRouteCallback;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Default parameters for the default route.
|
|
78
|
+
*
|
|
79
|
+
* @default {}
|
|
80
|
+
*/
|
|
81
|
+
defaultParams: Params | DefaultParamsCallback;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* How to handle trailing slashes in URLs.
|
|
85
|
+
* - "strict": Route must match exactly
|
|
86
|
+
* - "never": Always remove trailing slash
|
|
87
|
+
* - "always": Always add trailing slash
|
|
88
|
+
* - "preserve": Keep as provided
|
|
89
|
+
*
|
|
90
|
+
* @default "preserve"
|
|
91
|
+
*/
|
|
92
|
+
trailingSlash: "strict" | "never" | "always" | "preserve";
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* How to encode URL parameters.
|
|
96
|
+
* - "default": Standard encoding
|
|
97
|
+
* - "uri": URI encoding (encodeURI)
|
|
98
|
+
* - "uriComponent": Component encoding (encodeURIComponent)
|
|
99
|
+
* - "none": No encoding
|
|
100
|
+
*
|
|
101
|
+
* @default "default"
|
|
102
|
+
*/
|
|
103
|
+
urlParamsEncoding: "default" | "uri" | "uriComponent" | "none";
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* How to handle query parameters.
|
|
107
|
+
*
|
|
108
|
+
* @default "loose"
|
|
109
|
+
*/
|
|
110
|
+
queryParamsMode: QueryParamsMode;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Query parameter parsing options.
|
|
114
|
+
*
|
|
115
|
+
* @default undefined
|
|
116
|
+
*/
|
|
117
|
+
queryParams?: QueryParamsOptions;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Allow matching routes that don't exist.
|
|
121
|
+
* When true, unknown routes navigate without error.
|
|
122
|
+
*
|
|
123
|
+
* @default true
|
|
124
|
+
*/
|
|
125
|
+
allowNotFound: boolean;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Rewrite path on successful match.
|
|
129
|
+
*
|
|
130
|
+
* @default false
|
|
131
|
+
*/
|
|
132
|
+
rewritePathOnMatch: boolean;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Logger configuration.
|
|
136
|
+
*
|
|
137
|
+
* @default undefined
|
|
138
|
+
*/
|
|
139
|
+
logger?: Partial<LoggerConfig>;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Router resource limits configuration.
|
|
143
|
+
* Controls maximum allowed values for various router operations.
|
|
144
|
+
*
|
|
145
|
+
* @default DEFAULT_LIMITS (from LimitsNamespace)
|
|
146
|
+
*/
|
|
147
|
+
limits?: Partial<LimitsConfig>;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Disables argument validation in public router methods.
|
|
151
|
+
* Use in production for performance. Keep false in development for early error detection.
|
|
152
|
+
*
|
|
153
|
+
* @default false
|
|
154
|
+
*/
|
|
155
|
+
noValidate?: boolean;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export type ActivationFn = (
|
|
159
|
+
toState: State,
|
|
160
|
+
fromState: State | undefined,
|
|
161
|
+
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
|
162
|
+
) => boolean | Promise<boolean | State | void> | State | void;
|
|
163
|
+
|
|
164
|
+
export type DefaultDependencies = object;
|
|
165
|
+
|
|
166
|
+
export interface Config {
|
|
167
|
+
decoders: Record<string, (params: Params) => Params>;
|
|
168
|
+
encoders: Record<string, (params: Params) => Params>;
|
|
169
|
+
defaultParams: Record<string, Params>;
|
|
170
|
+
forwardMap: Record<string, string>;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export interface Plugin {
|
|
174
|
+
onStart?: () => void;
|
|
175
|
+
onStop?: () => void;
|
|
176
|
+
onTransitionStart?: (toState: State, fromState?: State) => void;
|
|
177
|
+
onTransitionCancel?: (toState: State, fromState?: State) => void;
|
|
178
|
+
onTransitionError?: (
|
|
179
|
+
toState: State | undefined,
|
|
180
|
+
fromState: State | undefined,
|
|
181
|
+
err: RouterError,
|
|
182
|
+
) => void;
|
|
183
|
+
onTransitionSuccess?: (
|
|
184
|
+
toState: State,
|
|
185
|
+
fromState: State | undefined,
|
|
186
|
+
opts: NavigationOptions,
|
|
187
|
+
) => void;
|
|
188
|
+
teardown?: () => void;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// eslint-disable-next-line sonarjs/redundant-type-aliases
|
|
192
|
+
export type Middleware = ActivationFn;
|
|
193
|
+
|
|
194
|
+
export interface SubscribeState {
|
|
195
|
+
route: State;
|
|
196
|
+
previousRoute?: State | undefined;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export type SubscribeFn = (state: SubscribeState) => void;
|
|
200
|
+
|
|
201
|
+
export interface Listener {
|
|
202
|
+
[key: string]: unknown;
|
|
203
|
+
next: (val: unknown) => void;
|
|
204
|
+
error?: (err: unknown) => void;
|
|
205
|
+
complete?: () => void;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export interface Subscription {
|
|
209
|
+
unsubscribe: Unsubscribe;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Navigator interface - a minimal, safe subset of Router methods.
|
|
214
|
+
*
|
|
215
|
+
* Provides only the essential navigation and state inspection methods.
|
|
216
|
+
* Excludes lifecycle methods (start, stop), plugin management, and internal APIs.
|
|
217
|
+
* Use this when you need to pass a limited router interface to components.
|
|
218
|
+
*
|
|
219
|
+
* For full router access, use the Router interface directly or the useRouter() hook.
|
|
220
|
+
*/
|
|
221
|
+
export interface Navigator {
|
|
222
|
+
navigate: (
|
|
223
|
+
routeName: string,
|
|
224
|
+
routeParams?: Params,
|
|
225
|
+
options?: NavigationOptions,
|
|
226
|
+
) => Promise<State>;
|
|
227
|
+
getState: () => State | undefined;
|
|
228
|
+
isActiveRoute: (
|
|
229
|
+
name: string,
|
|
230
|
+
params?: Params,
|
|
231
|
+
strictEquality?: boolean,
|
|
232
|
+
ignoreQueryParams?: boolean,
|
|
233
|
+
) => boolean;
|
|
234
|
+
canNavigateTo: (name: string, params?: Params) => boolean;
|
|
235
|
+
subscribe: (listener: SubscribeFn) => Unsubscribe;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Router interface - public API for route navigation and lifecycle management.
|
|
240
|
+
*
|
|
241
|
+
* Defines the contract for router implementations. The actual Router class in
|
|
242
|
+
* @real-router/core implements this interface with full functionality.
|
|
243
|
+
*
|
|
244
|
+
* This interface uses `ActivationFn | boolean` for guard types to avoid circular
|
|
245
|
+
* dependencies. The concrete Router class in @real-router/core narrows this to
|
|
246
|
+
* `ActivationFnFactory | boolean` for more precise type checking.
|
|
247
|
+
*/
|
|
248
|
+
export interface Router {
|
|
249
|
+
/**
|
|
250
|
+
* Register an activation guard for a route.
|
|
251
|
+
*
|
|
252
|
+
* @param name - Route name
|
|
253
|
+
* @param guard - Guard function or boolean
|
|
254
|
+
* @returns this for method chaining
|
|
255
|
+
*/
|
|
256
|
+
addActivateGuard: (name: string, guard: ActivationFn | boolean) => this;
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Register a deactivation guard for a route.
|
|
260
|
+
*
|
|
261
|
+
* @param name - Route name
|
|
262
|
+
* @param guard - Guard function or boolean
|
|
263
|
+
* @returns this for method chaining
|
|
264
|
+
*/
|
|
265
|
+
addDeactivateGuard: (name: string, guard: ActivationFn | boolean) => this;
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Remove an activation guard from a route.
|
|
269
|
+
*
|
|
270
|
+
* @param name - Route name
|
|
271
|
+
*/
|
|
272
|
+
removeActivateGuard: (name: string) => void;
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Remove a deactivation guard from a route.
|
|
276
|
+
*
|
|
277
|
+
* @param name - Route name
|
|
278
|
+
*/
|
|
279
|
+
removeDeactivateGuard: (name: string) => void;
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Check if navigation to a route is allowed without performing actual navigation.
|
|
283
|
+
*
|
|
284
|
+
* Synchronously checks all activation and deactivation guards in the transition path.
|
|
285
|
+
* Async guards return false with a console warning.
|
|
286
|
+
*
|
|
287
|
+
* @param name - Route name to check
|
|
288
|
+
* @param params - Route parameters (optional)
|
|
289
|
+
* @returns true if navigation is allowed, false otherwise
|
|
290
|
+
*/
|
|
291
|
+
canNavigateTo: (name: string, params?: Params) => boolean;
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Dispose the router and release all resources.
|
|
295
|
+
*
|
|
296
|
+
* Stops the router if active, calls plugin teardown, clears all event
|
|
297
|
+
* listeners, middleware, routes, and dependencies. After disposal, all
|
|
298
|
+
* mutating methods throw a ROUTER_DISPOSED error. Idempotent — safe to
|
|
299
|
+
* call multiple times.
|
|
300
|
+
*/
|
|
301
|
+
dispose: () => void;
|
|
302
|
+
}
|