slicejs-cli 2.8.6 → 2.9.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.
- package/README.md +347 -315
- package/client.js +526 -539
- package/commands/Print.js +167 -167
- package/commands/Validations.js +103 -103
- package/commands/build/build.js +40 -0
- package/commands/buildProduction/buildProduction.js +45 -10
- package/commands/bundle/bundle.js +235 -231
- package/commands/createComponent/VisualComponentTemplate.js +55 -55
- package/commands/createComponent/createComponent.js +126 -126
- package/commands/deleteComponent/deleteComponent.js +77 -77
- package/commands/doctor/doctor.js +369 -369
- package/commands/getComponent/getComponent.js +747 -747
- package/commands/init/init.js +261 -261
- package/commands/listComponents/listComponents.js +175 -175
- package/commands/startServer/startServer.js +260 -270
- package/commands/startServer/watchServer.js +79 -79
- package/commands/utils/PathHelper.js +68 -68
- package/commands/utils/VersionChecker.js +167 -167
- package/commands/utils/bundling/BundleGenerator.js +1331 -783
- package/commands/utils/bundling/DependencyAnalyzer.js +859 -679
- package/commands/utils/updateManager.js +437 -384
- package/package.json +46 -46
- package/post.js +25 -25
- package/refactor.md +271 -271
- package/tests/bundle-generator.test.js +38 -0
- package/tests/dependency-analyzer.test.js +24 -0
|
@@ -1,270 +1,260 @@
|
|
|
1
|
-
// commands/startServer/startServer.js - MEJORADO CON VALIDACIÓN Y FEEDBACK
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
|
|
13
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Carga la configuración desde sliceConfig.json
|
|
17
|
-
*/
|
|
18
|
-
const loadConfig = () => {
|
|
19
|
-
try {
|
|
20
|
-
const configPath = getConfigPath(import.meta.url);
|
|
21
|
-
const rawData = fs.readFileSync(configPath, 'utf-8');
|
|
22
|
-
return JSON.parse(rawData);
|
|
23
|
-
} catch (error) {
|
|
24
|
-
Print.error(`Loading configuration: ${error.message}`);
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Verifica si un puerto está disponible
|
|
31
|
-
*/
|
|
32
|
-
async function isPortAvailable(port) {
|
|
33
|
-
return new Promise((resolve) => {
|
|
34
|
-
const server = createServer();
|
|
35
|
-
|
|
36
|
-
server.once('error', (err) => {
|
|
37
|
-
if (err.code === 'EADDRINUSE') {
|
|
38
|
-
resolve(false);
|
|
39
|
-
} else {
|
|
40
|
-
resolve(false);
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
server.once('listening', () => {
|
|
45
|
-
server.close();
|
|
46
|
-
resolve(true);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
server.listen(port);
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Verifica si existe un build de producción
|
|
55
|
-
*/
|
|
56
|
-
async function checkProductionBuild() {
|
|
57
|
-
const distDir = getDistPath(import.meta.url);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
let
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
output.includes('
|
|
116
|
-
output.includes('
|
|
117
|
-
output.includes(
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
-
Print.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
Print.
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
Print.
|
|
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
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
Print.newLine();
|
|
262
|
-
Print.error(error.message);
|
|
263
|
-
throw error;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Funciones de utilidad exportadas
|
|
269
|
-
*/
|
|
270
|
-
export { checkProductionBuild, checkDevelopmentStructure, isPortAvailable };
|
|
1
|
+
// commands/startServer/startServer.js - MEJORADO CON VALIDACIÓN Y FEEDBACK
|
|
2
|
+
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import { spawn } from 'child_process';
|
|
7
|
+
import { createServer } from 'net';
|
|
8
|
+
import setupWatcher, { stopWatcher } from './watchServer.js';
|
|
9
|
+
import Print from '../Print.js';
|
|
10
|
+
import { getConfigPath, getApiPath, getSrcPath, getDistPath } from '../utils/PathHelper.js';
|
|
11
|
+
import build from '../build/build.js';
|
|
12
|
+
|
|
13
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Carga la configuración desde sliceConfig.json
|
|
17
|
+
*/
|
|
18
|
+
const loadConfig = () => {
|
|
19
|
+
try {
|
|
20
|
+
const configPath = getConfigPath(import.meta.url);
|
|
21
|
+
const rawData = fs.readFileSync(configPath, 'utf-8');
|
|
22
|
+
return JSON.parse(rawData);
|
|
23
|
+
} catch (error) {
|
|
24
|
+
Print.error(`Loading configuration: ${error.message}`);
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Verifica si un puerto está disponible
|
|
31
|
+
*/
|
|
32
|
+
async function isPortAvailable(port) {
|
|
33
|
+
return new Promise((resolve) => {
|
|
34
|
+
const server = createServer();
|
|
35
|
+
|
|
36
|
+
server.once('error', (err) => {
|
|
37
|
+
if (err.code === 'EADDRINUSE') {
|
|
38
|
+
resolve(false);
|
|
39
|
+
} else {
|
|
40
|
+
resolve(false);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
server.once('listening', () => {
|
|
45
|
+
server.close();
|
|
46
|
+
resolve(true);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
server.listen(port);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Verifica si existe un build de producción
|
|
55
|
+
*/
|
|
56
|
+
async function checkProductionBuild() {
|
|
57
|
+
const distDir = getDistPath(import.meta.url);
|
|
58
|
+
const bundleConfigPath = path.join(distDir, 'bundles', 'bundle.config.json');
|
|
59
|
+
return (await fs.pathExists(distDir)) && (await fs.pathExists(bundleConfigPath));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Verifica si existe la estructura de desarrollo
|
|
64
|
+
*/
|
|
65
|
+
async function checkDevelopmentStructure() {
|
|
66
|
+
const srcDir = getSrcPath(import.meta.url);
|
|
67
|
+
const apiDir = getApiPath(import.meta.url);
|
|
68
|
+
|
|
69
|
+
return (await fs.pathExists(srcDir)) && (await fs.pathExists(apiDir));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Inicia el servidor Node.js con argumentos y mejor feedback
|
|
74
|
+
*/
|
|
75
|
+
function startNodeServer(port, mode) {
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
const apiIndexPath = getApiPath(import.meta.url, 'index.js');
|
|
78
|
+
|
|
79
|
+
// Verificar que el archivo existe
|
|
80
|
+
if (!fs.existsSync(apiIndexPath)) {
|
|
81
|
+
reject(new Error(`Server file not found: ${apiIndexPath}`));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
Print.serverStatus('starting', 'Starting server...');
|
|
86
|
+
|
|
87
|
+
// Construir argumentos basados en el modo
|
|
88
|
+
const args = [apiIndexPath];
|
|
89
|
+
if (mode === 'production') {
|
|
90
|
+
args.push('--production');
|
|
91
|
+
} else if (mode === 'bundled') {
|
|
92
|
+
args.push('--bundled');
|
|
93
|
+
} else {
|
|
94
|
+
args.push('--development');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const serverProcess = spawn('node', args, {
|
|
98
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
99
|
+
env: {
|
|
100
|
+
...process.env,
|
|
101
|
+
PORT: port
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
let serverStarted = false;
|
|
106
|
+
let outputBuffer = '';
|
|
107
|
+
|
|
108
|
+
// Capturar la salida para detectar cuando el servidor está listo
|
|
109
|
+
serverProcess.stdout.on('data', (data) => {
|
|
110
|
+
const output = data.toString();
|
|
111
|
+
outputBuffer += output;
|
|
112
|
+
|
|
113
|
+
// Detectar mensajes comunes que indican que el servidor ha iniciado
|
|
114
|
+
if (!serverStarted && (
|
|
115
|
+
output.includes('Server running') ||
|
|
116
|
+
output.includes('listening on') ||
|
|
117
|
+
output.includes('Started on') ||
|
|
118
|
+
output.includes(`port ${port}`)
|
|
119
|
+
)) {
|
|
120
|
+
serverStarted = true;
|
|
121
|
+
Print.serverReady(port);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Mostrar la salida del servidor
|
|
125
|
+
process.stdout.write(output);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
serverProcess.stderr.on('data', (data) => {
|
|
129
|
+
const output = data.toString();
|
|
130
|
+
process.stderr.write(output);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
serverProcess.on('error', (error) => {
|
|
134
|
+
if (!serverStarted) {
|
|
135
|
+
Print.serverStatus('error', `Failed to start server: ${error.message}`);
|
|
136
|
+
reject(error);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
serverProcess.on('exit', (code, signal) => {
|
|
141
|
+
if (code !== null && code !== 0 && !serverStarted) {
|
|
142
|
+
reject(new Error(`Server exited with code ${code}`));
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Manejar Ctrl+C
|
|
147
|
+
process.on('SIGINT', () => {
|
|
148
|
+
Print.newLine();
|
|
149
|
+
Print.info('Shutting down server...');
|
|
150
|
+
serverProcess.kill('SIGINT');
|
|
151
|
+
setTimeout(() => {
|
|
152
|
+
process.exit(0);
|
|
153
|
+
}, 100);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
process.on('SIGTERM', () => {
|
|
157
|
+
serverProcess.kill('SIGTERM');
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// Si después de 3 segundos no detectamos inicio, asumimos que está listo
|
|
161
|
+
setTimeout(() => {
|
|
162
|
+
if (!serverStarted) {
|
|
163
|
+
serverStarted = true;
|
|
164
|
+
Print.serverReady(port);
|
|
165
|
+
}
|
|
166
|
+
resolve(serverProcess);
|
|
167
|
+
}, 3000);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Función principal para iniciar servidor
|
|
173
|
+
*/
|
|
174
|
+
export default async function startServer(options = {}) {
|
|
175
|
+
const config = loadConfig();
|
|
176
|
+
const defaultPort = config?.server?.port || 3000;
|
|
177
|
+
|
|
178
|
+
const { mode = 'development', port = defaultPort, watch = false } = options;
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
Print.title(`🚀 Starting Slice.js ${mode} server...`);
|
|
182
|
+
Print.newLine();
|
|
183
|
+
|
|
184
|
+
// Verificar estructura del proyecto
|
|
185
|
+
if (!await checkDevelopmentStructure()) {
|
|
186
|
+
throw new Error('Project structure not found. Run "slice init" first.');
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
let actualPort = await isPortAvailable(port) ? port : port + 1; // Try one more port
|
|
190
|
+
if(actualPort !== port) {
|
|
191
|
+
// Check if the fallback is available
|
|
192
|
+
const fallbackAvailable = await isPortAvailable(actualPort);
|
|
193
|
+
if(!fallbackAvailable) {
|
|
194
|
+
throw new Error(`Ports ${port} and ${actualPort} are in use.`);
|
|
195
|
+
}
|
|
196
|
+
Print.info(`ℹ️ Port ${port} in use, using ${actualPort} instead.`);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
Print.serverStatus('checking', `Port ${actualPort} available ✓`);
|
|
200
|
+
Print.newLine();
|
|
201
|
+
|
|
202
|
+
if (mode === 'production') {
|
|
203
|
+
// Verificar que existe build de producción
|
|
204
|
+
if (!await checkProductionBuild()) {
|
|
205
|
+
Print.info('No production build found. Running "slice build"...');
|
|
206
|
+
const success = await build({});
|
|
207
|
+
if (!success) {
|
|
208
|
+
throw new Error('Build failed. Cannot start production server.');
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
Print.info('Production mode: serving optimized files from /dist');
|
|
212
|
+
} else {
|
|
213
|
+
Print.info('Development mode: serving files from /src with hot reload');
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
Print.newLine();
|
|
217
|
+
|
|
218
|
+
// Iniciar el servidor con argumentos
|
|
219
|
+
let serverProcess = await startNodeServer(actualPort, mode);
|
|
220
|
+
|
|
221
|
+
// Configurar watch mode si está habilitado
|
|
222
|
+
if (watch) {
|
|
223
|
+
Print.newLine();
|
|
224
|
+
const watcher = setupWatcher(serverProcess, async (changedPath) => {
|
|
225
|
+
if (serverProcess) {
|
|
226
|
+
serverProcess.kill();
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Short delay to ensure port is freed
|
|
230
|
+
await new Promise(r => setTimeout(r, 500));
|
|
231
|
+
|
|
232
|
+
try {
|
|
233
|
+
Print.info('🔄 File changed. Restarting server...');
|
|
234
|
+
|
|
235
|
+
serverProcess = await startNodeServer(actualPort, mode);
|
|
236
|
+
} catch (e) {
|
|
237
|
+
Print.error(`Failed to restart server: ${e.message}`);
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
// Cleanup en exit
|
|
242
|
+
const cleanup = () => {
|
|
243
|
+
stopWatcher(watcher);
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
process.on('SIGINT', cleanup);
|
|
247
|
+
process.on('SIGTERM', cleanup);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
} catch (error) {
|
|
251
|
+
Print.newLine();
|
|
252
|
+
Print.error(error.message);
|
|
253
|
+
throw error;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Funciones de utilidad exportadas
|
|
259
|
+
*/
|
|
260
|
+
export { checkProductionBuild, checkDevelopmentStructure, isPortAvailable };
|