@real-router/core 0.55.0 → 0.57.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.
Files changed (145) hide show
  1. package/dist/cjs/Router-BSGzVINO.js +6 -0
  2. package/dist/cjs/Router-BSGzVINO.js.map +1 -0
  3. package/dist/{esm/Router-Dg-zk8AS.d.mts → cjs/Router-hW6ivqrX.d.ts} +2 -2
  4. package/dist/cjs/Router-hW6ivqrX.d.ts.map +1 -0
  5. package/dist/cjs/api.d.ts +2 -2
  6. package/dist/cjs/api.d.ts.map +1 -1
  7. package/dist/cjs/api.js +1 -1
  8. package/dist/cjs/api.js.map +1 -1
  9. package/dist/cjs/{cloneRouter-C9Rth_8U.js → cloneRouter-7z-60z_f.js} +2 -2
  10. package/dist/cjs/{cloneRouter-C9Rth_8U.js.map → cloneRouter-7z-60z_f.js.map} +1 -1
  11. package/dist/cjs/{index-C-i6vx5Y.d.ts → index-BWUmnecT.d.ts} +1 -2
  12. package/dist/cjs/index-BWUmnecT.d.ts.map +1 -0
  13. package/dist/cjs/{RouterError-WhCzIWuc.d.ts → index-CYpAZCoc.d.ts} +19 -2
  14. package/dist/cjs/index-CYpAZCoc.d.ts.map +1 -0
  15. package/dist/cjs/{index-K1U_fqfJ.d.ts → index-D2WRiyWS.d.ts} +2 -2
  16. package/dist/cjs/index-D2WRiyWS.d.ts.map +1 -0
  17. package/dist/cjs/index.d.ts +5 -5
  18. package/dist/cjs/index.js +1 -1
  19. package/dist/cjs/{internals-CWMOL1B8.js → internals-DJjgSePy.js} +2 -2
  20. package/dist/cjs/internals-DJjgSePy.js.map +1 -0
  21. package/dist/cjs/utils.d.ts +1 -1
  22. package/dist/cjs/utils.js +1 -1
  23. package/dist/cjs/utils.js.map +1 -1
  24. package/dist/cjs/validation.d.ts +17 -5
  25. package/dist/cjs/validation.d.ts.map +1 -1
  26. package/dist/cjs/validation.js +1 -1
  27. package/dist/esm/Router-B7txWo9N.mjs +6 -0
  28. package/dist/esm/Router-B7txWo9N.mjs.map +1 -0
  29. package/dist/{cjs/Router-Dg-zk8AS.d.ts → esm/Router-hW6ivqrX.d.mts} +2 -2
  30. package/dist/esm/Router-hW6ivqrX.d.mts.map +1 -0
  31. package/dist/esm/api.d.mts +2 -2
  32. package/dist/esm/api.d.mts.map +1 -1
  33. package/dist/esm/api.mjs +1 -1
  34. package/dist/esm/api.mjs.map +1 -1
  35. package/dist/esm/{cloneRouter-BYNiwchg.mjs → cloneRouter-BNCQ7tIa.mjs} +2 -2
  36. package/dist/esm/{cloneRouter-BYNiwchg.mjs.map → cloneRouter-BNCQ7tIa.mjs.map} +1 -1
  37. package/dist/esm/{index-C-i6vx5Y.d.mts → index-BWUmnecT.d.mts} +1 -2
  38. package/dist/esm/index-BWUmnecT.d.mts.map +1 -0
  39. package/dist/esm/{RouterError-WhCzIWuc.d.mts → index-CYpAZCoc.d.mts} +19 -2
  40. package/dist/esm/index-CYpAZCoc.d.mts.map +1 -0
  41. package/dist/esm/{index-DKzxav48.d.mts → index-CjWKWPY6.d.mts} +2 -2
  42. package/dist/esm/index-CjWKWPY6.d.mts.map +1 -0
  43. package/dist/esm/index.d.mts +5 -5
  44. package/dist/esm/index.mjs +1 -1
  45. package/dist/esm/index.mjs.map +1 -1
  46. package/dist/esm/{internals-DT4mneSz.mjs → internals-C8mRvTxc.mjs} +2 -2
  47. package/dist/esm/internals-C8mRvTxc.mjs.map +1 -0
  48. package/dist/esm/utils.d.mts +1 -1
  49. package/dist/esm/utils.mjs +1 -1
  50. package/dist/esm/utils.mjs.map +1 -1
  51. package/dist/esm/validation.d.mts +17 -5
  52. package/dist/esm/validation.d.mts.map +1 -1
  53. package/dist/esm/validation.mjs +1 -1
  54. package/package.json +3 -4
  55. package/dist/cjs/Router-C7eE1kIK.js +0 -6
  56. package/dist/cjs/Router-C7eE1kIK.js.map +0 -1
  57. package/dist/cjs/Router-Dg-zk8AS.d.ts.map +0 -1
  58. package/dist/cjs/RouterError-WhCzIWuc.d.ts.map +0 -1
  59. package/dist/cjs/index-C-i6vx5Y.d.ts.map +0 -1
  60. package/dist/cjs/index-K1U_fqfJ.d.ts.map +0 -1
  61. package/dist/cjs/internals-CWMOL1B8.js.map +0 -1
  62. package/dist/esm/Router-Dg-zk8AS.d.mts.map +0 -1
  63. package/dist/esm/Router-DiZbYMLx.mjs +0 -6
  64. package/dist/esm/Router-DiZbYMLx.mjs.map +0 -1
  65. package/dist/esm/RouterError-WhCzIWuc.d.mts.map +0 -1
  66. package/dist/esm/index-C-i6vx5Y.d.mts.map +0 -1
  67. package/dist/esm/index-DKzxav48.d.mts.map +0 -1
  68. package/dist/esm/internals-DT4mneSz.mjs.map +0 -1
  69. package/src/Router.ts +0 -725
  70. package/src/RouterError.ts +0 -324
  71. package/src/api/cloneRouter.ts +0 -159
  72. package/src/api/getDependenciesApi.ts +0 -160
  73. package/src/api/getLifecycleApi.ts +0 -65
  74. package/src/api/getPluginApi.ts +0 -228
  75. package/src/api/getRoutesApi.ts +0 -546
  76. package/src/api/helpers.ts +0 -10
  77. package/src/api/index.ts +0 -16
  78. package/src/api/types.ts +0 -12
  79. package/src/constants.ts +0 -101
  80. package/src/createRouter.ts +0 -32
  81. package/src/fsm/index.ts +0 -5
  82. package/src/fsm/routerFSM.ts +0 -130
  83. package/src/getNavigator.ts +0 -30
  84. package/src/guards.ts +0 -46
  85. package/src/helpers.ts +0 -197
  86. package/src/index.ts +0 -50
  87. package/src/internals.ts +0 -200
  88. package/src/namespaces/DependenciesNamespace/dependenciesStore.ts +0 -30
  89. package/src/namespaces/DependenciesNamespace/index.ts +0 -5
  90. package/src/namespaces/EventBusNamespace/EventBusNamespace.ts +0 -485
  91. package/src/namespaces/EventBusNamespace/index.ts +0 -5
  92. package/src/namespaces/EventBusNamespace/types.ts +0 -11
  93. package/src/namespaces/NavigationNamespace/NavigationNamespace.ts +0 -552
  94. package/src/namespaces/NavigationNamespace/constants.ts +0 -55
  95. package/src/namespaces/NavigationNamespace/index.ts +0 -5
  96. package/src/namespaces/NavigationNamespace/transition/completeTransition.ts +0 -108
  97. package/src/namespaces/NavigationNamespace/transition/errorHandling.ts +0 -124
  98. package/src/namespaces/NavigationNamespace/transition/guardPhase.ts +0 -283
  99. package/src/namespaces/NavigationNamespace/types.ts +0 -110
  100. package/src/namespaces/OptionsNamespace/OptionsNamespace.ts +0 -28
  101. package/src/namespaces/OptionsNamespace/constants.ts +0 -19
  102. package/src/namespaces/OptionsNamespace/helpers.ts +0 -50
  103. package/src/namespaces/OptionsNamespace/index.ts +0 -7
  104. package/src/namespaces/OptionsNamespace/validators.ts +0 -13
  105. package/src/namespaces/PluginsNamespace/PluginsNamespace.ts +0 -291
  106. package/src/namespaces/PluginsNamespace/constants.ts +0 -34
  107. package/src/namespaces/PluginsNamespace/index.ts +0 -7
  108. package/src/namespaces/PluginsNamespace/types.ts +0 -22
  109. package/src/namespaces/PluginsNamespace/validators.ts +0 -28
  110. package/src/namespaces/RouteLifecycleNamespace/RouteLifecycleNamespace.ts +0 -558
  111. package/src/namespaces/RouteLifecycleNamespace/index.ts +0 -5
  112. package/src/namespaces/RouteLifecycleNamespace/types.ts +0 -10
  113. package/src/namespaces/RouterLifecycleNamespace/RouterLifecycleNamespace.ts +0 -81
  114. package/src/namespaces/RouterLifecycleNamespace/constants.ts +0 -25
  115. package/src/namespaces/RouterLifecycleNamespace/index.ts +0 -5
  116. package/src/namespaces/RouterLifecycleNamespace/types.ts +0 -30
  117. package/src/namespaces/RoutesNamespace/RoutesNamespace.ts +0 -582
  118. package/src/namespaces/RoutesNamespace/constants.ts +0 -6
  119. package/src/namespaces/RoutesNamespace/forwardChain.ts +0 -34
  120. package/src/namespaces/RoutesNamespace/helpers.ts +0 -204
  121. package/src/namespaces/RoutesNamespace/index.ts +0 -11
  122. package/src/namespaces/RoutesNamespace/routeGuards.ts +0 -62
  123. package/src/namespaces/RoutesNamespace/routesStore.ts +0 -566
  124. package/src/namespaces/RoutesNamespace/types.ts +0 -81
  125. package/src/namespaces/StateNamespace/StateNamespace.ts +0 -224
  126. package/src/namespaces/StateNamespace/helpers.ts +0 -24
  127. package/src/namespaces/StateNamespace/index.ts +0 -5
  128. package/src/namespaces/StateNamespace/types.ts +0 -15
  129. package/src/namespaces/index.ts +0 -35
  130. package/src/stateMetaStore.ts +0 -15
  131. package/src/transitionPath.ts +0 -436
  132. package/src/typeGuards.ts +0 -59
  133. package/src/types/RouterValidator.ts +0 -156
  134. package/src/types.ts +0 -69
  135. package/src/utils/createRequestScope.ts +0 -174
  136. package/src/utils/getStaticPaths.ts +0 -50
  137. package/src/utils/hydrateRouter.ts +0 -89
  138. package/src/utils/index.ts +0 -27
  139. package/src/utils/serializeRouterState.ts +0 -120
  140. package/src/utils/serializeState.ts +0 -63
  141. package/src/validation.ts +0 -12
  142. package/src/wiring/RouterWiringBuilder.ts +0 -275
  143. package/src/wiring/index.ts +0 -7
  144. package/src/wiring/types.ts +0 -47
  145. package/src/wiring/wireRouter.ts +0 -26
