@real-router/core 0.26.0 → 0.28.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.
@@ -45,6 +45,8 @@ export class RouteLifecycleNamespace<
45
45
  readonly #canActivateFunctions = new Map<string, GuardFn>();
46
46
 
47
47
  readonly #registering = new Set<string>();
48
+ readonly #definitionActivateGuardNames = new Set<string>();
49
+ readonly #definitionDeactivateGuardNames = new Set<string>();
48
50
 
49
51
  #router!: Router<Dependencies>;
50
52
  #deps!: RouteLifecycleDependencies<Dependencies>;
@@ -73,12 +75,19 @@ export class RouteLifecycleNamespace<
73
75
  * @param name - Route name (input-validated by facade)
74
76
  * @param handler - Guard function or boolean (input-validated by facade)
75
77
  * @param skipValidation - True when called during route config building (#noValidate)
78
+ * @param isFromDefinition - True when guard comes from route definition (tracked for HMR replace)
76
79
  */
77
80
  addCanActivate(
78
81
  name: string,
79
82
  handler: GuardFnFactory<Dependencies> | boolean,
80
83
  skipValidation: boolean,
84
+ isFromDefinition = false,
81
85
  ): void {
86
+ if (isFromDefinition) {
87
+ this.#definitionActivateGuardNames.add(name);
88
+ } else {
89
+ this.#definitionActivateGuardNames.delete(name);
90
+ }
82
91
  if (!skipValidation) {
83
92
  validateNotRegistering(
84
93
  this.#registering.has(name),
@@ -115,12 +124,19 @@ export class RouteLifecycleNamespace<
115
124
  * @param name - Route name (input-validated by facade)
116
125
  * @param handler - Guard function or boolean (input-validated by facade)
117
126
  * @param skipValidation - True when called during route config building (#noValidate)
127
+ * @param isFromDefinition - True when guard comes from route definition (tracked for HMR replace)
118
128
  */
119
129
  addCanDeactivate(
120
130
  name: string,
121
131
  handler: GuardFnFactory<Dependencies> | boolean,
122
132
  skipValidation: boolean,
133
+ isFromDefinition = false,
123
134
  ): void {
135
+ if (isFromDefinition) {
136
+ this.#definitionDeactivateGuardNames.add(name);
137
+ } else {
138
+ this.#definitionDeactivateGuardNames.delete(name);
139
+ }
124
140
  if (!skipValidation) {
125
141
  validateNotRegistering(
126
142
  this.#registering.has(name),
@@ -159,6 +175,7 @@ export class RouteLifecycleNamespace<
159
175
  clearCanActivate(name: string): void {
160
176
  this.#canActivateFactories.delete(name);
161
177
  this.#canActivateFunctions.delete(name);
178
+ this.#definitionActivateGuardNames.delete(name);
162
179
  }
163
180
 
164
181
  /**
@@ -170,6 +187,7 @@ export class RouteLifecycleNamespace<
170
187
  clearCanDeactivate(name: string): void {
171
188
  this.#canDeactivateFactories.delete(name);
172
189
  this.#canDeactivateFunctions.delete(name);
190
+ this.#definitionDeactivateGuardNames.delete(name);
173
191
  }
174
192
 
175
193
  /**
@@ -181,6 +199,26 @@ export class RouteLifecycleNamespace<
181
199
  this.#canActivateFunctions.clear();
182
200
  this.#canDeactivateFactories.clear();
183
201
  this.#canDeactivateFunctions.clear();
202
+ this.#definitionActivateGuardNames.clear();
203
+ this.#definitionDeactivateGuardNames.clear();
204
+ }
205
+
206
+ /**
207
+ * Clears only lifecycle handlers that were registered from route definitions.
208
+ * Used by HMR to remove definition-sourced guards without touching externally-added guards.
209
+ */
210
+ clearDefinitionGuards(): void {
211
+ for (const name of this.#definitionActivateGuardNames) {
212
+ this.#canActivateFactories.delete(name);
213
+ this.#canActivateFunctions.delete(name);
214
+ }
215
+ for (const name of this.#definitionDeactivateGuardNames) {
216
+ this.#canDeactivateFactories.delete(name);
217
+ this.#canDeactivateFunctions.delete(name);
218
+ }
219
+
220
+ this.#definitionActivateGuardNames.clear();
221
+ this.#definitionDeactivateGuardNames.clear();
184
222
  }
185
223
 
186
224
  /**
@@ -135,6 +135,6 @@ export class RouterLifecycleNamespace {
135
135
  * Called only for READY/TRANSITIONING states (facade handles STARTING/IDLE/DISPOSED).
136
136
  */
137
137
  stop(): void {
138
- this.#deps.setState();
138
+ this.#deps.clearState();
139
139
  }
140
140
  }
@@ -10,7 +10,7 @@ import type {
10
10
  export interface RouterLifecycleDependencies {
11
11
  getOptions: () => Options;
12
12
  makeNotFoundState: (path: string, options: NavigationOptions) => State;
13
- setState: (state?: State) => void;
13
+ clearState: () => void;
14
14
  matchPath: <P extends Params = Params, MP extends Params = Params>(
15
15
  path: string,
16
16
  ) => State<P, MP> | undefined;
@@ -108,6 +108,17 @@ export function rebuildTreeInPlace<
108
108
  */
109
109
  export function resetStore<
110
110
  Dependencies extends DefaultDependencies = DefaultDependencies,
111
+ >(store: RoutesStore<Dependencies>): void {
112
+ clearRouteData(store);
113
+ rebuildTreeInPlace(store);
114
+ }
115
+
116
+ /**
117
+ * Clears route data without rebuilding the tree.
118
+ * Used by replace() to avoid double rebuild (clearRouteData + commitTreeChanges).
119
+ */
120
+ export function clearRouteData<
121
+ Dependencies extends DefaultDependencies = DefaultDependencies,
111
122
  >(store: RoutesStore<Dependencies>): void {
112
123
  store.definitions.length = 0;
113
124
 
@@ -118,8 +129,6 @@ export function resetStore<
118
129
  string,
119
130
  Record<string, unknown>
120
131
  >;
121
-
122
- rebuildTreeInPlace(store);
123
132
  }
124
133
 
125
134
  // =============================================================================
@@ -69,10 +69,10 @@ export class RouterWiringBuilder<
69
69
  wireRoutesDeps(): void {
70
70
  const routesDeps: RoutesDependencies<Dependencies> = {
71
71
  addActivateGuard: (name, handler) => {
72
- this.routeLifecycle.addCanActivate(name, handler, true);
72
+ this.routeLifecycle.addCanActivate(name, handler, true, true);
73
73
  },
74
74
  addDeactivateGuard: (name, handler) => {
75
- this.routeLifecycle.addCanDeactivate(name, handler, true);
75
+ this.routeLifecycle.addCanDeactivate(name, handler, true, true);
76
76
  },
77
77
  makeState: (name, params, path, meta) =>
78
78
  this.state.makeState(name, params, path, meta),
@@ -179,8 +179,8 @@ export class RouterWiringBuilder<
179
179
  getOptions: () => this.options.get(),
180
180
  makeNotFoundState: (path, options) =>
181
181
  this.state.makeNotFoundState(path, options),
182
- setState: (state) => {
183
- this.state.set(state);
182
+ clearState: () => {
183
+ this.state.set(undefined);
184
184
  },
185
185
  matchPath: (path) => this.routes.matchPath(path, this.options.get()),
186
186
  completeStart: () => {