slicejs-web-framework 1.0.28 → 1.0.31
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/Slice/Components/Structural/Controller/Controller.js +125 -12
- package/Slice/Components/Structural/Debugger/Debugger.css +590 -65
- package/Slice/Components/Structural/Debugger/Debugger.html +72 -9
- package/Slice/Components/Structural/Debugger/Debugger.js +529 -216
- package/Slice/Components/Structural/Router/EventThrottler.js +110 -0
- package/Slice/Components/Structural/Router/RouteCache.js +245 -0
- package/Slice/Components/Structural/Router/RouteMatcher.js +236 -0
- package/Slice/Components/Structural/Router/RouteRenderer.js +324 -0
- package/Slice/Components/Structural/Router/Router.js +315 -240
- package/Slice/Slice.js +5 -0
- package/package.json +1 -1
- package/src/Components/Visual/Button/Button.js +40 -17
|
@@ -1,305 +1,380 @@
|
|
|
1
|
+
// Slice/Components/Structural/Router/Router.js
|
|
2
|
+
|
|
3
|
+
import EventThrottler from './EventThrottler.js';
|
|
4
|
+
import RouteCache from './RouteCache.js';
|
|
5
|
+
import RouteMatcher from './RouteMatcher.js';
|
|
6
|
+
import RouteRenderer from './RouteRenderer.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Router optimizado con separación de responsabilidades
|
|
10
|
+
* Mejoras significativas en performance y mantenibilidad
|
|
11
|
+
*/
|
|
1
12
|
export default class Router {
|
|
2
13
|
constructor(routes) {
|
|
3
14
|
this.routes = routes;
|
|
4
15
|
this.activeRoute = null;
|
|
5
|
-
this.pathToRouteMap = this.createPathToRouteMap(routes);
|
|
6
16
|
|
|
7
|
-
//
|
|
8
|
-
this.
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
17
|
+
// Inicializar sistemas especializados
|
|
18
|
+
this.eventThrottler = new EventThrottler();
|
|
19
|
+
this.routeCache = new RouteCache();
|
|
20
|
+
this.routeMatcher = new RouteMatcher(routes);
|
|
21
|
+
this.routeRenderer = new RouteRenderer(this.routeCache);
|
|
11
22
|
|
|
12
|
-
//
|
|
13
|
-
this.
|
|
23
|
+
// Observer para cambios DOM
|
|
24
|
+
this.mutationObserver = null;
|
|
25
|
+
|
|
26
|
+
// Estado del router
|
|
27
|
+
this.isInitialized = false;
|
|
28
|
+
this.isNavigating = false;
|
|
14
29
|
}
|
|
15
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Inicializar router con observadores optimizados
|
|
33
|
+
*/
|
|
16
34
|
async init() {
|
|
17
|
-
|
|
18
|
-
|
|
35
|
+
if (this.isInitialized) {
|
|
36
|
+
slice.logger.logWarning('Router', 'Router already initialized');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
// Configurar observador de mutaciones optimizado
|
|
42
|
+
this.setupMutationObserver();
|
|
43
|
+
|
|
44
|
+
// Cargar ruta inicial
|
|
45
|
+
await this.loadInitialRoute();
|
|
46
|
+
|
|
47
|
+
// Configurar listeners de navegación
|
|
48
|
+
this.setupNavigationListeners();
|
|
49
|
+
|
|
50
|
+
this.isInitialized = true;
|
|
51
|
+
slice.logger.logInfo('Router', 'Router initialized successfully');
|
|
52
|
+
|
|
53
|
+
} catch (error) {
|
|
54
|
+
slice.logger.logError('Router', 'Error initializing router', error);
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
19
57
|
}
|
|
20
58
|
|
|
21
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Configurar observador de mutaciones optimizado
|
|
61
|
+
*/
|
|
22
62
|
setupMutationObserver() {
|
|
23
|
-
if (typeof MutationObserver
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.observer.observe(document.body, {
|
|
52
|
-
childList: true,
|
|
53
|
-
subtree: true
|
|
63
|
+
if (typeof MutationObserver === 'undefined') {
|
|
64
|
+
slice.logger.logWarning('Router', 'MutationObserver not available');
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
this.mutationObserver = new MutationObserver((mutations) => {
|
|
69
|
+
// Usar throttling para evitar múltiples invalidaciones
|
|
70
|
+
this.eventThrottler.throttle('cache-invalidation', () => {
|
|
71
|
+
this.routeCache.invalidateByMutation(mutations);
|
|
72
|
+
}, 50);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
this.mutationObserver.observe(document.body, {
|
|
76
|
+
childList: true,
|
|
77
|
+
subtree: true,
|
|
78
|
+
attributeFilter: ['slice-route', 'slice-multi-route']
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Configurar listeners de navegación
|
|
84
|
+
*/
|
|
85
|
+
setupNavigationListeners() {
|
|
86
|
+
// Listener para popstate (back/forward)
|
|
87
|
+
window.addEventListener('popstate', (event) => {
|
|
88
|
+
this.eventThrottler.throttle('popstate', () => {
|
|
89
|
+
return this.onRouteChange();
|
|
54
90
|
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Interceptación automática de enlaces (activada por defecto)
|
|
94
|
+
// Para desactivar: agregar disableAutoInterceptLinks: true en la configuración
|
|
95
|
+
if (!this.routes.disableAutoInterceptLinks) {
|
|
96
|
+
this.setupLinkInterception();
|
|
97
|
+
slice.logger.logInfo('Router', 'Auto link interception enabled');
|
|
55
98
|
}
|
|
56
99
|
}
|
|
57
100
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Configurar interceptación de enlaces
|
|
103
|
+
* Convierte todos los <a href="/path"> en slice.router.navigate()
|
|
104
|
+
*/
|
|
105
|
+
setupLinkInterception() {
|
|
106
|
+
document.addEventListener('click', (event) => {
|
|
107
|
+
const link = event.target.closest('a[href]');
|
|
108
|
+
if (link && this.shouldInterceptLink(link)) {
|
|
109
|
+
event.preventDefault();
|
|
110
|
+
|
|
111
|
+
const href = link.getAttribute('href');
|
|
112
|
+
slice.logger.logInfo('Router', `Intercepting link: ${href}`);
|
|
113
|
+
|
|
114
|
+
this.navigate(href);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
62
117
|
}
|
|
63
118
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
pathToRouteMap.set(childPath, childRoute);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
119
|
+
/**
|
|
120
|
+
* Verificar si debe interceptar el enlace
|
|
121
|
+
*/
|
|
122
|
+
shouldInterceptLink(link) {
|
|
123
|
+
const href = link.getAttribute('href');
|
|
124
|
+
|
|
125
|
+
// No interceptar si no hay href
|
|
126
|
+
if (!href) return false;
|
|
127
|
+
|
|
128
|
+
// No interceptar enlaces externos (diferentes dominio)
|
|
129
|
+
if (href.startsWith('http://') || href.startsWith('https://')) {
|
|
130
|
+
const linkUrl = new URL(href, window.location.origin);
|
|
131
|
+
if (linkUrl.origin !== window.location.origin) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// No interceptar protocolos especiales
|
|
137
|
+
if (href.startsWith('mailto:') ||
|
|
138
|
+
href.startsWith('tel:') ||
|
|
139
|
+
href.startsWith('sms:') ||
|
|
140
|
+
href.startsWith('ftp:')) {
|
|
141
|
+
return false;
|
|
90
142
|
}
|
|
91
|
-
|
|
92
|
-
|
|
143
|
+
|
|
144
|
+
// No interceptar anchors (#hash)
|
|
145
|
+
if (href.startsWith('#')) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// No interceptar si tiene atributos especiales
|
|
150
|
+
if (link.hasAttribute('download') ||
|
|
151
|
+
link.target === '_blank' ||
|
|
152
|
+
link.target === '_top' ||
|
|
153
|
+
link.target === '_parent' ||
|
|
154
|
+
link.hasAttribute('data-no-intercept') ||
|
|
155
|
+
link.hasAttribute('data-external')) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// No interceptar si está marcado como externo
|
|
160
|
+
if (link.classList.contains('external-link') ||
|
|
161
|
+
link.classList.contains('no-intercept')) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return true;
|
|
93
166
|
}
|
|
94
167
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
168
|
+
/**
|
|
169
|
+
* Manejar cambio de ruta con throttling optimizado
|
|
170
|
+
*/
|
|
171
|
+
async onRouteChange() {
|
|
172
|
+
if (this.isNavigating) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
99
175
|
|
|
100
|
-
|
|
176
|
+
return this.eventThrottler.throttle('route-change', async () => {
|
|
177
|
+
this.isNavigating = true;
|
|
178
|
+
|
|
101
179
|
try {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
180
|
+
const path = window.location.pathname;
|
|
181
|
+
|
|
182
|
+
// Intentar renderizar rutas en componentes existentes primero
|
|
183
|
+
const routeContainersFlag = await this.routeRenderer.renderRoutesComponentsInPage();
|
|
184
|
+
|
|
185
|
+
if (routeContainersFlag) {
|
|
186
|
+
return;
|
|
106
187
|
}
|
|
107
188
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
189
|
+
// Si no hay contenedores de rutas, hacer matching tradicional
|
|
190
|
+
const { route, params } = this.routeMatcher.matchRoute(path);
|
|
191
|
+
if (route) {
|
|
192
|
+
await this.routeRenderer.handleRoute(route, params);
|
|
112
193
|
}
|
|
194
|
+
|
|
113
195
|
} catch (error) {
|
|
114
|
-
slice.logger.logError('Router',
|
|
196
|
+
slice.logger.logError('Router', 'Error during route change', error);
|
|
197
|
+
} finally {
|
|
198
|
+
this.isNavigating = false;
|
|
115
199
|
}
|
|
200
|
+
}, 10);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Navegar a una ruta específica
|
|
205
|
+
*/
|
|
206
|
+
async navigate(path, options = {}) {
|
|
207
|
+
if (!path || path === window.location.pathname) {
|
|
208
|
+
return;
|
|
116
209
|
}
|
|
117
210
|
|
|
118
|
-
|
|
211
|
+
try {
|
|
212
|
+
const { replace = false, state = {} } = options;
|
|
213
|
+
|
|
214
|
+
// Actualizar historia del navegador
|
|
215
|
+
if (replace) {
|
|
216
|
+
window.history.replaceState(state, '', window.location.origin + path);
|
|
217
|
+
} else {
|
|
218
|
+
window.history.pushState(state, '', window.location.origin + path);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Ejecutar cambio de ruta
|
|
222
|
+
await this.onRouteChange();
|
|
223
|
+
|
|
224
|
+
} catch (error) {
|
|
225
|
+
slice.logger.logError('Router', `Error navigating to ${path}`, error);
|
|
226
|
+
}
|
|
119
227
|
}
|
|
120
228
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (this.routeContainersCache.has(containerKey) &&
|
|
128
|
-
(now - this.lastCacheUpdate) < this.CACHE_DURATION) {
|
|
129
|
-
return this.routeContainersCache.get(containerKey);
|
|
130
|
-
}
|
|
229
|
+
/**
|
|
230
|
+
* Navegar hacia atrás
|
|
231
|
+
*/
|
|
232
|
+
back() {
|
|
233
|
+
window.history.back();
|
|
234
|
+
}
|
|
131
235
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return routeContainers;
|
|
236
|
+
/**
|
|
237
|
+
* Navegar hacia adelante
|
|
238
|
+
*/
|
|
239
|
+
forward() {
|
|
240
|
+
window.history.forward();
|
|
138
241
|
}
|
|
139
242
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
container,
|
|
147
|
-
NodeFilter.SHOW_ELEMENT,
|
|
148
|
-
{
|
|
149
|
-
acceptNode: (node) => {
|
|
150
|
-
// Solo aceptar nodos que sean slice-route o slice-multi-route
|
|
151
|
-
if (node.tagName === 'SLICE-ROUTE' || node.tagName === 'SLICE-MULTI-ROUTE') {
|
|
152
|
-
return NodeFilter.FILTER_ACCEPT;
|
|
153
|
-
}
|
|
154
|
-
return NodeFilter.FILTER_SKIP;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
);
|
|
243
|
+
/**
|
|
244
|
+
* Cargar ruta inicial
|
|
245
|
+
*/
|
|
246
|
+
async loadInitialRoute() {
|
|
247
|
+
const path = window.location.pathname;
|
|
248
|
+
const { route, params } = this.routeMatcher.matchRoute(path);
|
|
158
249
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
250
|
+
if (route) {
|
|
251
|
+
await this.routeRenderer.handleRoute(route, params);
|
|
252
|
+
} else {
|
|
253
|
+
slice.logger.logWarning('Router', `No route found for initial path: ${path}`);
|
|
162
254
|
}
|
|
255
|
+
}
|
|
163
256
|
|
|
164
|
-
|
|
257
|
+
/**
|
|
258
|
+
* Métodos de conveniencia para acceso a subsistemas
|
|
259
|
+
*/
|
|
260
|
+
|
|
261
|
+
// Acceso al matcher
|
|
262
|
+
matchRoute(path) {
|
|
263
|
+
return this.routeMatcher.matchRoute(path);
|
|
165
264
|
}
|
|
166
265
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
slice.logger.logWarning('Router', 'No component provided for route rendering');
|
|
171
|
-
return false;
|
|
172
|
-
}
|
|
266
|
+
hasRoute(path) {
|
|
267
|
+
return this.routeMatcher.hasRoute(path);
|
|
268
|
+
}
|
|
173
269
|
|
|
174
|
-
|
|
270
|
+
generateUrl(routePath, params) {
|
|
271
|
+
return this.routeMatcher.generateUrl(routePath, params);
|
|
175
272
|
}
|
|
176
273
|
|
|
177
|
-
//
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
clearTimeout(this.routeChangeTimeout);
|
|
182
|
-
}
|
|
274
|
+
// Acceso al caché
|
|
275
|
+
invalidateCache() {
|
|
276
|
+
this.routeCache.invalidateAll();
|
|
277
|
+
}
|
|
183
278
|
|
|
184
|
-
|
|
185
|
-
this.
|
|
186
|
-
|
|
187
|
-
const routeContainersFlag = await this.renderRoutesComponentsInPage();
|
|
279
|
+
getCacheStats() {
|
|
280
|
+
return this.routeCache.getStats();
|
|
281
|
+
}
|
|
188
282
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
283
|
+
// Acceso al renderer
|
|
284
|
+
async renderRoutesInComponent(component) {
|
|
285
|
+
return this.routeRenderer.renderRoutesInComponent(component);
|
|
286
|
+
}
|
|
192
287
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
await this.handleRoute(route, params);
|
|
196
|
-
}
|
|
197
|
-
}, 10);
|
|
288
|
+
getRendererStats() {
|
|
289
|
+
return this.routeRenderer.getStats();
|
|
198
290
|
}
|
|
199
291
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
292
|
+
/**
|
|
293
|
+
* Actualizar rutas dinámicamente
|
|
294
|
+
*/
|
|
295
|
+
updateRoutes(newRoutes) {
|
|
296
|
+
this.routes = newRoutes;
|
|
297
|
+
this.routeMatcher.updateRoutes(newRoutes);
|
|
298
|
+
this.invalidateCache();
|
|
203
299
|
}
|
|
204
300
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
301
|
+
/**
|
|
302
|
+
* Añadir ruta individual
|
|
303
|
+
*/
|
|
304
|
+
addRoute(route, basePath = '') {
|
|
305
|
+
this.routeMatcher.addRoute(route, basePath);
|
|
306
|
+
this.invalidateCache();
|
|
307
|
+
}
|
|
212
308
|
|
|
213
|
-
|
|
214
|
-
|
|
309
|
+
/**
|
|
310
|
+
* Remover ruta
|
|
311
|
+
*/
|
|
312
|
+
removeRoute(path) {
|
|
313
|
+
this.routeMatcher.removeRoute(path);
|
|
314
|
+
this.invalidateCache();
|
|
215
315
|
}
|
|
216
316
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
targetElement.appendChild(existingComponent);
|
|
224
|
-
// Renderizar DESPUÉS de insertar (pero antes de mostrar)
|
|
225
|
-
await this.renderRoutesInComponent(existingComponent);
|
|
226
|
-
} else {
|
|
227
|
-
const component = await slice.build(componentName, {
|
|
228
|
-
params,
|
|
229
|
-
sliceId: sliceId,
|
|
230
|
-
});
|
|
317
|
+
/**
|
|
318
|
+
* Obtener todas las rutas
|
|
319
|
+
*/
|
|
320
|
+
getAllRoutes() {
|
|
321
|
+
return this.routeMatcher.getAllRoutes();
|
|
322
|
+
}
|
|
231
323
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
324
|
+
/**
|
|
325
|
+
* Obtener estadísticas completas del router
|
|
326
|
+
*/
|
|
327
|
+
getStats() {
|
|
328
|
+
return {
|
|
329
|
+
isInitialized: this.isInitialized,
|
|
330
|
+
isNavigating: this.isNavigating,
|
|
331
|
+
activeRoute: this.activeRoute,
|
|
332
|
+
matcher: this.routeMatcher.getStats(),
|
|
333
|
+
cache: this.routeCache.getStats(),
|
|
334
|
+
renderer: this.routeRenderer.getStats(),
|
|
335
|
+
eventThrottler: {
|
|
336
|
+
pendingEvents: this.eventThrottler.timeouts.size
|
|
337
|
+
}
|
|
338
|
+
};
|
|
237
339
|
}
|
|
238
340
|
|
|
239
|
-
|
|
240
|
-
|
|
341
|
+
/**
|
|
342
|
+
* Destruir router y cleanup
|
|
343
|
+
*/
|
|
344
|
+
destroy() {
|
|
345
|
+
// Detener observadores
|
|
346
|
+
if (this.mutationObserver) {
|
|
347
|
+
this.mutationObserver.disconnect();
|
|
348
|
+
this.mutationObserver = null;
|
|
349
|
+
}
|
|
241
350
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
351
|
+
// Cancelar eventos pendientes
|
|
352
|
+
this.eventThrottler.destroy();
|
|
245
353
|
|
|
246
|
-
|
|
247
|
-
|
|
354
|
+
// Limpiar subsistemas
|
|
355
|
+
this.routeCache.destroy();
|
|
356
|
+
this.routeRenderer.destroy();
|
|
248
357
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
const { route, params } = this.matchRoute(path);
|
|
358
|
+
// Remover listeners
|
|
359
|
+
window.removeEventListener('popstate', this.onRouteChange);
|
|
252
360
|
|
|
253
|
-
|
|
361
|
+
this.isInitialized = false;
|
|
362
|
+
|
|
363
|
+
slice.logger.logInfo('Router', 'Router destroyed successfully');
|
|
254
364
|
}
|
|
255
365
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
return { route: exactMatch, params: {} };
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
for (const [routePattern, route] of this.pathToRouteMap.entries()) {
|
|
270
|
-
if (routePattern.includes('${')) {
|
|
271
|
-
const { regex, paramNames } = this.compilePathPattern(routePattern);
|
|
272
|
-
const match = path.match(regex);
|
|
273
|
-
if (match) {
|
|
274
|
-
const params = {};
|
|
275
|
-
paramNames.forEach((name, i) => {
|
|
276
|
-
params[name] = match[i + 1];
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
if (route.parentRoute) {
|
|
280
|
-
return {
|
|
281
|
-
route: route.parentRoute,
|
|
282
|
-
params: params,
|
|
283
|
-
childRoute: route
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
return { route, params };
|
|
288
|
-
}
|
|
289
|
-
}
|
|
366
|
+
/**
|
|
367
|
+
* Reinicializar router (útil para testing)
|
|
368
|
+
*/
|
|
369
|
+
async reinitialize(newRoutes = null) {
|
|
370
|
+
this.destroy();
|
|
371
|
+
|
|
372
|
+
if (newRoutes) {
|
|
373
|
+
this.routes = newRoutes;
|
|
374
|
+
this.routeMatcher = new RouteMatcher(newRoutes);
|
|
375
|
+
this.routeRenderer = new RouteRenderer(this.routeCache);
|
|
290
376
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
return { route: notFoundRoute, params: {} };
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
compilePathPattern(pattern) {
|
|
297
|
-
const paramNames = [];
|
|
298
|
-
const regexPattern = '^' + pattern.replace(/\$\{([^}]+)\}/g, (_, paramName) => {
|
|
299
|
-
paramNames.push(paramName);
|
|
300
|
-
return '([^/]+)';
|
|
301
|
-
}) + '$';
|
|
302
|
-
|
|
303
|
-
return { regex: new RegExp(regexPattern), paramNames };
|
|
377
|
+
|
|
378
|
+
await this.init();
|
|
304
379
|
}
|
|
305
380
|
}
|
package/Slice/Slice.js
CHANGED
|
@@ -11,6 +11,7 @@ export default class Slice {
|
|
|
11
11
|
this.loggerConfig = sliceConfig.logger;
|
|
12
12
|
this.debuggerConfig = sliceConfig.debugger;
|
|
13
13
|
this.loadingConfig = sliceConfig.loading;
|
|
14
|
+
this.productionConfig = sliceConfig.production;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
async getClass(module) {
|
|
@@ -22,6 +23,10 @@ export default class Slice {
|
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
isProduction(){
|
|
27
|
+
return this.productionConfig.enabled;
|
|
28
|
+
}
|
|
29
|
+
|
|
25
30
|
getComponent(componentSliceId) {
|
|
26
31
|
return this.controller.activeComponents.get(componentSliceId);
|
|
27
32
|
}
|