slicejs-web-framework 2.0.1 → 2.1.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.
@@ -276,10 +276,126 @@ export default class Controller {
276
276
  return usedProps;
277
277
  }
278
278
 
279
- destroyComponent(component) {
280
- const sliceId = component.sliceId;
281
- this.activeComponents.delete(sliceId);
282
- component.remove();
279
+ /**
280
+ * Destruye uno o múltiples componentes
281
+ * @param {HTMLElement|Array<HTMLElement>|string|Array<string>} components
282
+ * - Componente individual (HTMLElement)
283
+ * - Array de componentes
284
+ * - sliceId individual (string)
285
+ * - Array de sliceIds
286
+ * @returns {number} Cantidad de componentes destruidos
287
+ */
288
+ destroyComponent(components) {
289
+ // Normalizar entrada a array
290
+ const toDestroy = Array.isArray(components) ? components : [components];
291
+ let destroyedCount = 0;
292
+
293
+ for (const item of toDestroy) {
294
+ let component = null;
295
+
296
+ // Si es string, buscar el componente por sliceId
297
+ if (typeof item === 'string') {
298
+ component = this.activeComponents.get(item);
299
+
300
+ if (!component) {
301
+ slice.logger.logWarning('Controller', `Component with sliceId "${item}" not found`);
302
+ continue;
303
+ }
304
+ }
305
+ // Si es un componente directamente
306
+ else if (item && item.sliceId) {
307
+ component = item;
308
+ }
309
+ else {
310
+ slice.logger.logWarning('Controller', `Invalid component or sliceId provided to destroyComponent`);
311
+ continue;
312
+ }
313
+
314
+ // Ejecutar hook beforeDestroy si existe
315
+ if (typeof component.beforeDestroy === 'function') {
316
+ try {
317
+ component.beforeDestroy();
318
+ } catch (error) {
319
+ slice.logger.logError('Controller', `Error in beforeDestroy for ${component.sliceId}`, error);
320
+ }
321
+ }
322
+
323
+ // Eliminar del mapa de componentes activos
324
+ this.activeComponents.delete(component.sliceId);
325
+
326
+ // Remover del DOM si está conectado
327
+ if (component.isConnected) {
328
+ component.remove();
329
+ }
330
+
331
+ destroyedCount++;
332
+ }
333
+
334
+ if (destroyedCount > 0) {
335
+ slice.logger.logInfo('Controller', `Destroyed ${destroyedCount} component(s)`);
336
+ }
337
+
338
+ return destroyedCount;
339
+ }
340
+
341
+ /**
342
+ * Destruye todos los componentes Slice dentro de un contenedor
343
+ * @param {HTMLElement} container - Elemento contenedor
344
+ * @returns {number} Cantidad de componentes destruidos
345
+ */
346
+ destroyByContainer(container) {
347
+ if (!container) {
348
+ slice.logger.logWarning('Controller', 'No container provided to destroyByContainer');
349
+ return 0;
350
+ }
351
+
352
+ // Buscar todos los elementos que sean componentes Slice
353
+ const sliceComponents = container.querySelectorAll('[slice-id]');
354
+ const sliceIdsToDestroy = [];
355
+
356
+ sliceComponents.forEach(element => {
357
+ const sliceId = element.getAttribute('slice-id') || element.sliceId;
358
+ if (sliceId && this.activeComponents.has(sliceId)) {
359
+ sliceIdsToDestroy.push(sliceId);
360
+ }
361
+ });
362
+
363
+ // Destruir usando el método principal
364
+ const count = this.destroyComponent(sliceIdsToDestroy);
365
+
366
+ if (count > 0) {
367
+ slice.logger.logInfo('Controller', `Destroyed ${count} component(s) from container`);
368
+ }
369
+
370
+ return count;
371
+ }
372
+
373
+ /**
374
+ * Destruye componentes cuyos sliceId coincidan con un patrón
375
+ * @param {string|RegExp} pattern - Patrón a buscar (string o expresión regular)
376
+ * @returns {number} Cantidad de componentes destruidos
377
+ */
378
+ destroyByPattern(pattern) {
379
+ const componentsToDestroy = [];
380
+
381
+ // Convertir string a RegExp si es necesario
382
+ const regex = pattern instanceof RegExp ? pattern : new RegExp(pattern);
383
+
384
+ // Buscar componentes que coincidan con el patrón
385
+ for (const [sliceId, component] of this.activeComponents) {
386
+ if (regex.test(sliceId)) {
387
+ componentsToDestroy.push(component);
388
+ }
389
+ }
390
+
391
+ // Destruir usando el método principal
392
+ const count = this.destroyComponent(componentsToDestroy);
393
+
394
+ if (count > 0) {
395
+ slice.logger.logInfo('Controller', `Destroyed ${count} component(s) matching pattern: ${pattern}`);
396
+ }
397
+
398
+ return count;
283
399
  }
284
400
  }
285
401
 
package/Slice/Slice.js CHANGED
@@ -11,7 +11,6 @@ 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;
15
14
  }
16
15
 