@@ -1,108 +0,0 @@
1
- import { errorCodes, constants } from "../../../constants";
2
- import { RouterError } from "../../../RouterError";
3
-
4
- import type { NavigationDependencies, NavigationContext } from "../types";
5
- import type {
6
- NavigationOptions,
7
- State,
8
- TransitionMeta,
9
- } from "@real-router/types";
10
-
11
- type MutableTransitionMeta = {
12
- -readonly [K in keyof TransitionMeta]: TransitionMeta[K];
13
- };
14
-
15
- function buildTransitionMeta(
16
- fromState: State | undefined,
17
- opts: NavigationOptions,
18
- toDeactivate: string[],
19
- toActivate: string[],
20
- intersection: string,
21
- ): TransitionMeta {
22
- Object.freeze(toDeactivate);
23
- Object.freeze(toActivate);
24
-
25
- const segments = Object.freeze({
26
- deactivated: toDeactivate,
27
- activated: toActivate,
28
- intersection,
29
- });
30
-
31
- const meta: MutableTransitionMeta = {
32
- phase: "activating",
33
- reason: "success",
34
- segments,
35
- };
36
-
37
- if (fromState?.name !== undefined) {
38
- meta.from = fromState.name;
39
- }
40
-
41
- if (opts.reload !== undefined) {
42
- meta.reload = opts.reload;
43
- }
44
-
45
- if (opts.replace !== undefined) {
46
- meta.replace = opts.replace;
47
- }
48
-
49
- if (opts.redirected !== undefined) {
50
- meta.redirected = opts.redirected;
51
- }
52
-
53
- return Object.freeze(meta);
54
- }
55
-
56
- function stripSignal({
57
- signal: _,
58
- ...rest
59
- }: NavigationOptions): NavigationOptions {
60
- return rest;
61
- }
62
-
63
- export function completeTransition(
64
- deps: NavigationDependencies,
65
- nav: NavigationContext,
66
- ): State {
67
- const { toState, fromState, opts, toDeactivate, toActivate, intersection } =
68
- nav;
69
-
70
- if (
71
- toState.name !== constants.UNKNOWN_ROUTE &&
72
- !deps.hasRoute(toState.name)
73
- ) {
74
- const err = new RouterError(errorCodes.ROUTE_NOT_FOUND, {
75
- routeName: toState.name,
76
- });
77
-
78
- deps.sendTransitionFail(toState, fromState, err);
79
-
80
- throw err;
81
- }
82
-
83
- if (fromState) {
84
- for (const name of toDeactivate) {
85
- if (!toActivate.includes(name) && nav.canDeactivateFunctions.has(name)) {
86
- deps.clearCanDeactivate(name);
87
- }
88
- }
89
- }
90
-
91
- (toState as { transition: TransitionMeta }).transition = buildTransitionMeta(
92
- fromState,
93
- opts,
94
- toDeactivate,
95
- toActivate,
96
- intersection,
97
- );
98
-
99
- const finalState = Object.freeze(toState);
100
-
101
- deps.setState(finalState);
102
-
103
- const transitionOpts = opts.signal === undefined ? opts : stripSignal(opts);
104
-
105
- deps.sendTransitionDone(finalState, fromState, transitionOpts);
106
-
107
- return finalState;
108
- }
@@ -1,124 +0,0 @@
1
- // packages/core/src/namespaces/NavigationNamespace/transition/errorHandling.ts
2
-
3
- import { errorCodes } from "../../../constants";
4
- import { RouterError } from "../../../RouterError";
5
-
6
- import type { NavigationDependencies } from "../types";
7
- import type { State } from "@real-router/types";
8
-
9
- export function routeTransitionError(
10
- deps: NavigationDependencies,
11
- error: unknown,
12
- toState: State,
13
- fromState: State | undefined,
14
- ): void {
15
- const routerError = error as RouterError;
16
-
17
- if (
18
- routerError.code === errorCodes.TRANSITION_CANCELLED ||
19
- routerError.code === errorCodes.ROUTE_NOT_FOUND
20
- ) {
21
- return;
22
- }
23
-
24
- deps.sendTransitionFail(toState, fromState, routerError);
25
- }
26
-
27
- export function handleGuardError(
28
- error: unknown,
29
- errorCode: string,
30
- segment: string,
31
- ): never {
32
- if (error instanceof DOMException && error.name === "AbortError") {
33
- throw new RouterError(errorCodes.TRANSITION_CANCELLED);
34
- }
35
-
36
- rethrowAsRouterError(error, errorCode, segment);
37
- }
38
-
39
- /**
40
- * Error metadata structure for transition errors.
41
- * Contains information extracted from caught exceptions.
42
- */
43
- export interface SyncErrorMetadata {
44
- [key: string]: unknown;
45
- message?: string;
46
- stack?: string | undefined;
47
- cause?: unknown;
48
- segment?: string;
49
- }
50
-
51
- /**
52
- * Re-throws a caught error as a RouterError with the given error code.
53
- * If the error is already a RouterError, sets the code directly.
54
- * Otherwise wraps it with wrapSyncError metadata.
55
- */
56
- export function rethrowAsRouterError(
57
- error: unknown,
58
- errorCode: string,
59
- segment: string,
60
- ): never {
61
- if (error instanceof RouterError) {
62
- error.setCode(errorCode);
63
-
64
- throw error;
65
- }
66
-
67
- throw new RouterError(errorCode, wrapSyncError(error, segment));
68
- }
69
-
70
- const reservedRouterErrorProps = new Set([
71
- "code",
72
- "segment",
73
- "path",
74
- "redirect",
75
- ]);
76
-
77
- /**
78
- * Wraps a synchronously thrown value into structured error metadata.
79
- *
80
- * This helper extracts useful debugging information from various thrown values:
81
- * - Error instances: extracts message, stack, and cause (ES2022+)
82
- * - Plain objects: spreads properties into metadata
83
- * - Primitives (string, number, etc.): returns minimal metadata
84
- *
85
- * @param thrown - The value caught in a try-catch block
86
- * @param segment - Route segment name (for lifecycle hooks)
87
- * @returns Structured error metadata for RouterError
88
- */
89
- export function wrapSyncError(
90
- thrown: unknown,
91
- segment: string,
92
- ): SyncErrorMetadata {
93
- const base: SyncErrorMetadata = { segment };
94
-
95
- // Handle Error instances - extract all useful properties
96
- if (thrown instanceof Error) {
97
- return {
98
- ...base,
99
- message: thrown.message,
100
- stack: thrown.stack,
101
- // Error.cause requires ES2022+ - safely access if present
102
- ...("cause" in thrown &&
103
- thrown.cause !== undefined && { cause: thrown.cause }),
104
- };
105
- }
106
-
107
- // Handle plain objects - spread properties into metadata, filtering reserved props
108
- if (thrown && typeof thrown === "object") {
109
- const filtered: Record<string, unknown> = {};
110
-
111
- for (const [key, value] of Object.entries(thrown)) {
112
- // Issue #39: Skip reserved properties to avoid RouterError constructor TypeError
113
- if (!reservedRouterErrorProps.has(key)) {
114
- filtered[key] = value;
115
- }
116
- }
117
-
118
- return { ...base, ...filtered };
119
- }
120
-
121
- // Primitives (string, number, boolean, null, undefined, symbol, bigint)
122
- // Return base metadata only - the primitive value isn't useful as metadata
123
- return base;
124
- }
@@ -1,283 +0,0 @@
1
- import { handleGuardError } from "./errorHandling";
2
- import { errorCodes } from "../../../constants";
3
- import { RouterError } from "../../../RouterError";
4
-
5
- import type { GuardFn, State } from "@real-router/types";
6
-
7
- async function resolveAsyncGuard(
8
- promise: Promise<boolean>,
9
- errorCode: string,
10
- segment: string,
11
- ): Promise<void> {
12
- let result: boolean;
13
-
14
- try {
15
- result = await promise;
16
- } catch (error: unknown) {
17
- handleGuardError(error, errorCode, segment);
18
-
19
- return; // unreachable — handleGuardError returns never
20
- }
21
-
22
- if (!result) {
23
- throw new RouterError(errorCode, { segment });
24
- }
25
- }
26
-
27
- async function resolveRemainingGuards( // NOSONAR -- params kept flat to avoid object allocation on hot path
28
- guards: Map<string, GuardFn>,
29
- segments: string[],
30
- errorCode: string,
31
- toState: State,
32
- fromState: State | undefined,
33
- signal: AbortSignal | undefined,
34
- isActive: () => boolean,
35
- startIndex: number,
36
- firstResult: Promise<boolean>,
37
- firstSegment: string,
38
- ): Promise<void> {
39
- await resolveAsyncGuard(firstResult, errorCode, firstSegment);
40
-
41
- for (let i = startIndex; i < segments.length; i++) {
42
- if (!isActive()) {
43
- throw new RouterError(errorCodes.TRANSITION_CANCELLED);
44
- }
45
-
46
- const segment = segments[i];
47
- const guardFn = guards.get(segment);
48
-
49
- if (!guardFn) {
50
- continue;
51
- }
52
-
53
- let guardResult: boolean | Promise<boolean> = false;
54
-
55
- try {
56
- guardResult = guardFn(toState, fromState, signal);
57
- } catch (error: unknown) {
58
- handleGuardError(error, errorCode, segment);
59
- }
60
-
61
- if (guardResult instanceof Promise) {
62
- await resolveAsyncGuard(guardResult, errorCode, segment);
63
- continue;
64
- }
65
-
66
- if (!guardResult) {
67
- throw new RouterError(errorCode, { segment });
68
- }
69
- }
70
- }
71
-
72
- async function finishAsyncPipeline( // NOSONAR
73
- deactivateCompletion: Promise<void>,
74
- activateGuards: Map<string, GuardFn>,
75
- toActivate: string[],
76
- shouldActivate: boolean,
77
- toState: State,
78
- fromState: State | undefined,
79
- signal: AbortSignal,
80
- isActive: () => boolean,
81
- emitLeaveApprove: () => Promise<void> | undefined,
82
- ): Promise<void> {
83
- await deactivateCompletion;
84
-
85
- if (!isActive()) {
86
- throw new RouterError(errorCodes.TRANSITION_CANCELLED);
87
- }
88
-
89
- const leaveResult = emitLeaveApprove();
90
-
91
- if (leaveResult !== undefined) {
92
- await leaveResult;
93
-
94
- /* v8 ignore next 3 -- @preserve: V8 cannot track cancellation check through async leave continuation after Promise.allSettled */
95
- if (!isActive()) {
96
- throw new RouterError(errorCodes.TRANSITION_CANCELLED);
97
- }
98
- }
99
-
100
- if (shouldActivate) {
101
- const pending = runGuards(
102
- activateGuards,
103
- toActivate,
104
- errorCodes.CANNOT_ACTIVATE,
105
- toState,
106
- fromState,
107
- signal,
108
- isActive,
109
- );
110
-
111
- if (pending !== undefined) {
112
- await pending;
113
- }
114
-
115
- if (!isActive()) {
116
- throw new RouterError(errorCodes.TRANSITION_CANCELLED);
117
- }
118
- }
119
- }
120
-
121
- export function executeGuardPipeline( // NOSONAR
122
- deactivateGuards: Map<string, GuardFn>,
123
- activateGuards: Map<string, GuardFn>,
124
- toDeactivate: string[],
125
- toActivate: string[],
126
- shouldDeactivate: boolean,
127
- shouldActivate: boolean,
128
- toState: State,
129
- fromState: State | undefined,
130
- signal: AbortSignal,
131
- isActive: () => boolean,
132
- emitLeaveApprove: () => Promise<void> | undefined,
133
- ): Promise<void> | undefined {
134
- if (shouldDeactivate) {
135
- const pending = runGuards(
136
- deactivateGuards,
137
- toDeactivate,
138
- errorCodes.CANNOT_DEACTIVATE,
139
- toState,
140
- fromState,
141
- signal,
142
- isActive,
143
- );
144
-
145
- if (pending !== undefined) {
146
- return finishAsyncPipeline(
147
- pending,
148
- activateGuards,
149
- toActivate,
150
- shouldActivate,
151
- toState,
152
- fromState,
153
- signal,
154
- isActive,
155
- emitLeaveApprove,
156
- );
157
- }
158
- }
159
-
160
- if (!isActive()) {
161
- throw new RouterError(errorCodes.TRANSITION_CANCELLED);
162
- }
163
-
164
- const leaveResult = emitLeaveApprove();
165
-
166
- if (leaveResult !== undefined) {
167
- return finishAfterAsyncLeave(
168
- leaveResult,
169
- /* v8 ignore next -- @preserve: false-branch unreachable — navigateToNotFound bypasses guards pipeline */
170
- shouldActivate ? activateGuards : undefined,
171
- toActivate,
172
- toState,
173
- fromState,
174
- signal,
175
- isActive,
176
- );
177
- }
178
-
179
- if (shouldActivate) {
180
- return runGuards(
181
- activateGuards,
182
- toActivate,
183
- errorCodes.CANNOT_ACTIVATE,
184
- toState,
185
- fromState,
186
- signal,
187
- isActive,
188
- );
189
- }
190
-
191
- return undefined;
192
- }
193
-
194
- async function finishAfterAsyncLeave(
195
- leaveCompletion: Promise<void>,
196
- activateGuards: Map<string, GuardFn> | undefined,
197
- toActivate: string[],
198
- toState: State,
199
- fromState: State | undefined,
200
- signal: AbortSignal,
201
- isActive: () => boolean,
202
- ): Promise<void> {
203
- await leaveCompletion;
204
-
205
- /* v8 ignore next 3 -- @preserve: unreachable after #663 — signal abort
206
- mid-leave rejects via settleLeavePromises, so `await leaveCompletion`
207
- throws directly instead of completing with a stale isActive() */
208
- if (!isActive()) {
209
- throw new RouterError(errorCodes.TRANSITION_CANCELLED);
210
- }
211
-
212
- /* v8 ignore next -- @preserve: false-branch unreachable — navigateToNotFound bypasses guards pipeline */
213
- if (activateGuards !== undefined) {
214
- const pending = runGuards(
215
- activateGuards,
216
- toActivate,
217
- errorCodes.CANNOT_ACTIVATE,
218
- toState,
219
- fromState,
220
- signal,
221
- isActive,
222
- );
223
-
224
- if (pending !== undefined) {
225
- await pending;
226
- }
227
-
228
- if (!isActive()) {
229
- throw new RouterError(errorCodes.TRANSITION_CANCELLED);
230
- }
231
- }
232
- }
233
-
234
- function runGuards(
235
- guards: Map<string, GuardFn>,
236
- segments: string[],
237
- errorCode: string,
238
- toState: State,
239
- fromState: State | undefined,
240
- signal: AbortSignal | undefined,
241
- isActive: () => boolean,
242
- ): Promise<void> | undefined {
243
- for (const [i, segment] of segments.entries()) {
244
- if (!isActive()) {
245
- throw new RouterError(errorCodes.TRANSITION_CANCELLED);
246
- }
247
-
248
- const guardFn = guards.get(segment);
249
-
250
- if (!guardFn) {
251
- continue;
252
- }
253
-
254
- let guardResult: boolean | Promise<boolean> = false;
255
-
256
- try {
257
- guardResult = guardFn(toState, fromState, signal);
258
- } catch (error: unknown) {
259
- handleGuardError(error, errorCode, segment);
260
- }
261
-
262
- if (guardResult instanceof Promise) {
263
- return resolveRemainingGuards(
264
- guards,
265
- segments,
266
- errorCode,
267
- toState,
268
- fromState,
269
- signal,
270
- isActive,
271
- i + 1,
272
- guardResult,
273
- segment,
274
- );
275
- }
276
-
277
- if (!guardResult) {
278
- throw new RouterError(errorCode, { segment });
279
- }
280
- }
281
-
282
- return undefined;
283
- }
@@ -1,110 +0,0 @@
1
- // packages/core/src/namespaces/NavigationNamespace/types.ts
2
-
3
- import type {
4
- GuardFn,
5
- NavigationOptions,
6
- Options,
7
- Params,
8
- State,
9
- } from "@real-router/types";
10
-
11
- export interface NavigationContext {
12
- toState: State;
13
- fromState: State | undefined;
14
- opts: NavigationOptions;
15
- toDeactivate: string[];
16
- toActivate: string[];
17
- intersection: string;
18
- canDeactivateFunctions: Map<string, GuardFn>;
19
- }
20
-
21
- /**
22
- * Dependencies injected into NavigationNamespace.
23
- *
24
- * These are function references from other namespaces/facade,
25
- * avoiding the need to pass the entire Router object.
26
- */
27
- export interface NavigationDependencies {
28
- /** Get router options */
29
- getOptions: () => Options;
30
-
31
- /** Check if route exists */
32
- hasRoute: (name: string) => boolean;
33
-
34
- /** Get current state */
35
- getState: () => State | undefined;
36
-
37
- /** Set router state */
38
- setState: (state: State) => void;
39
-
40
- /** Build complete navigate state: forwardState + route check + buildPath + makeState in one step */
41
- buildNavigateState: (
42
- routeName: string,
43
- routeParams: Params,
44
- ) => State | undefined;
45
-
46
- /** Resolve defaultRoute and defaultParams options (static value or callback) */
47
- resolveDefault: () => { route: string; params: Params };
48
-
49
- /** Start transition and send NAVIGATE event to routerFSM */
50
- startTransition: (toState: State, fromState: State | undefined) => void;
51
-
52
- /** Cancel navigation if transition is running */
53
- cancelNavigation: () => void;
54
-
55
- /** Send COMPLETE event to routerFSM */
56
- sendTransitionDone: (
57
- state: State,
58
- fromState: State | undefined,
59
- opts: NavigationOptions,
60
- ) => void;
61
-
62
- /** Send FAIL event to routerFSM */
63
- sendTransitionFail: (
64
- toState: State,
65
- fromState: State | undefined,
66
- error: unknown,
67
- ) => void;
68
-
69
- /** Emit TRANSITION_ERROR event to listeners */
70
- emitTransitionError: (
71
- toState: State | undefined,
72
- fromState: State | undefined,
73
- error: unknown,
74
- ) => void;
75
-
76
- /** Emit TRANSITION_SUCCESS event to listeners (without FSM transition) */
77
- emitTransitionSuccess: (
78
- toState: State,
79
- fromState?: State,
80
- opts?: NavigationOptions,
81
- ) => void;
82
-
83
- /** Send LEAVE_APPROVE event to routerFSM and emit to listeners */
84
- sendLeaveApprove: (toState: State, fromState: State | undefined) => void;
85
-
86
- /** Check if navigation can begin (router is started) */
87
- canNavigate: () => boolean;
88
-
89
- /** Get lifecycle functions (canDeactivate, canActivate maps) */
90
- getLifecycleFunctions: () => [Map<string, GuardFn>, Map<string, GuardFn>];
91
-
92
- /** Check if router is active (for cancellation check on stop()) */
93
- isActive: () => boolean;
94
-
95
- /** Check if a transition is currently in progress */
96
- isTransitioning: () => boolean;
97
-
98
- /** Clear canDeactivate guard for a route */
99
- clearCanDeactivate: (name: string) => void;
100
-
101
- /** Check if any leave listeners are registered */
102
- hasLeaveListeners: () => boolean;
103
-
104
- /** Call all leave listeners — returns Promise if any are async, undefined otherwise */
105
- awaitLeaveListeners: (
106
- toState: State,
107
- fromState: State | undefined,
108
- signal: AbortSignal,
109
- ) => Promise<void> | undefined;
110
- }
@@ -1,28 +0,0 @@
1
- // packages/core/src/namespaces/OptionsNamespace/OptionsNamespace.ts
2
-
3
- import { defaultOptions } from "./constants";
4
- import { deepFreeze } from "./helpers";
5
- import { validateOptionsIsObject } from "./validators";
6
-
7
- import type { Options } from "@real-router/types";
8
-
9
- export class OptionsNamespace {
10
- readonly #options: Readonly<Options>;
11
-
12
- constructor(initialOptions: Partial<Options> = {}) {
13
- this.#options = deepFreeze({
14
- ...defaultOptions,
15
- ...initialOptions,
16
- });
17
- }
18
-
19
- static validateOptionsIsObject(
20
- options: unknown,
21
- ): asserts options is Record<string, unknown> {
22
- validateOptionsIsObject(options);
23
- }
24
-
25
- get(): Readonly<Options> {
26
- return this.#options;
27
- }
28
- }
@@ -1,19 +0,0 @@
1
- // packages/core/src/namespaces/OptionsNamespace/constants.ts
2
-
3
- import { DEFAULT_QUERY_PARAMS } from "route-tree";
4
-
5
- import type { Options } from "@real-router/types";
6
-
7
- /**
8
- * Default options for the router.
9
- */
10
- export const defaultOptions: Options = {
11
- defaultRoute: "",
12
- defaultParams: {},
13
- trailingSlash: "preserve",
14
- queryParamsMode: "loose",
15
- queryParams: DEFAULT_QUERY_PARAMS,
16
- urlParamsEncoding: "default",
17
- allowNotFound: true,
18
- rewritePathOnMatch: true,
19
- } satisfies Options;