slicejs-cli 2.7.8 → 2.7.9

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.
@@ -220,13 +220,66 @@ export default class BundleGenerator {
220
220
  assignHybridBundles(criticalNames) {
221
221
  const routeGroups = new Map();
222
222
 
223
- // Group routes by category
223
+ // First, handle MultiRoute groups
224
+ if (this.analysisData.routeGroups) {
225
+ for (const [groupKey, groupData] of this.analysisData.routeGroups) {
226
+ if (groupData.type === 'multiroute') {
227
+ // Create a bundle for this MultiRoute group
228
+ const allComponents = new Set();
229
+
230
+ // Add the main component (MultiRoute handler)
231
+ const mainComponent = this.analysisData.components.find(c => c.name === groupData.component);
232
+ if (mainComponent) {
233
+ allComponents.add(mainComponent);
234
+
235
+ // Add all components used by this MultiRoute
236
+ const routeComponents = this.getRouteComponents(mainComponent.name);
237
+ for (const comp of routeComponents) {
238
+ allComponents.add(comp);
239
+ // Add transitive dependencies
240
+ const dependencies = this.getComponentDependencies(comp);
241
+ for (const dep of dependencies) {
242
+ allComponents.add(dep);
243
+ }
244
+ }
245
+ }
246
+
247
+ // Filter those already in critical
248
+ const uniqueComponents = Array.from(allComponents).filter(comp =>
249
+ !criticalNames.has(comp.name)
250
+ );
251
+
252
+ if (uniqueComponents.length > 0) {
253
+ const totalSize = uniqueComponents.reduce((sum, c) => sum + c.size, 0);
254
+
255
+ this.bundles.routes[groupKey] = {
256
+ paths: groupData.routes,
257
+ components: uniqueComponents,
258
+ size: totalSize,
259
+ file: `slice-bundle.${groupKey}.js`
260
+ };
261
+
262
+ console.log(`✓ Bundle ${groupKey}: ${uniqueComponents.length} components, ${(totalSize / 1024).toFixed(1)} KB (${groupData.routes.length} routes)`);
263
+ }
264
+ }
265
+ }
266
+ }
267
+
268
+ // Group remaining routes by category (skip those already handled by MultiRoute)
224
269
  for (const route of this.analysisData.routes) {
225
- const category = this.categorizeRoute(route.path);
226
- if (!routeGroups.has(category)) {
227
- routeGroups.set(category, []);
270
+ // Check if this route is already handled by a MultiRoute group
271
+ const isHandledByMultiRoute = this.analysisData.routeGroups &&
272
+ Array.from(this.analysisData.routeGroups.values()).some(group =>
273
+ group.type === 'multiroute' && group.routes.includes(route.path)
274
+ );
275
+
276
+ if (!isHandledByMultiRoute) {
277
+ const category = this.categorizeRoute(route.path);
278
+ if (!routeGroups.has(category)) {
279
+ routeGroups.set(category, []);
280
+ }
281
+ routeGroups.get(category).push(route);
228
282
  }
229
- routeGroups.get(category).push(route);
230
283
  }
231
284
 
232
285
  // Create bundles for each group
@@ -268,9 +321,19 @@ export default class BundleGenerator {
268
321
  }
269
322
 
270
323
  /**
271
- * Categorizes a route path for grouping
324
+ * Categorizes a route path for grouping, considering MultiRoute context
272
325
  */
273
326
  categorizeRoute(routePath) {
327
+ // Check if this route belongs to a MultiRoute handler
328
+ if (this.analysisData.routeGroups) {
329
+ for (const [groupKey, groupData] of this.analysisData.routeGroups) {
330
+ if (groupData.type === 'multiroute' && groupData.routes.includes(routePath)) {
331
+ return groupKey; // Return the MultiRoute group key
332
+ }
333
+ }
334
+ }
335
+
336
+ // Default categorization
274
337
  const path = routePath.toLowerCase();
275
338
 
276
339
  if (path === '/' || path === '/home') return 'home';
@@ -461,7 +524,7 @@ export default class BundleGenerator {
461
524
  name: comp.name,
462
525
  category: comp.category,
463
526
  categoryType: comp.categoryType,
464
- js: this.cleanJavaScript(jsContent),
527
+ js: this.cleanJavaScript(jsContent, comp.name),
465
528
  externalDependencies: dependencyContents, // Files imported with import statements
466
529
  componentDependencies: Array.from(comp.dependencies), // Other components this one depends on
467
530
  html: htmlContent,
@@ -484,15 +547,28 @@ export default class BundleGenerator {
484
547
  }
485
548
 
486
549
  /**
487
- * Cleans JavaScript code by removing imports/exports
550
+ * Cleans JavaScript code by removing imports/exports and ensuring class is available globally
488
551
  */
489
- cleanJavaScript(code) {
552
+ cleanJavaScript(code, componentName) {
490
553
  // Remove export default
491
554
  code = code.replace(/export\s+default\s+/g, '');
492
555
 
493
556
  // Remove imports (components will already be available)
494
557
  code = code.replace(/import\s+.*?from\s+['"].*?['"];?\s*/g, '');
495
558
 
559
+ // Make sure the class is available globally for bundle evaluation
560
+ // Preserve original customElements.define if it exists
561
+ if (code.includes('customElements.define')) {
562
+ // Add global assignment before customElements.define
563
+ code = code.replace(/customElements\.define\([^;]+\);?\s*$/, `window.${componentName} = ${componentName};\n$&`);
564
+ } else {
565
+ // If no customElements.define found, just assign to global
566
+ code += `\nwindow.${componentName} = ${componentName};`;
567
+ }
568
+
569
+ // Add return statement for bundle evaluation compatibility
570
+ code += `\nreturn ${componentName};`;
571
+
496
572
  return code;
497
573
  }
498
574
 
@@ -45,6 +45,7 @@ export default class DependencyAnalyzer {
45
45
  components: Array.from(this.components.values()),
46
46
  routes: Array.from(this.routes.values()),
47
47
  dependencyGraph: this.dependencyGraph,
48
+ routeGroups: this.routeGroups,
48
49
  metrics
49
50
  };
50
51
  }
@@ -153,8 +154,33 @@ export default class DependencyAnalyzer {
153
154
  CallExpression(path) {
154
155
  const { callee, arguments: args } = path.node;
155
156
 
156
- // slice.build('ComponentName', ...)
157
+ // slice.build('MultiRoute', { routes: [...] })
157
158
  if (
159
+ callee.type === 'MemberExpression' &&
160
+ callee.object.name === 'slice' &&
161
+ callee.property.name === 'build' &&
162
+ args[0]?.type === 'StringLiteral' &&
163
+ args[0].value === 'MultiRoute' &&
164
+ args[1]?.type === 'ObjectExpression'
165
+ ) {
166
+ // Add MultiRoute itself
167
+ dependencies.add('MultiRoute');
168
+
169
+ // Extract routes from MultiRoute props
170
+ const routesProp = args[1].properties.find(p => p.key?.name === 'routes');
171
+ if (routesProp?.value?.type === 'ArrayExpression') {
172
+ routesProp.value.elements.forEach(routeElement => {
173
+ if (routeElement.type === 'ObjectExpression') {
174
+ const componentProp = routeElement.properties.find(p => p.key?.name === 'component');
175
+ if (componentProp?.value?.type === 'StringLiteral') {
176
+ dependencies.add(componentProp.value.value);
177
+ }
178
+ }
179
+ });
180
+ }
181
+ }
182
+ // Regular slice.build() calls
183
+ else if (
158
184
  callee.type === 'MemberExpression' &&
159
185
  callee.object.name === 'slice' &&
160
186
  callee.property.name === 'build' &&
@@ -181,7 +207,7 @@ export default class DependencyAnalyzer {
181
207
  }
182
208
 
183
209
  /**
184
- * Analyzes the routes file
210
+ * Analyzes the routes file and detects route groups
185
211
  */
186
212
  async analyzeRoutes() {
187
213
  if (!await fs.pathExists(this.routesPath)) {
@@ -189,7 +215,7 @@ export default class DependencyAnalyzer {
189
215
  }
190
216
 
191
217
  const content = await fs.readFile(this.routesPath, 'utf-8');
192
-
218
+
193
219
  try {
194
220
  const ast = parse(content, {
195
221
  sourceType: 'module',
@@ -225,6 +251,10 @@ export default class DependencyAnalyzer {
225
251
  }
226
252
  }
227
253
  });
254
+
255
+ // Detect and store route groups based on MultiRoute usage
256
+ this.routeGroups = this.detectRouteGroups();
257
+
228
258
  } catch (error) {
229
259
  console.warn(`⚠️ Error parseando rutas: ${error.message}`);
230
260
  }
@@ -249,6 +279,40 @@ export default class DependencyAnalyzer {
249
279
  }
250
280
  }
251
281
 
282
+ /**
283
+ * Detects route groups based on MultiRoute usage
284
+ */
285
+ detectRouteGroups() {
286
+ const routeGroups = new Map();
287
+
288
+ for (const [componentName, component] of this.components) {
289
+ // Check if component uses MultiRoute
290
+ const hasMultiRoute = Array.from(component.dependencies).includes('MultiRoute');
291
+
292
+ if (hasMultiRoute) {
293
+ // Find all routes that point to this component
294
+ const relatedRoutes = Array.from(this.routes.values())
295
+ .filter(route => route.component === componentName);
296
+
297
+ if (relatedRoutes.length > 1) {
298
+ // Group these routes together
299
+ const groupKey = `multiroute-${componentName}`;
300
+ routeGroups.set(groupKey, {
301
+ component: componentName,
302
+ routes: relatedRoutes.map(r => r.path),
303
+ type: 'multiroute'
304
+ });
305
+
306
+ // Mark component as multiroute handler
307
+ component.isMultiRouteHandler = true;
308
+ component.multiRoutePaths = relatedRoutes.map(r => r.path);
309
+ }
310
+ }
311
+ }
312
+
313
+ return routeGroups;
314
+ }
315
+
252
316
  /**
253
317
  * Gets all dependencies of a component (recursive)
254
318
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slicejs-cli",
3
- "version": "2.7.8",
3
+ "version": "2.7.9",
4
4
  "description": "Command client for developing web applications with Slice.js framework",
5
5
  "main": "client.js",
6
6
  "bin": {