slicejs-web-framework 2.3.5 → 2.4.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.
- package/LICENSE +21 -21
- package/README.md +24 -5
- package/Slice/Components/Structural/Controller/Controller.js +156 -154
- package/Slice/Components/Structural/Debugger/Debugger.css +619 -619
- package/Slice/Components/Structural/Debugger/Debugger.html +72 -72
- package/Slice/Components/Structural/Logger/Log.js +10 -10
- package/Slice/Components/Structural/StylesManager/StylesManager.js +6 -3
- package/Slice/Slice.js +111 -51
- package/api/index.js +261 -233
- package/api/middleware/securityMiddleware.js +252 -252
- package/package.json +37 -37
- package/sliceConfig.schema.json +4 -0
- package/src/App/index.html +22 -22
- package/src/App/index.js +23 -23
- package/src/App/style.css +40 -40
- package/src/Components/AppComponents/HomePage/HomePage.css +204 -204
- package/src/Components/AppComponents/HomePage/HomePage.html +48 -48
- package/src/Components/AppComponents/HomePage/HomePage.js +195 -195
- package/src/Components/AppComponents/Playground/Playground.css +11 -11
- package/src/Components/AppComponents/Playground/Playground.js +111 -111
- package/src/Components/Service/FetchManager/FetchManager.js +133 -133
- package/src/Components/Service/IndexedDbManager/IndexedDbManager.js +141 -141
- package/src/Components/Service/LocalStorageManager/LocalStorageManager.js +45 -45
- package/src/Components/Visual/Button/Button.css +47 -47
- package/src/Components/Visual/Button/Button.html +5 -5
- package/src/Components/Visual/Button/Button.js +92 -92
- package/src/Components/Visual/Card/Card.css +68 -68
- package/src/Components/Visual/Card/Card.html +7 -7
- package/src/Components/Visual/Card/Card.js +107 -107
- package/src/Components/Visual/Checkbox/Checkbox.css +87 -87
- package/src/Components/Visual/Checkbox/Checkbox.html +8 -8
- package/src/Components/Visual/Checkbox/Checkbox.js +86 -86
- package/src/Components/Visual/CodeVisualizer/CodeVisualizer.css +129 -129
- package/src/Components/Visual/CodeVisualizer/CodeVisualizer.html +3 -3
- package/src/Components/Visual/CodeVisualizer/CodeVisualizer.js +259 -259
- package/src/Components/Visual/Details/Details.css +70 -70
- package/src/Components/Visual/Details/Details.html +9 -9
- package/src/Components/Visual/Details/Details.js +76 -76
- package/src/Components/Visual/DropDown/DropDown.css +60 -60
- package/src/Components/Visual/DropDown/DropDown.html +5 -5
- package/src/Components/Visual/DropDown/DropDown.js +63 -63
- package/src/Components/Visual/Grid/Grid.css +7 -7
- package/src/Components/Visual/Grid/Grid.html +1 -1
- package/src/Components/Visual/Grid/Grid.js +57 -57
- package/src/Components/Visual/Icon/Icon.css +510 -510
- package/src/Components/Visual/Icon/Icon.js +89 -89
- package/src/Components/Visual/Icon/slc.json +554 -554
- package/src/Components/Visual/Icon/slc.styl +507 -507
- package/src/Components/Visual/Icon/slc.svg +1485 -1485
- package/src/Components/Visual/Icon/slc.symbol.svg +1058 -1058
- package/src/Components/Visual/Input/Input.css +91 -91
- package/src/Components/Visual/Input/Input.html +4 -4
- package/src/Components/Visual/Input/Input.js +215 -215
- package/src/Components/Visual/Layout/Layout.js +49 -49
- package/src/Components/Visual/Loading/Loading.css +56 -56
- package/src/Components/Visual/Loading/Loading.html +83 -83
- package/src/Components/Visual/Loading/Loading.js +38 -38
- package/src/Components/Visual/MultiRoute/MultiRoute.js +93 -93
- package/src/Components/Visual/Navbar/Navbar.css +115 -115
- package/src/Components/Visual/Navbar/Navbar.html +44 -44
- package/src/Components/Visual/Navbar/Navbar.js +141 -141
- package/src/Components/Visual/NotFound/NotFound.css +116 -116
- package/src/Components/Visual/NotFound/NotFound.html +23 -23
- package/src/Components/Visual/NotFound/NotFound.js +16 -16
- package/src/Components/Visual/Route/Route.js +93 -93
- package/src/Components/Visual/Select/Select.css +84 -84
- package/src/Components/Visual/Select/Select.html +8 -8
- package/src/Components/Visual/Select/Select.js +195 -195
- package/src/Components/Visual/Switch/Switch.css +76 -76
- package/src/Components/Visual/Switch/Switch.html +8 -8
- package/src/Components/Visual/Switch/Switch.js +102 -102
- package/src/Components/Visual/TreeItem/TreeItem.css +36 -36
- package/src/Components/Visual/TreeItem/TreeItem.html +1 -1
- package/src/Components/Visual/TreeItem/TreeItem.js +126 -126
- package/src/Components/Visual/TreeView/TreeView.css +8 -8
- package/src/Components/Visual/TreeView/TreeView.html +1 -1
- package/src/Components/Visual/TreeView/TreeView.js +48 -48
- package/src/Styles/sliceStyles.css +34 -34
- package/src/Themes/Dark.css +42 -42
- package/src/Themes/Light.css +31 -31
- package/src/Themes/Slice.css +47 -47
- package/src/routes.js +15 -15
- package/src/sliceConfig.json +8 -3
- 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
|
-
|
|
24
|
-
const
|
|
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
|
-
'/package.json',
|
|
52
|
-
'
|
|
53
|
-
'/.
|
|
54
|
-
'
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
app.use(express.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
res.header('Access-Control-Allow-
|
|
80
|
-
res.header('Access-Control-Allow-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
//
|
|
91
|
-
//
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
res.setHeader('
|
|
121
|
-
res.setHeader('
|
|
122
|
-
res.setHeader('
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Servir
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
app.get('/
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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;
|