slicejs-web-framework 2.2.0 → 2.2.1
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.
|
@@ -8,6 +8,10 @@ export default class Router {
|
|
|
8
8
|
this._beforeEachGuard = null;
|
|
9
9
|
this._afterEachGuard = null;
|
|
10
10
|
|
|
11
|
+
// Router state
|
|
12
|
+
this._started = false;
|
|
13
|
+
this._autoStartTimeout = null;
|
|
14
|
+
|
|
11
15
|
// Sistema de caché optimizado
|
|
12
16
|
this.routeContainersCache = new Map();
|
|
13
17
|
this.lastCacheUpdate = 0;
|
|
@@ -17,9 +21,43 @@ export default class Router {
|
|
|
17
21
|
this.setupMutationObserver();
|
|
18
22
|
}
|
|
19
23
|
|
|
20
|
-
|
|
21
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Inicializa el router
|
|
26
|
+
* Si el usuario no llama start() manualmente, se auto-inicia después de un delay
|
|
27
|
+
*/
|
|
28
|
+
init() {
|
|
22
29
|
window.addEventListener('popstate', this.onRouteChange.bind(this));
|
|
30
|
+
|
|
31
|
+
// Auto-start después de 50ms si el usuario no llama start() manualmente
|
|
32
|
+
// Esto da tiempo para que el usuario configure guards si lo necesita
|
|
33
|
+
this._autoStartTimeout = setTimeout(async () => {
|
|
34
|
+
if (!this._started) {
|
|
35
|
+
slice.logger.logInfo('Router', 'Auto-starting router (no manual start() called)');
|
|
36
|
+
await this.start();
|
|
37
|
+
}
|
|
38
|
+
}, 50);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Inicia el router y carga la ruta inicial
|
|
43
|
+
* OPCIONAL: Solo necesario si usas guards (beforeEach/afterEach)
|
|
44
|
+
* Si no lo llamas, el router se auto-inicia después de 50ms
|
|
45
|
+
*/
|
|
46
|
+
async start() {
|
|
47
|
+
// Prevenir múltiples llamadas
|
|
48
|
+
if (this._started) {
|
|
49
|
+
slice.logger.logWarning('Router', 'start() already called');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Cancelar auto-start si existe
|
|
54
|
+
if (this._autoStartTimeout) {
|
|
55
|
+
clearTimeout(this._autoStartTimeout);
|
|
56
|
+
this._autoStartTimeout = null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
this._started = true;
|
|
60
|
+
await this.loadInitialRoute();
|
|
23
61
|
}
|
|
24
62
|
|
|
25
63
|
// ============================================
|
|
@@ -56,12 +94,13 @@ export default class Router {
|
|
|
56
94
|
* Crea un objeto con información de ruta para los guards
|
|
57
95
|
* @param {Object} route - Objeto de ruta
|
|
58
96
|
* @param {Object} params - Parámetros de la ruta
|
|
97
|
+
* @param {String} requestedPath - Path original solicitado
|
|
59
98
|
* @returns {Object} Objeto con path, component, params, query, metadata
|
|
60
99
|
*/
|
|
61
|
-
_createRouteInfo(route, params = {}) {
|
|
100
|
+
_createRouteInfo(route, params = {}, requestedPath = null) {
|
|
62
101
|
if (!route) {
|
|
63
102
|
return {
|
|
64
|
-
path: '/404',
|
|
103
|
+
path: requestedPath || '/404',
|
|
65
104
|
component: 'NotFound',
|
|
66
105
|
params: {},
|
|
67
106
|
query: this._parseQueryParams(),
|
|
@@ -70,7 +109,7 @@ export default class Router {
|
|
|
70
109
|
}
|
|
71
110
|
|
|
72
111
|
return {
|
|
73
|
-
path: route.fullPath || route.path,
|
|
112
|
+
path: requestedPath || route.fullPath || route.path,
|
|
74
113
|
component: route.parentRoute ? route.parentRoute.component : route.component,
|
|
75
114
|
params: params,
|
|
76
115
|
query: this._parseQueryParams(),
|
|
@@ -161,31 +200,48 @@ export default class Router {
|
|
|
161
200
|
// ROUTING CORE (MODIFICADO CON GUARDS)
|
|
162
201
|
// ============================================
|
|
163
202
|
|
|
164
|
-
async navigate(path) {
|
|
203
|
+
async navigate(path, _redirectChain = []) {
|
|
165
204
|
const currentPath = window.location.pathname;
|
|
166
205
|
|
|
206
|
+
|
|
207
|
+
// Detectar loops infinitos: si ya visitamos esta ruta en la cadena de redirecciones
|
|
208
|
+
if (_redirectChain.includes(path)) {
|
|
209
|
+
slice.logger.logError(
|
|
210
|
+
'Router',
|
|
211
|
+
`Guard redirection loop detected: ${_redirectChain.join(' → ')} → ${path}`
|
|
212
|
+
);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Límite de seguridad: máximo 10 redirecciones
|
|
217
|
+
if (_redirectChain.length >= 10) {
|
|
218
|
+
slice.logger.logError(
|
|
219
|
+
'Router',
|
|
220
|
+
`Too many redirections: ${_redirectChain.join(' → ')} → ${path}`
|
|
221
|
+
);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
167
225
|
// Obtener información de ruta actual
|
|
168
226
|
const { route: fromRoute, params: fromParams } = this.matchRoute(currentPath);
|
|
169
|
-
const from = this._createRouteInfo(fromRoute, fromParams);
|
|
227
|
+
const from = this._createRouteInfo(fromRoute, fromParams, currentPath);
|
|
170
228
|
|
|
171
229
|
// Obtener información de ruta destino
|
|
172
230
|
const { route: toRoute, params: toParams } = this.matchRoute(path);
|
|
173
|
-
const to = this._createRouteInfo(toRoute, toParams);
|
|
231
|
+
const to = this._createRouteInfo(toRoute, toParams, path); // ← PASAR EL PATH AQUÍ
|
|
232
|
+
|
|
174
233
|
|
|
175
234
|
// EJECUTAR BEFORE EACH GUARD
|
|
176
235
|
const redirectPath = await this._executeBeforeEachGuard(to, from);
|
|
177
236
|
|
|
178
|
-
// Si el guard redirige, navegar a la nueva ruta
|
|
237
|
+
// Si el guard redirige, agregar ruta actual a la cadena y navegar a la nueva ruta
|
|
179
238
|
if (redirectPath) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
return this.navigate(redirectPath);
|
|
239
|
+
const newChain = [..._redirectChain, path];
|
|
240
|
+
|
|
241
|
+
return this.navigate(redirectPath, newChain);
|
|
186
242
|
}
|
|
187
243
|
|
|
188
|
-
//
|
|
244
|
+
// No hay redirección - continuar con la navegación normal
|
|
189
245
|
window.history.pushState({}, path, window.location.origin + path);
|
|
190
246
|
await this._performNavigation(to, from);
|
|
191
247
|
}
|
|
@@ -272,8 +328,8 @@ export default class Router {
|
|
|
272
328
|
const { route, params } = this.matchRoute(path);
|
|
273
329
|
|
|
274
330
|
// Para la carga inicial, también ejecutar guards
|
|
275
|
-
const from = this._createRouteInfo(null, {});
|
|
276
|
-
const to = this._createRouteInfo(route, params);
|
|
331
|
+
const from = this._createRouteInfo(null, {}, null);
|
|
332
|
+
const to = this._createRouteInfo(route, params, path); // ← PASAR EL PATH AQUÍ
|
|
277
333
|
|
|
278
334
|
// EJECUTAR BEFORE EACH GUARD en carga inicial
|
|
279
335
|
const redirectPath = await this._executeBeforeEachGuard(to, from);
|
package/Slice/Slice.js
CHANGED
|
@@ -217,15 +217,6 @@ async function init() {
|
|
|
217
217
|
window.slice.router = new RouterModule(routes);
|
|
218
218
|
await window.slice.router.init();
|
|
219
219
|
|
|
220
|
-
|
|
221
|
-
/*
|
|
222
|
-
if (sliceConfig.translator.enabled) {
|
|
223
|
-
const translator = await window.slice.build('Translator');
|
|
224
|
-
window.slice.translator = translator;
|
|
225
|
-
window.slice.logger.logInfo('Slice', 'Translator succesfuly enabled');
|
|
226
|
-
}
|
|
227
|
-
*/
|
|
228
|
-
|
|
229
220
|
}
|
|
230
221
|
|
|
231
222
|
await init();
|