slicejs-web-framework 2.3.5 → 2.4.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.
Files changed (84) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +24 -5
  3. package/Slice/Components/Structural/Controller/Controller.js +156 -154
  4. package/Slice/Components/Structural/Debugger/Debugger.css +619 -619
  5. package/Slice/Components/Structural/Debugger/Debugger.html +72 -72
  6. package/Slice/Components/Structural/Logger/Log.js +10 -10
  7. package/Slice/Components/Structural/StylesManager/StylesManager.js +6 -3
  8. package/Slice/Slice.js +118 -51
  9. package/api/index.js +261 -233
  10. package/api/middleware/securityMiddleware.js +252 -252
  11. package/package.json +37 -37
  12. package/sliceConfig.schema.json +4 -0
  13. package/src/App/index.html +22 -22
  14. package/src/App/index.js +23 -23
  15. package/src/App/style.css +40 -40
  16. package/src/Components/AppComponents/HomePage/HomePage.css +204 -204
  17. package/src/Components/AppComponents/HomePage/HomePage.html +48 -48
  18. package/src/Components/AppComponents/HomePage/HomePage.js +195 -195
  19. package/src/Components/AppComponents/Playground/Playground.css +11 -11
  20. package/src/Components/AppComponents/Playground/Playground.js +111 -111
  21. package/src/Components/Service/FetchManager/FetchManager.js +133 -133
  22. package/src/Components/Service/IndexedDbManager/IndexedDbManager.js +141 -141
  23. package/src/Components/Service/LocalStorageManager/LocalStorageManager.js +45 -45
  24. package/src/Components/Visual/Button/Button.css +47 -47
  25. package/src/Components/Visual/Button/Button.html +5 -5
  26. package/src/Components/Visual/Button/Button.js +92 -92
  27. package/src/Components/Visual/Card/Card.css +68 -68
  28. package/src/Components/Visual/Card/Card.html +7 -7
  29. package/src/Components/Visual/Card/Card.js +107 -107
  30. package/src/Components/Visual/Checkbox/Checkbox.css +87 -87
  31. package/src/Components/Visual/Checkbox/Checkbox.html +8 -8
  32. package/src/Components/Visual/Checkbox/Checkbox.js +86 -86
  33. package/src/Components/Visual/CodeVisualizer/CodeVisualizer.css +129 -129
  34. package/src/Components/Visual/CodeVisualizer/CodeVisualizer.html +3 -3
  35. package/src/Components/Visual/CodeVisualizer/CodeVisualizer.js +259 -259
  36. package/src/Components/Visual/Details/Details.css +70 -70
  37. package/src/Components/Visual/Details/Details.html +9 -9
  38. package/src/Components/Visual/Details/Details.js +76 -76
  39. package/src/Components/Visual/DropDown/DropDown.css +60 -60
  40. package/src/Components/Visual/DropDown/DropDown.html +5 -5
  41. package/src/Components/Visual/DropDown/DropDown.js +63 -63
  42. package/src/Components/Visual/Grid/Grid.css +7 -7
  43. package/src/Components/Visual/Grid/Grid.html +1 -1
  44. package/src/Components/Visual/Grid/Grid.js +57 -57
  45. package/src/Components/Visual/Icon/Icon.css +510 -510
  46. package/src/Components/Visual/Icon/Icon.js +89 -89
  47. package/src/Components/Visual/Icon/slc.json +554 -554
  48. package/src/Components/Visual/Icon/slc.styl +507 -507
  49. package/src/Components/Visual/Icon/slc.svg +1485 -1485
  50. package/src/Components/Visual/Icon/slc.symbol.svg +1058 -1058
  51. package/src/Components/Visual/Input/Input.css +91 -91
  52. package/src/Components/Visual/Input/Input.html +4 -4
  53. package/src/Components/Visual/Input/Input.js +215 -215
  54. package/src/Components/Visual/Layout/Layout.js +49 -49
  55. package/src/Components/Visual/Loading/Loading.css +56 -56
  56. package/src/Components/Visual/Loading/Loading.html +83 -83
  57. package/src/Components/Visual/Loading/Loading.js +38 -38
  58. package/src/Components/Visual/MultiRoute/MultiRoute.js +93 -93
  59. package/src/Components/Visual/Navbar/Navbar.css +115 -115
  60. package/src/Components/Visual/Navbar/Navbar.html +44 -44
  61. package/src/Components/Visual/Navbar/Navbar.js +141 -141
  62. package/src/Components/Visual/NotFound/NotFound.css +116 -116
  63. package/src/Components/Visual/NotFound/NotFound.html +23 -23
  64. package/src/Components/Visual/NotFound/NotFound.js +16 -16
  65. package/src/Components/Visual/Route/Route.js +93 -93
  66. package/src/Components/Visual/Select/Select.css +84 -84
  67. package/src/Components/Visual/Select/Select.html +8 -8
  68. package/src/Components/Visual/Select/Select.js +195 -195
  69. package/src/Components/Visual/Switch/Switch.css +76 -76
  70. package/src/Components/Visual/Switch/Switch.html +8 -8
  71. package/src/Components/Visual/Switch/Switch.js +102 -102
  72. package/src/Components/Visual/TreeItem/TreeItem.css +36 -36
  73. package/src/Components/Visual/TreeItem/TreeItem.html +1 -1
  74. package/src/Components/Visual/TreeItem/TreeItem.js +126 -126
  75. package/src/Components/Visual/TreeView/TreeView.css +8 -8
  76. package/src/Components/Visual/TreeView/TreeView.html +1 -1
  77. package/src/Components/Visual/TreeView/TreeView.js +48 -48
  78. package/src/Styles/sliceStyles.css +34 -34
  79. package/src/Themes/Dark.css +42 -42
  80. package/src/Themes/Light.css +31 -31
  81. package/src/Themes/Slice.css +47 -47
  82. package/src/routes.js +15 -15
  83. package/src/sliceConfig.json +8 -3
  84. package/src/testing.js +887 -887