17
16
  async getClass(module) {
@@ -24,7 +23,7 @@ export default class Slice {
24
23
  }
25
24
 
26
25
  isProduction(){
27
- return this.productionConfig.enabled;
26
+ return true;
28
27
  }
29
28
 
30
29
  getComponent(componentSliceId) {
package/api/index.js CHANGED
@@ -14,35 +14,20 @@ const app = express();
14
14
 
15
15
  // Parsear argumentos de línea de comandos
16
16
  const args = process.argv.slice(2);
17
- let runMode = 'development'; // Default
18
17
 
19
- // Detectar modo basado en argumentos
20
- if (args.includes('--production') || args.includes('--prod')) {
21
- runMode = 'production';
22
- } else if (args.includes('--development') || args.includes('--dev')) {
23
- runMode = 'development';
24
- }
25
-
26
- // También mantener compatibilidad con NODE_ENV como fallback
27
- if (!args.length) {
28
- const NODE_ENV = process.env.NODE_ENV || 'development';
29
- runMode = NODE_ENV === 'production' ? 'production' : 'development';
30
- }
18
+ // Siempre usar development mode (ignorar argumentos de production)
19
+ const runMode = 'development';
20
+ const folderDeployed = 'src';
31
21
 
32
22
  // Obtener puerto desde sliceConfig.json, con fallback a process.env.PORT
33
23
  const PORT = sliceConfig.server?.port || process.env.PORT || 3001;
34
24
 
35
- // Determinar directorio a servir basado en argumentos
36
- let folderDeployed;
37
- if (runMode === 'production') {
38
- folderDeployed = 'dist';
39
- } else {
40
- folderDeployed = 'src';
41
- }
42
-
43
25
  console.log(`🚀 Starting Slice.js server in ${runMode} mode`);
44
26
  console.log(`📁 Serving files from: /${folderDeployed}`);
45
27
 
28
+ app.use('/Slice/', express.static(path.join(__dirname, '..', 'node_modules', 'slicejs-web-framework', 'Slice')));
29
+
30
+
46
31
  // Middleware para servir archivos estáticos
47
32
  app.use(express.static(path.join(__dirname, `../${folderDeployed}`)));
48
33
 
@@ -77,7 +62,7 @@ app.get('/api/status', (req, res) => {
77
62
 
78
63
  // SPA fallback - servir index.html para rutas no encontradas
79
64
  app.get('*', (req, res) => {
80
- const indexPath = path.join(__dirname, `../${folderDeployed}`, 'index.html');
65
+ const indexPath = path.join(__dirname, `../${folderDeployed}`,"App", 'index.html');
81
66
  res.sendFile(indexPath, (err) => {
82
67
  if (err) {
83
68
  res.status(404).send(`
@@ -95,24 +80,29 @@ app.get('*', (req, res) => {
95
80
 
96
81
  function startServer() {
97
82
  server = app.listen(PORT, () => {
98
- console.log(`✅ Server running at http://localhost:${PORT}`);
99
- console.log(`📂 Mode: ${runMode} (serving from /${folderDeployed})`);
100
-
101
- if (runMode === 'development') {
102
- console.log('🔄 Development mode: Changes in /src will require server restart');
103
- } else {
104
- console.log('⚡ Production mode: Serving optimized files from /dist');
105
- }
83
+ // Limpiar consola y mostrar banner de inicio
84
+ console.clear();
85
+ showWelcomeBanner();
106
86
 
107
- console.log('🛑 Press Ctrl+C to stop');
108
- console.log('\n💡 Available commands:');
109
- console.log(' - Development: npm run slice:dev');
110
- console.log(' - Production: npm run slice:start');
111
- console.log(' - Build: npm run slice:build');
87
+ // Información del servidor
88
+ console.log(`✅ Server running at ${'\x1b[36m'}http://localhost:${PORT}${'\x1b[0m'}`);
89
+ console.log(`📂 Mode: ${'\x1b[32m'}${runMode}${'\x1b[0m'} (serving from ${'\x1b[33m'}/${folderDeployed}${'\x1b[0m'})`);
90
+ console.log(`🔄 ${'\x1b[32m'}Development mode${'\x1b[0m'}: Changes in /src are served instantly`);
91
+ console.log(`🛑 Press ${'\x1b[31m'}Ctrl+C${'\x1b[0m'} to stop\n`);
112
92
  });
113
93
 
114
- // Siempre mostrar menú interactivo
115
- setTimeout(showInteractiveMenu, 1000);
94
+ // Mostrar menú interactivo después de un momento
95
+ setTimeout(showInteractiveMenu, 1500);
96
+ }
97
+
98
+ function showWelcomeBanner() {
99
+ const banner = `
100
+ ${'\x1b[36m'}╔══════════════════════════════════════════════════╗${'\x1b[0m'}
101
+ ${'\x1b[36m'}║${'\x1b[0m'} ${'\x1b[1m'}🍰 SLICE.JS SERVER${'\x1b[0m'} ${'\x1b[36m'}║${'\x1b[0m'}
102
+ ${'\x1b[36m'}║${'\x1b[0m'} ${'\x1b[90m'}Development Environment${'\x1b[0m'} ${'\x1b[36m'}║${'\x1b[0m'}
103
+ ${'\x1b[36m'}╚══════════════════════════════════════════════════╝${'\x1b[0m'}
104
+ `;
105
+ console.log(banner);
116
106
  }
117
107
 
118
108
  async function showInteractiveMenu() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slicejs-web-framework",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "description": "",
5
5
  "engines": {
6
6
  "node": ">=20"