@real-router/core 0.22.0 → 0.23.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 (80) hide show
  1. package/README.md +1 -3
  2. package/dist/cjs/index.d.ts +1 -1
  3. package/dist/cjs/index.js +1 -1
  4. package/dist/cjs/index.js.map +1 -1
  5. package/dist/cjs/metafile-cjs.json +1 -1
  6. package/dist/esm/index.d.mts +1 -1
  7. package/dist/esm/index.mjs +1 -1
  8. package/dist/esm/index.mjs.map +1 -1
  9. package/dist/esm/metafile-esm.json +1 -1
  10. package/package.json +7 -5
  11. package/src/Router.ts +1174 -0
  12. package/src/RouterError.ts +324 -0
  13. package/src/constants.ts +112 -0
  14. package/src/createRouter.ts +32 -0
  15. package/src/fsm/index.ts +5 -0
  16. package/src/fsm/routerFSM.ts +129 -0
  17. package/src/getNavigator.ts +15 -0
  18. package/src/helpers.ts +194 -0
  19. package/src/index.ts +46 -0
  20. package/src/namespaces/CloneNamespace/CloneNamespace.ts +120 -0
  21. package/src/namespaces/CloneNamespace/index.ts +3 -0
  22. package/src/namespaces/CloneNamespace/types.ts +46 -0
  23. package/src/namespaces/DependenciesNamespace/DependenciesNamespace.ts +250 -0
  24. package/src/namespaces/DependenciesNamespace/index.ts +3 -0
  25. package/src/namespaces/DependenciesNamespace/validators.ts +105 -0
  26. package/src/namespaces/EventBusNamespace/EventBusNamespace.ts +272 -0
  27. package/src/namespaces/EventBusNamespace/index.ts +5 -0
  28. package/src/namespaces/EventBusNamespace/types.ts +11 -0
  29. package/src/namespaces/MiddlewareNamespace/MiddlewareNamespace.ts +206 -0
  30. package/src/namespaces/MiddlewareNamespace/index.ts +5 -0
  31. package/src/namespaces/MiddlewareNamespace/types.ts +28 -0
  32. package/src/namespaces/MiddlewareNamespace/validators.ts +96 -0
  33. package/src/namespaces/NavigationNamespace/NavigationNamespace.ts +308 -0
  34. package/src/namespaces/NavigationNamespace/index.ts +5 -0
  35. package/src/namespaces/NavigationNamespace/transition/executeLifecycleHooks.ts +84 -0
  36. package/src/namespaces/NavigationNamespace/transition/executeMiddleware.ts +56 -0
  37. package/src/namespaces/NavigationNamespace/transition/index.ts +107 -0
  38. package/src/namespaces/NavigationNamespace/transition/makeError.ts +37 -0
  39. package/src/namespaces/NavigationNamespace/transition/mergeStates.ts +54 -0
  40. package/src/namespaces/NavigationNamespace/transition/processLifecycleResult.ts +81 -0
  41. package/src/namespaces/NavigationNamespace/transition/wrapSyncError.ts +82 -0
  42. package/src/namespaces/NavigationNamespace/types.ts +129 -0
  43. package/src/namespaces/NavigationNamespace/validators.ts +87 -0
  44. package/src/namespaces/OptionsNamespace/OptionsNamespace.ts +50 -0
  45. package/src/namespaces/OptionsNamespace/constants.ts +41 -0
  46. package/src/namespaces/OptionsNamespace/helpers.ts +51 -0
  47. package/src/namespaces/OptionsNamespace/index.ts +11 -0
  48. package/src/namespaces/OptionsNamespace/validators.ts +252 -0
  49. package/src/namespaces/PluginsNamespace/PluginsNamespace.ts +325 -0
  50. package/src/namespaces/PluginsNamespace/constants.ts +35 -0
  51. package/src/namespaces/PluginsNamespace/index.ts +7 -0
  52. package/src/namespaces/PluginsNamespace/types.ts +32 -0
  53. package/src/namespaces/PluginsNamespace/validators.ts +79 -0
  54. package/src/namespaces/RouteLifecycleNamespace/RouteLifecycleNamespace.ts +389 -0
  55. package/src/namespaces/RouteLifecycleNamespace/index.ts +5 -0
  56. package/src/namespaces/RouteLifecycleNamespace/types.ts +17 -0
  57. package/src/namespaces/RouteLifecycleNamespace/validators.ts +65 -0
  58. package/src/namespaces/RouterLifecycleNamespace/RouterLifecycleNamespace.ts +140 -0
  59. package/src/namespaces/RouterLifecycleNamespace/constants.ts +25 -0
  60. package/src/namespaces/RouterLifecycleNamespace/index.ts +5 -0
  61. package/src/namespaces/RouterLifecycleNamespace/types.ts +23 -0
  62. package/src/namespaces/RoutesNamespace/RoutesNamespace.ts +1482 -0
  63. package/src/namespaces/RoutesNamespace/constants.ts +14 -0
  64. package/src/namespaces/RoutesNamespace/helpers.ts +532 -0
  65. package/src/namespaces/RoutesNamespace/index.ts +9 -0
  66. package/src/namespaces/RoutesNamespace/stateBuilder.ts +70 -0
  67. package/src/namespaces/RoutesNamespace/types.ts +82 -0
  68. package/src/namespaces/RoutesNamespace/validators.ts +331 -0
  69. package/src/namespaces/StateNamespace/StateNamespace.ts +317 -0
  70. package/src/namespaces/StateNamespace/helpers.ts +43 -0
  71. package/src/namespaces/StateNamespace/index.ts +5 -0
  72. package/src/namespaces/StateNamespace/types.ts +15 -0
  73. package/src/namespaces/index.ts +42 -0
  74. package/src/transitionPath.ts +441 -0
  75. package/src/typeGuards.ts +74 -0
  76. package/src/types.ts +194 -0
  77. package/src/wiring/RouterWiringBuilder.ts +235 -0
  78. package/src/wiring/index.ts +7 -0
  79. package/src/wiring/types.ts +53 -0
  80. package/src/wiring/wireRouter.ts +29 -0