package/api/index.js CHANGED
@@ -1,233 +1,261 @@
1
- // api/index.js - Seguridad automática sin configuración
2
- import express from 'express';
3
- import path from 'path';
4
- import fs from 'fs';
5
- import { fileURLToPath } from 'url';
6
- import { dirname } from 'path';
7
- import {
8
- securityMiddleware,
9
- sliceFrameworkProtection,
10
- suspiciousRequestLogger
11
- } from './middleware/securityMiddleware.js';
12
-
13
- const __filename = fileURLToPath(import.meta.url);
14
- const __dirname = dirname(__filename);
15
- import sliceConfig from '../src/sliceConfig.json' with { type: 'json' };
16
-
17
- let server;
18
- const app = express();
19
-
20
- // Parsear argumentos de línea de comandos
21
- const args = process.argv.slice(2);
22
-
23
- // Siempre usar development mode (ignorar argumentos de production)
24
- const runMode = 'development';
25
- const folderDeployed = 'src';
26
-
27
- // Obtener puerto desde sliceConfig.json, con fallback a process.env.PORT
28
- const PORT = sliceConfig.server?.port || process.env.PORT || 3001;
29
-
30
- // ==============================================
31
- // MIDDLEWARES DE SEGURIDAD (APLICAR PRIMERO)
32
- // ==============================================
33
-
34
- // 1. Logger de peticiones sospechosas (solo observación, no bloquea)
35
- app.use(suspiciousRequestLogger());
36
-
37
- // 2. Protección del framework - TOTALMENTE AUTOMÁTICA
38
- // Detecta automáticamente el dominio desde los headers
39
- // Funciona en localhost, IP, y cualquier dominio
40
- app.use(sliceFrameworkProtection());
41
-
42
- // 3. Middleware de seguridad general
43
- app.use(securityMiddleware({
44
- allowedExtensions: [
45
- '.js', '.css', '.html', '.json',
46
- '.svg', '.png', '.jpg', '.jpeg', '.gif',
47
- '.woff', '.woff2', '.ttf', '.ico'
48
- ],
49
- blockedPaths: [
50
- '/node_modules',
51
- '/package.json',
52
- '/package-lock.json',
53
- '/.env',
54
- '/.git',
55
- '/api/middleware'
56
- ],
57
- allowPublicAssets: true
58
- }));
59
-
60
- // ==============================================
61
- // MIDDLEWARES DE APLICACIÓN
62
- // ==============================================
63
-
64
- // Middleware global para archivos JavaScript con MIME types correctos
65
- app.use((req, res, next) => {
66
- if (req.path.endsWith('.js')) {
67
- // Forzar headers correctos para TODOS los archivos .js
68
- res.setHeader('Content-Type', 'application/javascript; charset=utf-8');
69
- }
70
- next();
71
- });
72
-
73
- // Middleware para parsear JSON y formularios
74
- app.use(express.json());
75
- app.use(express.urlencoded({ extended: true }));
76
-
77
- // Configurar headers de CORS
78
- app.use((req, res, next) => {
79
- res.header('Access-Control-Allow-Origin', '*');
80
- res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
81
- res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
82
-
83
- if (req.method === 'OPTIONS') {
84
- res.sendStatus(200);
85
- } else {
86
- next();
87
- }
88
- });
89
-
90
- // ==============================================
91
- // ARCHIVOS ESTÁTICOS (DESPUÉS DE SEGURIDAD)
92
- // ==============================================
93
-
94
- // Función de utilidad para verificar si existe el directorio bundles
95
- function bundlesDirectoryExists() {
96
- const bundleDir = path.join(__dirname, `../${folderDeployed}`, 'bundles');
97
- return fs.existsSync(bundleDir) && fs.statSync(bundleDir).isDirectory();
98
- }
99
-
100
- // Middleware personalizado para archivos de bundles con MIME types correctos
101
- // ⚠️ DEBE IR ANTES del middleware general para tener prioridad
102
- app.use('/bundles/', (req, res, next) => {
103
- // Verificar si existe el directorio bundles
104
- if (!bundlesDirectoryExists()) {
105
- console.log(`ℹ️ Bundles directory does not exist, skipping bundle processing`);
106
- return next(); // Continuar con el siguiente middleware
107
- }
108
-
109
- // Solo procesar archivos .js
110
- if (req.path.endsWith('.js')) {
111
- const filePath = path.join(__dirname, `../${folderDeployed}`, 'bundles', req.path);
112
- console.log(`📂 Processing bundle: ${req.path} -> ${filePath}`);
113
-
114
- // Verificar que el archivo existe
115
- if (fs.existsSync(filePath)) {
116
- try {
117
- // Leer y servir el archivo con headers correctos
118
- const fileContent = fs.readFileSync(filePath, 'utf8');
119
- res.setHeader('Content-Type', 'application/javascript; charset=utf-8');
120
- res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); // No cachear para permitir actualizaciones en tiempo real
121
- res.setHeader('Pragma', 'no-cache');
122
- res.setHeader('Expires', '0');
123
- console.log(`✅ Serving bundle: ${req.path} (${fileContent.length} bytes, ${Buffer.byteLength(fileContent, 'utf8')} bytes UTF-8)`);
124
- return res.send(fileContent);
125
- } catch (error) {
126
- console.log(`❌ Error reading bundle file: ${error.message}`);
127
- return res.status(500).send('Error reading bundle file');
128
- }
129
- } else {
130
- console.log(`❌ Bundle file not found: ${filePath}`);
131
- // Listar archivos disponibles para debugging
132
- try {
133
- const bundleDir = path.join(__dirname, `../${folderDeployed}`, 'bundles');
134
- if (fs.existsSync(bundleDir)) {
135
- const files = fs.readdirSync(bundleDir);
136
- console.log(`📁 Available files in bundles: ${files.join(', ')}`);
137
- }
138
- } catch (e) {
139
- console.log(`❌ Could not list bundle directory: ${e.message}`);
140
- }
141
- return res.status(404).send('Bundle file not found');
142
- }
143
- }
144
-
145
- // Para archivos no .js, continuar con el middleware estático normal
146
- next();
147
- });
148
-
149
- // Servir otros archivos de bundles (CSS, etc.) con el middleware estático normal
150
- // Solo si existe el directorio bundles
151
- if (bundlesDirectoryExists()) {
152
- app.use('/bundles/', express.static(path.join(__dirname, `../${folderDeployed}`, 'bundles')));
153
- console.log(`📦 Bundles directory found, serving static files`);
154
- } else {
155
- console.log(`ℹ️ Bundles directory not found, skipping static bundle serving`);
156
- }
157
-
158
- // Servir framework Slice.js
159
- app.use('/Slice/', express.static(path.join(__dirname, '..', 'node_modules', 'slicejs-web-framework', 'Slice')));
160
-
161
- // Servir archivos estáticos del proyecto
162
- app.use(express.static(path.join(__dirname, `../${folderDeployed}`)));
163
-
164
- // ==============================================
165
- // RUTAS DE API
166
- // ==============================================
167
-
168
- // Ruta de ejemplo para API
169
- app.get('/api/status', (req, res) => {
170
- res.json({
171
- status: 'ok',
172
- mode: runMode,
173
- folder: folderDeployed,
174
- timestamp: new Date().toISOString(),
175
- framework: 'Slice.js',
176
- version: '2.0.0',
177
- security: {
178
- enabled: true,
179
- mode: 'automatic',
180
- description: 'Zero-config security - works with any domain'
181
- }
182
- });
183
- });
184
-
185
-
186
- // ==============================================
187
- // SPA FALLBACK
188
- // ==============================================
189
-
190
- // SPA fallback - servir index.html para rutas no encontradas
191
- app.get('*', (req, res) => {
192
- const indexPath = path.join(__dirname, `../${folderDeployed}`, "App", 'index.html');
193
- res.sendFile(indexPath, (err) => {
194
- if (err) {
195
- res.status(404).send(`
196
- <h1>404 - Page Not Found</h1>
197
- <p>The requested file could not be found in /${folderDeployed}</p>
198
- <p>Make sure you've run the appropriate build command:</p>
199
- <ul>
200
- <li>For development: Files should be in /src</li>
201
- <li>For production: Run "npm run slice:build" first</li>
202
- </ul>
203
- `);
204
- }
205
- });
206
- });
207
-
208
- // ==============================================
209
- // INICIO DEL SERVIDOR
210
- // ==============================================
211
-
212
- function startServer() {
213
- server = app.listen(PORT, () => {
214
- console.log(`🔒 Security middleware: active (zero-config, automatic)`);
215
- console.log(`🚀 Slice.js server running on port ${PORT}`);
216
- });
217
- }
218
-
219
- // Manejar cierre del proceso
220
- process.on('SIGINT', () => {
221
- console.log('\n🛑 Slice server stopped');
222
- process.exit(0);
223
- });
224
-
225
- process.on('SIGTERM', () => {
226
- console.log('\n🛑 Server terminated');
227
- process.exit(0);
228
- });
229
-
230
- // Iniciar servidor
231
- startServer();
232
-
233
- export default app;
1
+ // api/index.js - Seguridad automática sin configuración
2
+ import express from 'express';
3
+ import path from 'path';
4
+ import fs from 'fs';
5
+ import { fileURLToPath } from 'url';
6
+ import { dirname } from 'path';
7
+ import {
8
+ securityMiddleware,
9
+ sliceFrameworkProtection,
10
+ suspiciousRequestLogger
11
+ } from './middleware/securityMiddleware.js';
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = dirname(__filename);
15
+ import sliceConfig from '../src/sliceConfig.json' with { type: 'json' };
16
+
17
+ let server;
18
+ const app = express();
19
+
20
+ // Parsear argumentos de línea de comandos
21
+ const args = process.argv.slice(2);
22
+
23
+ const runMode = process.env.NODE_ENV === 'production' ? 'production' : 'development';
24
+ const folderDeployed = runMode === 'production' ? 'dist' : 'src';
25
+
26
+ // Obtener puerto desde process.env.PORT con fallback a sliceConfig.json
27
+ const PORT = process.env.PORT || sliceConfig.server?.port || 3001;
28
+
29
+ // ==============================================
30
+ // MIDDLEWARES DE SEGURIDAD (APLICAR PRIMERO)
31
+ // ==============================================
32
+
33
+ // 1. Logger de peticiones sospechosas (solo observación, no bloquea)
34
+ app.use(suspiciousRequestLogger());
35
+
36
+ // 2. Protección del framework - TOTALMENTE AUTOMÁTICA
37
+ // Detecta automáticamente el dominio desde los headers
38
+ // Funciona en localhost, IP, y cualquier dominio
39
+ app.use(sliceFrameworkProtection());
40
+
41
+ // 3. Middleware de seguridad general
42
+ app.use(securityMiddleware({
43
+ allowedExtensions: [
44
+ '.js', '.css', '.html', '.json',
45
+ '.svg', '.png', '.jpg', '.jpeg', '.gif',
46
+ '.woff', '.woff2', '.ttf', '.ico'
47
+ ],
48
+ blockedPaths: [
49
+ '/node_modules',
50
+ '/package.json',
51
+ '/package-lock.json',
52
+ '/.env',
53
+ '/.git',
54
+ '/api/middleware'
55
+ ],
56
+ allowPublicAssets: true
57
+ }));
58
+
59
+ // ==============================================
60
+ // MIDDLEWARES DE APLICACIÓN
61
+ // ==============================================
62
+
63
+ // Middleware global para archivos JavaScript con MIME types correctos
64
+ app.use((req, res, next) => {
65
+ if (req.path.endsWith('.js')) {
66
+ // Forzar headers correctos para TODOS los archivos .js
67
+ res.setHeader('Content-Type', 'application/javascript; charset=utf-8');
68
+ }
69
+ next();
70
+ });
71
+
72
+ // Middleware para parsear JSON y formularios
73
+ app.use(express.json());
74
+ app.use(express.urlencoded({ extended: true }));
75
+
76
+ // Configurar headers de CORS
77
+ app.use((req, res, next) => {
78
+ res.header('Access-Control-Allow-Origin', '*');
79
+ res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
80
+ res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
81
+
82
+ if (req.method === 'OPTIONS') {
83
+ res.sendStatus(200);
84
+ } else {
85
+ next();
86
+ }
87
+ });
88
+
89
+ // ==============================================
90
+ // ARCHIVOS ESTÁTICOS (DESPUÉS DE SEGURIDAD)
91
+ // ==============================================
92
+
93
+ if (runMode === 'production') {
94
+ app.get('/Slice/Slice.js', (req, res) => {
95
+ const slicePath = path.join(__dirname, '..', 'node_modules', 'slicejs-web-framework', 'Slice', 'Slice.js');
96
+ if (fs.existsSync(slicePath)) {
97
+ res.setHeader('Content-Type', 'application/javascript; charset=utf-8');
98
+ return res.send(fs.readFileSync(slicePath, 'utf8'));
99
+ }
100
+ return res.status(404).send('Slice.js not found');
101
+ });
102
+
103
+ app.use('/Slice', (req, res) => res.status(404).send('Not found'));
104
+ app.use('/Components', (req, res) => res.status(404).send('Not found'));
105
+ }
106
+
107
+ // Middleware personalizado para archivos de bundles con MIME types correctos
108
+ // ⚠️ DEBE IR ANTES del middleware general para tener prioridad
109
+ app.use('/bundles/', (req, res, next) => {
110
+ // Solo procesar archivos .js
111
+ if (req.path.endsWith('.js')) {
112
+ const filePath = path.join(__dirname, `../${folderDeployed}`, 'bundles', req.path);
113
+ console.log(`📂 Processing bundle: ${req.path} -> ${filePath}`);
114
+
115
+ // Verificar que el archivo existe
116
+ if (fs.existsSync(filePath)) {
117
+ try {
118
+ // Leer y servir el archivo con headers correctos
119
+ const fileContent = fs.readFileSync(filePath, 'utf8');
120
+ res.setHeader('Content-Type', 'application/javascript; charset=utf-8');
121
+ res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); // No cachear para permitir actualizaciones en tiempo real
122
+ res.setHeader('Pragma', 'no-cache');
123
+ res.setHeader('Expires', '0');
124
+ console.log(`✅ Serving bundle: ${req.path} (${fileContent.length} bytes, ${Buffer.byteLength(fileContent, 'utf8')} bytes UTF-8)`);
125
+ return res.send(fileContent);
126
+ } catch (error) {
127
+ console.log(`❌ Error reading bundle file: ${error.message}`);
128
+ return res.status(500).send('Error reading bundle file');
129
+ }
130
+ } else {
131
+ console.log(`❌ Bundle file not found: ${filePath}`);
132
+ return res.status(404).send('Bundle file not found');
133
+ }
134
+ }
135
+
136
+ // Para archivos no .js, continuar con el middleware estático normal
137
+ next();
138
+ });
139
+
140
+ // Servir otros archivos de bundles (JSON, CSS, etc.) con el middleware estático normal
141
+ app.use('/bundles/', express.static(path.join(__dirname, `../${folderDeployed}`, 'bundles')));
142
+ console.log(`📦 Serving bundles from /${folderDeployed}/bundles`);
143
+
144
+ // Servir framework Slice.js (solo development)
145
+ if (runMode === 'development') {
146
+ app.use('/Slice/', express.static(path.join(__dirname, '..', 'node_modules', 'slicejs-web-framework', 'Slice')));
147
+ }
148
+
149
+ // Servir archivos estáticos del proyecto con allowlist
150
+ const publicFolders = Array.isArray(sliceConfig.publicFolders) ? sliceConfig.publicFolders : [];
151
+ const normalizedPublicFolders = publicFolders
152
+ .filter((entry) => typeof entry === 'string')
153
+ .map((entry) => entry.trim())
154
+ .filter((entry) => entry.length > 0)
155
+ .map((entry) => (entry.startsWith('/') ? entry : `/${entry}`));
156
+
157
+ if (runMode === 'development') {
158
+ app.use(express.static(path.join(__dirname, `../${folderDeployed}`)));
159
+ } else {
160
+ app.use('/App', express.static(path.join(__dirname, `../${folderDeployed}`, 'App')));
161
+ app.get('/manifest.json', (req, res) => {
162
+ const manifestPath = path.join(__dirname, `../${folderDeployed}`, 'manifest.json');
163
+ if (fs.existsSync(manifestPath)) {
164
+ res.setHeader('Content-Type', 'application/json; charset=utf-8');
165
+ return res.send(fs.readFileSync(manifestPath, 'utf8'));
166
+ }
167
+ return res.status(404).send('manifest.json not found');
168
+ });
169
+ app.get('/service-worker.js', (req, res) => {
170
+ const workerPath = path.join(__dirname, `../${folderDeployed}`, 'service-worker.js');
171
+ if (fs.existsSync(workerPath)) {
172
+ res.setHeader('Content-Type', 'application/javascript; charset=utf-8');
173
+ return res.send(fs.readFileSync(workerPath, 'utf8'));
174
+ }
175
+ return res.status(404).send('service-worker.js not found');
176
+ });
177
+ app.get('/routes.js', (req, res) => {
178
+ const routesPath = path.join(__dirname, `../${folderDeployed}`, 'routes.js');
179
+ if (fs.existsSync(routesPath)) {
180
+ res.setHeader('Content-Type', 'application/javascript; charset=utf-8');
181
+ return res.send(fs.readFileSync(routesPath, 'utf8'));
182
+ }
183
+ return res.status(404).send('routes.js not found');
184
+ });
185
+ for (const folder of normalizedPublicFolders) {
186
+ app.use(folder, express.static(path.join(__dirname, `../${folderDeployed}`, folder)));
187
+ }
188
+ app.use('/bundles/', express.static(path.join(__dirname, `../${folderDeployed}`, 'bundles')));
189
+ app.use('/dist/', express.static(path.join(__dirname, '..', 'dist')));
190
+ }
191
+
192
+ // ==============================================
193
+ // RUTAS DE API
194
+ // ==============================================
195
+
196
+ // Ruta de ejemplo para API
197
+ app.get('/api/status', (req, res) => {
198
+ res.json({
199
+ status: 'ok',
200
+ mode: runMode,
201
+ folder: folderDeployed,
202
+ timestamp: new Date().toISOString(),
203
+ framework: 'Slice.js',
204
+ version: '2.0.0',
205
+ security: {
206
+ enabled: true,
207
+ mode: 'automatic',
208
+ description: 'Zero-config security - works with any domain'
209
+ }
210
+ });
211
+ });
212
+
213
+
214
+ // ==============================================
215
+ // SPA FALLBACK
216
+ // ==============================================
217
+
218
+ // SPA fallback - servir index.html para rutas no encontradas
219
+ app.get('*', (req, res) => {
220
+ const indexPath = path.join(__dirname, `../${folderDeployed}`, "App", 'index.html');
221
+ res.sendFile(indexPath, (err) => {
222
+ if (err) {
223
+ res.status(404).send(`
224
+ <h1>404 - Page Not Found</h1>
225
+ <p>The requested file could not be found in /${folderDeployed}</p>
226
+ <p>Make sure you've run the appropriate build command:</p>
227
+ <ul>
228
+ <li>For development: Files should be in /src</li>
229
+ <li>For production: Run "npm run slice:build" first</li>
230
+ </ul>
231
+ `);
232
+ }
233
+ });
234
+ });
235
+
236
+ // ==============================================
237
+ // INICIO DEL SERVIDOR
238
+ // ==============================================
239
+
240
+ function startServer() {
241
+ server = app.listen(PORT, () => {
242
+ console.log(`🔒 Security middleware: active (zero-config, automatic)`);
243
+ console.log(`🚀 Slice.js server running on port ${PORT}`);
244
+ });
245
+ }
246
+
247
+ // Manejar cierre del proceso
248
+ process.on('SIGINT', () => {
249
+ console.log('\n🛑 Slice server stopped');
250
+ process.exit(0);
251
+ });
252
+
253
+ process.on('SIGTERM', () => {
254
+ console.log('\n🛑 Server terminated');
255
+ process.exit(0);
256
+ });
257
+
258
+ // Iniciar servidor
259
+ startServer();
260
+
261
+ export default app;