package/src/types.ts ADDED
@@ -0,0 +1,194 @@
1
+ // packages/core/src/types.ts
2
+
3
+ /**
4
+ * Router-dependent types.
5
+ *
6
+ * These types reference the Router class and are therefore defined in core
7
+ * rather than core-types to avoid circular dependencies.
8
+ */
9
+
10
+ import type { events, plugins } from "./constants";
11
+ import type { Router } from "./Router";
12
+ import type {
13
+ ActivationFn,
14
+ DefaultDependencies,
15
+ EventsKeys,
16
+ ForwardToCallback,
17
+ LimitsConfig,
18
+ Middleware,
19
+ NavigationOptions,
20
+ Params,
21
+ Plugin,
22
+ RouterError as RouterErrorType,
23
+ RouteTreeState,
24
+ State,
25
+ } from "@real-router/types";
26
+
27
+ export type EventMethodMap = {
28
+ [K in EventsKeys as (typeof events)[K]]: (typeof plugins)[K];
29
+ };
30
+
31
+ /**
32
+ * Event argument tuples for the router's 6 events.
33
+ *
34
+ * Uses explicit `| undefined` unions (not optional `?`) to satisfy
35
+ * `exactOptionalPropertyTypes` when passing undefined args from FSM payloads.
36
+ */
37
+ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions -- must be `type` for Record<string, unknown[]> constraint
38
+ export type RouterEventMap = {
39
+ $start: [];
40
+ $stop: [];
41
+ $$start: [toState: State, fromState: State | undefined];
42
+ $$success: [
43
+ toState: State,
44
+ fromState: State | undefined,
45
+ opts: NavigationOptions | undefined,
46
+ ];
47
+ $$error: [
48
+ toState: State | undefined,
49
+ fromState: State | undefined,
50
+ error: RouterErrorType | undefined,
51
+ ];
52
+ $$cancel: [toState: State, fromState: State | undefined];
53
+ };
54
+
55
+ /**
56
+ * Immutable limits configuration type.
57
+ */
58
+ export type Limits = Readonly<LimitsConfig>;
59
+
60
+ /**
61
+ * Extended build result that includes segments for path building.
62
+ * Used internally to avoid duplicate getSegmentsByName calls.
63
+ *
64
+ * @param segments - Route segments from getSegmentsByName (typed as unknown[] for cross-package compatibility)
65
+ * @internal
66
+ */
67
+ export interface BuildStateResultWithSegments<P extends Params = Params> {
68
+ readonly state: RouteTreeState<P>;
69
+ readonly segments: readonly unknown[];
70
+ }
71
+
72
+ /**
73
+ * Route configuration.
74
+ */
75
+ export interface Route<
76
+ Dependencies extends DefaultDependencies = DefaultDependencies,
77
+ > {
78
+ [key: string]: unknown;
79
+ /** Route name (dot-separated for nested routes). */
80
+ name: string;
81
+ /** URL path pattern for this route. */
82
+ path: string;
83
+ /** Factory function that returns a guard for route activation. */
84
+ canActivate?: ActivationFnFactory<Dependencies>;
85
+ /** Factory function that returns a guard for route deactivation. */
86
+ canDeactivate?: ActivationFnFactory<Dependencies>;
87
+ /**
88
+ * Redirects navigation to another route.
89
+ *
90
+ * IMPORTANT: forwardTo creates a URL alias, not a transition chain.
91
+ * Guards (canActivate) on the source route are NOT executed.
92
+ * Only guards on the final destination are executed.
93
+ *
94
+ * This matches Vue Router and Angular Router behavior.
95
+ *
96
+ * @example
97
+ * // Correct: guard on target
98
+ * { name: "old", path: "/old", forwardTo: "new" }
99
+ * { name: "new", path: "/new", canActivate: myGuard }
100
+ *
101
+ * // Wrong: guard on source (will be ignored with warning)
102
+ * { name: "old", path: "/old", forwardTo: "new", canActivate: myGuard }
103
+ */
104
+ forwardTo?: string | ForwardToCallback<Dependencies>;
105
+ /** Nested child routes. */
106
+ children?: Route<Dependencies>[];
107
+ /** Encodes state params to URL params. */
108
+ encodeParams?: (stateParams: Params) => Params;
109
+ /** Decodes URL params to state params. */
110
+ decodeParams?: (pathParams: Params) => Params;
111
+ /**
112
+ * Default parameters for this route.
113
+ *
114
+ * @remarks
115
+ * **Type Contract:**
116
+ * The type of defaultParams MUST match the expected params type P
117
+ * when using `router.makeState<P>()` or `router.navigate<P>()`.
118
+ *
119
+ * These values are merged into state.params when creating route states.
120
+ * Missing URL params are filled from defaultParams.
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * // Define route with pagination defaults
125
+ * {
126
+ * name: "users",
127
+ * path: "/users",
128
+ * defaultParams: { page: 1, limit: 10 }
129
+ * }
130
+ *
131
+ * // Navigate without specifying page/limit
132
+ * router.navigate("users", { filter: "active" });
133
+ * // Result: state.params = { page: 1, limit: 10, filter: "active" }
134
+ *
135
+ * // Correct typing — include defaultParams properties
136
+ * type UsersParams = { page: number; limit: number; filter?: string };
137
+ * ```
138
+ */
139
+ defaultParams?: Params;
140
+ }
141
+
142
+ /**
143
+ * Configuration update options for updateRoute().
144
+ * All properties are optional. Set to null to remove the configuration.
145
+ */
146
+ export interface RouteConfigUpdate<
147
+ Dependencies extends DefaultDependencies = DefaultDependencies,
148
+ > {
149
+ /** Set to null to remove forwardTo */
150
+ forwardTo?: string | ForwardToCallback<Dependencies> | null;
151
+ /** Set to null to remove defaultParams */
152
+ defaultParams?: Params | null;
153
+ /** Set to null to remove decoder */
154
+ decodeParams?: ((params: Params) => Params) | null;
155
+ /** Set to null to remove encoder */
156
+ encodeParams?: ((params: Params) => Params) | null;
157
+ /** Set to null to remove canActivate */
158
+ canActivate?: ActivationFnFactory<Dependencies> | null;
159
+ /** Set to null to remove canDeactivate */
160
+ canDeactivate?: ActivationFnFactory<Dependencies> | null;
161
+ }
162
+
163
+ /**
164
+ * Factory function for creating activation guards.
165
+ * Receives the router instance and a dependency getter.
166
+ */
167
+ export type ActivationFnFactory<
168
+ Dependencies extends DefaultDependencies = DefaultDependencies,
169
+ > = (
170
+ router: Router<Dependencies>,
171
+ getDependency: <K extends keyof Dependencies>(key: K) => Dependencies[K],
172
+ ) => ActivationFn;
173
+
174
+ /**
175
+ * Factory function for creating middleware.
176
+ * Receives the router instance and a dependency getter.
177
+ */
178
+ export type MiddlewareFactory<
179
+ Dependencies extends DefaultDependencies = DefaultDependencies,
180
+ > = (
181
+ router: Router<Dependencies>,
182
+ getDependency: <K extends keyof Dependencies>(key: K) => Dependencies[K],
183
+ ) => Middleware;
184
+
185
+ /**
186
+ * Factory function for creating plugins.
187
+ * Receives the router instance and a dependency getter.
188
+ */
189
+ export type PluginFactory<
190
+ Dependencies extends DefaultDependencies = DefaultDependencies,
191
+ > = (
192
+ router: Router<Dependencies>,
193
+ getDependency: <K extends keyof Dependencies>(key: K) => Dependencies[K],
194
+ ) => Plugin;
@@ -0,0 +1,235 @@
1
+ // packages/core/src/wiring/RouterWiringBuilder.ts
2
+
3
+ import type { EventBusNamespace } from "../namespaces";
4
+ import type { WiringOptions } from "./types";
5
+ import type { MiddlewareDependencies } from "../namespaces/MiddlewareNamespace";
6
+ import type {
7
+ NavigationDependencies,
8
+ TransitionDependencies,
9
+ } from "../namespaces/NavigationNamespace";
10
+ import type { PluginsDependencies } from "../namespaces/PluginsNamespace";
11
+ import type { RouteLifecycleDependencies } from "../namespaces/RouteLifecycleNamespace";
12
+ import type { RouterLifecycleDependencies } from "../namespaces/RouterLifecycleNamespace";
13
+ import type { RoutesDependencies } from "../namespaces/RoutesNamespace";
14
+ import type { DefaultDependencies } from "@real-router/types";
15
+
16
+ export class RouterWiringBuilder<
17
+ Dependencies extends DefaultDependencies = DefaultDependencies,
18
+ > {
19
+ private readonly router: WiringOptions<Dependencies>["router"];
20
+ private readonly options: WiringOptions<Dependencies>["options"];
21
+ private readonly limits: WiringOptions<Dependencies>["limits"];
22
+ private readonly dependencies: WiringOptions<Dependencies>["dependencies"];
23
+ private readonly state: WiringOptions<Dependencies>["state"];
24
+ private readonly routes: WiringOptions<Dependencies>["routes"];
25
+ private readonly routeLifecycle: WiringOptions<Dependencies>["routeLifecycle"];
26
+ private readonly middleware: WiringOptions<Dependencies>["middleware"];
27
+ private readonly plugins: WiringOptions<Dependencies>["plugins"];
28
+ private readonly navigation: WiringOptions<Dependencies>["navigation"];
29
+ private readonly lifecycle: WiringOptions<Dependencies>["lifecycle"];
30
+ private readonly clone: WiringOptions<Dependencies>["clone"];
31
+ private readonly eventBus: EventBusNamespace;
32
+
33
+ constructor(wiringOptions: WiringOptions<Dependencies>) {
34
+ this.router = wiringOptions.router;
35
+ this.options = wiringOptions.options;
36
+ this.limits = wiringOptions.limits;
37
+ this.dependencies = wiringOptions.dependencies;
38
+ this.state = wiringOptions.state;
39
+ this.routes = wiringOptions.routes;
40
+ this.routeLifecycle = wiringOptions.routeLifecycle;
41
+ this.middleware = wiringOptions.middleware;
42
+ this.plugins = wiringOptions.plugins;
43
+ this.navigation = wiringOptions.navigation;
44
+ this.lifecycle = wiringOptions.lifecycle;
45
+ this.clone = wiringOptions.clone;
46
+ this.eventBus = wiringOptions.eventBus;
47
+ }
48
+
49
+ wireLimits(): void {
50
+ this.dependencies.setLimits(this.limits);
51
+ this.plugins.setLimits(this.limits);
52
+ this.middleware.setLimits(this.limits);
53
+ this.eventBus.setLimits({
54
+ maxListeners: this.limits.maxListeners,
55
+ warnListeners: this.limits.warnListeners,
56
+ maxEventDepth: this.limits.maxEventDepth,
57
+ });
58
+ this.routeLifecycle.setLimits(this.limits);
59
+ }
60
+
61
+ wireRouteLifecycleDeps(): void {
62
+ this.routeLifecycle.setRouter(this.router);
63
+
64
+ const routeLifecycleDeps: RouteLifecycleDependencies<Dependencies> = {
65
+ getDependency: <K extends keyof Dependencies>(dependencyName: K) =>
66
+ this.dependencies.get(dependencyName),
67
+ };
68
+
69
+ this.routeLifecycle.setDependencies(routeLifecycleDeps);
70
+ }
71
+
72
+ wireRoutesDeps(): void {
73
+ const routesDeps: RoutesDependencies<Dependencies> = {
74
+ addActivateGuard: (name, handler) => {
75
+ this.router.addActivateGuard(name, handler);
76
+ },
77
+ addDeactivateGuard: (name, handler) => {
78
+ this.router.addDeactivateGuard(name, handler);
79
+ },
80
+ makeState: (name, params, path, meta) =>
81
+ this.state.makeState(name, params, path, meta),
82
+ getState: () => this.state.get(),
83
+ areStatesEqual: (state1, state2, ignoreQueryParams) =>
84
+ this.state.areStatesEqual(state1, state2, ignoreQueryParams),
85
+ getDependency: (name) => this.dependencies.get(name),
86
+ forwardState: (name, params) => this.router.forwardState(name, params),
87
+ };
88
+
89
+ this.routes.setDependencies(routesDeps);
90
+ this.routes.setLifecycleNamespace(this.routeLifecycle);
91
+ }
92
+
93
+ wireMiddlewareDeps(): void {
94
+ this.middleware.setRouter(this.router);
95
+
96
+ const middlewareDeps: MiddlewareDependencies<Dependencies> = {
97
+ getDependency: <K extends keyof Dependencies>(dependencyName: K) =>
98
+ this.dependencies.get(dependencyName),
99
+ };
100
+
101
+ this.middleware.setDependencies(middlewareDeps);
102
+ }
103
+
104
+ wirePluginsDeps(): void {
105
+ this.plugins.setRouter(this.router);
106
+
107
+ const pluginsDeps: PluginsDependencies<Dependencies> = {
108
+ addEventListener: (eventName, cb) =>
109
+ this.eventBus.addEventListener(eventName, cb),
110
+ canNavigate: () => this.eventBus.canBeginTransition(),
111
+ getDependency: <K extends keyof Dependencies>(dependencyName: K) =>
112
+ this.dependencies.get(dependencyName),
113
+ };
114
+
115
+ this.plugins.setDependencies(pluginsDeps);
116
+ }
117
+
118
+ wireNavigationDeps(): void {
119
+ const navigationDeps: NavigationDependencies = {
120
+ getOptions: () => this.options.get(),
121
+ hasRoute: (name) => this.routes.hasRoute(name),
122
+ getState: () => this.state.get(),
123
+ setState: (state) => {
124
+ this.state.set(state);
125
+ },
126
+ buildStateWithSegments: (routeName, routeParams) => {
127
+ const { name, params } = this.router.forwardState(
128
+ routeName,
129
+ routeParams,
130
+ );
131
+
132
+ return this.routes.buildStateWithSegmentsResolved(name, params);
133
+ },
134
+ makeState: (name, params, path, meta) =>
135
+ this.state.makeState(name, params, path, meta),
136
+ buildPath: (route, params) =>
137
+ this.routes.buildPath(route, params, this.options.get()),
138
+ areStatesEqual: (state1, state2, ignoreQueryParams) =>
139
+ this.state.areStatesEqual(state1, state2, ignoreQueryParams),
140
+ getDependency: (name: string) =>
141
+ this.dependencies.get(name as keyof Dependencies),
142
+ startTransition: (toState, fromState) => {
143
+ this.eventBus.beginTransition(toState, fromState);
144
+ },
145
+ cancelNavigation: () => {
146
+ this.eventBus.cancelTransition(
147
+ this.eventBus.getCurrentToState()!, // eslint-disable-line @typescript-eslint/no-non-null-assertion -- guaranteed set before TRANSITIONING
148
+ this.state.get(),
149
+ );
150
+ },
151
+ sendTransitionDone: (state, fromState, opts) => {
152
+ this.eventBus.completeTransition(state, fromState, opts);
153
+ },
154
+ sendTransitionBlocked: (toState, fromState, error) => {
155
+ this.eventBus.failTransition(toState, fromState, error);
156
+ },
157
+ sendTransitionError: (toState, fromState, error) => {
158
+ this.eventBus.failTransition(toState, fromState, error);
159
+ },
160
+ emitTransitionError: (toState, fromState, error) => {
161
+ this.eventBus.emitOrFailTransitionError(toState, fromState, error);
162
+ },
163
+ };
164
+
165
+ this.navigation.setDependencies(navigationDeps);
166
+
167
+ const transitionDeps: TransitionDependencies = {
168
+ getLifecycleFunctions: () => this.routeLifecycle.getFunctions(),
169
+ getMiddlewareFunctions: () => this.middleware.getFunctions(),
170
+ isActive: () => this.router.isActive(),
171
+ isTransitioning: () => this.eventBus.isTransitioning(),
172
+ clearCanDeactivate: (name) => {
173
+ this.routeLifecycle.clearCanDeactivate(name);
174
+ },
175
+ };
176
+
177
+ this.navigation.setTransitionDependencies(transitionDeps);
178
+ }
179
+
180
+ wireLifecycleDeps(): void {
181
+ const lifecycleDeps: RouterLifecycleDependencies = {
182
+ getOptions: () => this.options.get(),
183
+ makeNotFoundState: (path, options) =>
184
+ this.state.makeNotFoundState(path, options),
185
+ setState: (state) => {
186
+ this.state.set(state);
187
+ },
188
+ matchPath: (path) => this.routes.matchPath(path, this.options.get()),
189
+ completeStart: () => {
190
+ this.eventBus.completeStart();
191
+ },
192
+ emitTransitionError: (toState, fromState, error) => {
193
+ this.eventBus.failTransition(toState, fromState, error);
194
+ },
195
+ };
196
+
197
+ this.lifecycle.setDependencies(lifecycleDeps);
198
+ }
199
+
200
+ wireStateDeps(): void {
201
+ this.state.setDependencies({
202
+ getDefaultParams: () => this.routes.getConfig().defaultParams,
203
+ buildPath: (name, params) =>
204
+ this.routes.buildPath(name, params, this.options.get()),
205
+ getUrlParams: (name) => this.routes.getUrlParams(name),
206
+ });
207
+ }
208
+
209
+ wireCloneCallbacks(): void {
210
+ this.clone.setGetCloneData(() => {
211
+ const [canDeactivateFactories, canActivateFactories] =
212
+ this.routeLifecycle.getFactories();
213
+
214
+ return {
215
+ routes: this.routes.cloneRoutes(),
216
+ options: { ...this.options.get() },
217
+ dependencies: this.dependencies.getAll(),
218
+ canDeactivateFactories,
219
+ canActivateFactories,
220
+ middlewareFactories: this.middleware.getFactories(),
221
+ pluginFactories: this.plugins.getAll(),
222
+ routeConfig: this.routes.getConfig(),
223
+ resolvedForwardMap: this.routes.getResolvedForwardMap(),
224
+ };
225
+ });
226
+ }
227
+
228
+ wireCyclicDeps(): void {
229
+ this.navigation.setCanNavigate(() => this.eventBus.canBeginTransition());
230
+
231
+ this.lifecycle.setNavigateToState((toState, fromState, opts) =>
232
+ this.navigation.navigateToState(toState, fromState, opts),
233
+ );
234
+ }
235
+ }
@@ -0,0 +1,7 @@
1
+ // packages/core/src/wiring/index.ts
2
+
3
+ export { RouterWiringBuilder } from "./RouterWiringBuilder";
4
+
5
+ export { wireRouter } from "./wireRouter";
6
+
7
+ export type { WiringOptions } from "./types";
@@ -0,0 +1,53 @@
1
+ // packages/core/src/wiring/types.ts
2
+
3
+ import type {
4
+ CloneNamespace,
5
+ DependenciesNamespace,
6
+ EventBusNamespace,
7
+ MiddlewareNamespace,
8
+ NavigationNamespace,
9
+ OptionsNamespace,
10
+ PluginsNamespace,
11
+ RouteLifecycleNamespace,
12
+ RouterLifecycleNamespace,
13
+ RoutesNamespace,
14
+ StateNamespace,
15
+ } from "../namespaces";
16
+ import type { Router } from "../Router";
17
+ import type { Limits } from "../types";
18
+ import type { DefaultDependencies } from "@real-router/types";
19
+
20
+ /**
21
+ * Constructor options bag for RouterWiringBuilder.
22
+ *
23
+ * Contains all namespaces, FSM, emitter, and accessors needed to wire
24
+ * inter-namespace dependencies.
25
+ */
26
+ export interface WiringOptions<Dependencies extends DefaultDependencies> {
27
+ /** Router instance — passed to namespaces for factory initialization */
28
+ router: Router<Dependencies>;
29
+ /** Options namespace */
30
+ options: OptionsNamespace;
31
+ /** Immutable limits configuration */
32
+ limits: Limits;
33
+ /** Dependencies namespace */
34
+ dependencies: DependenciesNamespace<Dependencies>;
35
+ /** State namespace */
36
+ state: StateNamespace;
37
+ /** Routes namespace */
38
+ routes: RoutesNamespace<Dependencies>;
39
+ /** Route lifecycle namespace (canActivate/canDeactivate guards) */
40
+ routeLifecycle: RouteLifecycleNamespace<Dependencies>;
41
+ /** Middleware namespace */
42
+ middleware: MiddlewareNamespace<Dependencies>;
43
+ /** Plugins namespace */
44
+ plugins: PluginsNamespace<Dependencies>;
45
+ /** Navigation namespace */
46
+ navigation: NavigationNamespace;
47
+ /** Router lifecycle namespace (start/stop) */
48
+ lifecycle: RouterLifecycleNamespace;
49
+ /** Clone namespace (SSR cloning) */
50
+ clone: CloneNamespace<Dependencies>;
51
+ /** EventBus namespace — unified FSM + EventEmitter abstraction */
52
+ eventBus: EventBusNamespace;
53
+ }
@@ -0,0 +1,29 @@
1
+ // packages/core/src/wiring/wireRouter.ts
2
+
3
+ import type { RouterWiringBuilder } from "./RouterWiringBuilder";
4
+ import type { DefaultDependencies } from "@real-router/types";
5
+
6
+ /**
7
+ * Director function — calls RouterWiringBuilder methods in the correct dependency order.
8
+ *
9
+ * ORDER MATTERS:
10
+ * - `wireLimits()` first: all namespaces must have limits before any other setup
11
+ * - `wireRouteLifecycleDeps()` BEFORE `wireRoutesDeps()`: RoutesNamespace.setDependencies()
12
+ * registers pending canActivate handlers which require RouteLifecycleNamespace to be ready
13
+ * - `wireCyclicDeps()` LAST: resolves circular references between NavigationNamespace and
14
+ * RouterLifecycleNamespace (they depend on each other via direct property assignment)
15
+ */
16
+ export function wireRouter<Dependencies extends DefaultDependencies>(
17
+ builder: RouterWiringBuilder<Dependencies>,
18
+ ): void {
19
+ builder.wireLimits();
20
+ builder.wireRouteLifecycleDeps();
21
+ builder.wireRoutesDeps();
22
+ builder.wireMiddlewareDeps();
23
+ builder.wirePluginsDeps();
24
+ builder.wireNavigationDeps();
25
+ builder.wireLifecycleDeps();
26
+ builder.wireStateDeps();
27
+ builder.wireCloneCallbacks();
28
+ builder.wireCyclicDeps();
29
+ }