slicejs-cli 2.3.3 → 2.5.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 +280 -0
- package/client.js +29 -13
- package/commands/Print.js +81 -30
- package/commands/doctor/doctor.js +335 -0
- package/commands/init/init.js +38 -34
- package/commands/listComponents/listComponents.js +79 -17
- package/commands/startServer/startServer.js +130 -23
- package/commands/startServer/watchServer.js +67 -0
- package/package.json +13 -2
- package/post.js +81 -64
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { createServer } from 'net';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import Table from 'cli-table3';
|
|
7
|
+
import Print from '../Print.js';
|
|
8
|
+
|
|
9
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Verifica la versión de Node.js
|
|
13
|
+
*/
|
|
14
|
+
async function checkNodeVersion() {
|
|
15
|
+
const currentVersion = process.version;
|
|
16
|
+
const majorVersion = parseInt(currentVersion.slice(1).split('.')[0]);
|
|
17
|
+
const required = 20;
|
|
18
|
+
|
|
19
|
+
if (majorVersion >= required) {
|
|
20
|
+
return {
|
|
21
|
+
pass: true,
|
|
22
|
+
message: `Node.js version: ${currentVersion} (required: >= v${required})`
|
|
23
|
+
};
|
|
24
|
+
} else {
|
|
25
|
+
return {
|
|
26
|
+
pass: false,
|
|
27
|
+
message: `Node.js version: ${currentVersion} (required: >= v${required})`,
|
|
28
|
+
suggestion: `Update Node.js to v${required} or higher`
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Verifica la estructura de directorios
|
|
35
|
+
*/
|
|
36
|
+
async function checkDirectoryStructure() {
|
|
37
|
+
const projectRoot = path.join(__dirname, '../../../../');
|
|
38
|
+
const srcPath = path.join(projectRoot, 'src');
|
|
39
|
+
const apiPath = path.join(projectRoot, 'api');
|
|
40
|
+
|
|
41
|
+
const srcExists = await fs.pathExists(srcPath);
|
|
42
|
+
const apiExists = await fs.pathExists(apiPath);
|
|
43
|
+
|
|
44
|
+
if (srcExists && apiExists) {
|
|
45
|
+
return {
|
|
46
|
+
pass: true,
|
|
47
|
+
message: 'Project structure (src/ and api/) exists'
|
|
48
|
+
};
|
|
49
|
+
} else {
|
|
50
|
+
const missing = [];
|
|
51
|
+
if (!srcExists) missing.push('src/');
|
|
52
|
+
if (!apiExists) missing.push('api/');
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
pass: false,
|
|
56
|
+
message: `Missing directories: ${missing.join(', ')}`,
|
|
57
|
+
suggestion: 'Run "slice init" to initialize your project'
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Verifica sliceConfig.json
|
|
64
|
+
*/
|
|
65
|
+
async function checkConfig() {
|
|
66
|
+
const configPath = path.join(__dirname, '../../../../src/sliceConfig.json');
|
|
67
|
+
|
|
68
|
+
if (!await fs.pathExists(configPath)) {
|
|
69
|
+
return {
|
|
70
|
+
pass: false,
|
|
71
|
+
message: 'sliceConfig.json not found',
|
|
72
|
+
suggestion: 'Run "slice init" to create configuration'
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const config = await fs.readJson(configPath);
|
|
78
|
+
|
|
79
|
+
if (!config.paths || !config.paths.components) {
|
|
80
|
+
return {
|
|
81
|
+
pass: false,
|
|
82
|
+
message: 'sliceConfig.json is invalid (missing paths.components)',
|
|
83
|
+
suggestion: 'Check your configuration file'
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
pass: true,
|
|
89
|
+
message: 'sliceConfig.json is valid'
|
|
90
|
+
};
|
|
91
|
+
} catch (error) {
|
|
92
|
+
return {
|
|
93
|
+
pass: false,
|
|
94
|
+
message: `sliceConfig.json is invalid JSON: ${error.message}`,
|
|
95
|
+
suggestion: 'Fix JSON syntax errors in sliceConfig.json'
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Verifica disponibilidad del puerto
|
|
102
|
+
*/
|
|
103
|
+
async function checkPort() {
|
|
104
|
+
const configPath = path.join(__dirname, '../../../../src/sliceConfig.json');
|
|
105
|
+
let port = 3000;
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
if (await fs.pathExists(configPath)) {
|
|
109
|
+
const config = await fs.readJson(configPath);
|
|
110
|
+
port = config.server?.port || 3000;
|
|
111
|
+
}
|
|
112
|
+
} catch { }
|
|
113
|
+
|
|
114
|
+
return new Promise((resolve) => {
|
|
115
|
+
const server = createServer();
|
|
116
|
+
|
|
117
|
+
server.once('error', (err) => {
|
|
118
|
+
if (err.code === 'EADDRINUSE') {
|
|
119
|
+
resolve({
|
|
120
|
+
warn: true,
|
|
121
|
+
message: `Port ${port} is already in use`,
|
|
122
|
+
suggestion: `Stop the process using port ${port} or use: slice dev -p <other-port>`
|
|
123
|
+
});
|
|
124
|
+
} else {
|
|
125
|
+
resolve({
|
|
126
|
+
pass: true,
|
|
127
|
+
message: `Port ${port} is available`
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
server.once('listening', () => {
|
|
133
|
+
server.close();
|
|
134
|
+
resolve({
|
|
135
|
+
pass: true,
|
|
136
|
+
message: `Port ${port} is available`
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
server.listen(port);
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Verifica dependencias en package.json
|
|
146
|
+
*/
|
|
147
|
+
async function checkDependencies() {
|
|
148
|
+
const packagePath = path.join(__dirname, '../../../../package.json');
|
|
149
|
+
|
|
150
|
+
if (!await fs.pathExists(packagePath)) {
|
|
151
|
+
return {
|
|
152
|
+
warn: true,
|
|
153
|
+
message: 'package.json not found',
|
|
154
|
+
suggestion: 'Run "npm init" to create package.json'
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
const pkg = await fs.readJson(packagePath);
|
|
160
|
+
const hasCli = pkg.dependencies?.['slicejs-cli'] || pkg.devDependencies?.['slicejs-cli'];
|
|
161
|
+
const hasFramework = pkg.dependencies?.['slicejs-web-framework'];
|
|
162
|
+
|
|
163
|
+
if (hasCli && hasFramework) {
|
|
164
|
+
return {
|
|
165
|
+
pass: true,
|
|
166
|
+
message: 'All required dependencies are installed'
|
|
167
|
+
};
|
|
168
|
+
} else {
|
|
169
|
+
const missing = [];
|
|
170
|
+
if (!hasCli) missing.push('slicejs-cli');
|
|
171
|
+
if (!hasFramework) missing.push('slicejs-web-framework');
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
warn: true,
|
|
175
|
+
message: `Missing dependencies: ${missing.join(', ')}`,
|
|
176
|
+
suggestion: 'Run "npm install"'
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
} catch (error) {
|
|
180
|
+
return {
|
|
181
|
+
pass: false,
|
|
182
|
+
message: `package.json is invalid: ${error.message}`,
|
|
183
|
+
suggestion: 'Fix JSON syntax errors in package.json'
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Verifica integridad de componentes
|
|
190
|
+
*/
|
|
191
|
+
async function checkComponents() {
|
|
192
|
+
const configPath = path.join(__dirname, '../../../../src/sliceConfig.json');
|
|
193
|
+
const projectRoot = path.join(__dirname, '../../../../');
|
|
194
|
+
|
|
195
|
+
if (!await fs.pathExists(configPath)) {
|
|
196
|
+
return {
|
|
197
|
+
warn: true,
|
|
198
|
+
message: 'Cannot check components (no config)',
|
|
199
|
+
suggestion: 'Run "slice init" first'
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
const config = await fs.readJson(configPath);
|
|
205
|
+
const componentPaths = config.paths?.components || {};
|
|
206
|
+
|
|
207
|
+
let totalComponents = 0;
|
|
208
|
+
let componentIssues = 0;
|
|
209
|
+
|
|
210
|
+
for (const [category, { path: compPath }] of Object.entries(componentPaths)) {
|
|
211
|
+
const fullPath = path.join(projectRoot, 'src', compPath);
|
|
212
|
+
|
|
213
|
+
if (await fs.pathExists(fullPath)) {
|
|
214
|
+
const items = await fs.readdir(fullPath);
|
|
215
|
+
|
|
216
|
+
for (const item of items) {
|
|
217
|
+
const itemPath = path.join(fullPath, item);
|
|
218
|
+
const stat = await fs.stat(itemPath);
|
|
219
|
+
|
|
220
|
+
if (stat.isDirectory()) {
|
|
221
|
+
totalComponents++;
|
|
222
|
+
|
|
223
|
+
// Verificar archivos JS
|
|
224
|
+
const jsFile = path.join(itemPath, `${item}.js`);
|
|
225
|
+
if (!await fs.pathExists(jsFile)) {
|
|
226
|
+
componentIssues++;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (componentIssues === 0) {
|
|
234
|
+
return {
|
|
235
|
+
pass: true,
|
|
236
|
+
message: `${totalComponents} components checked, all OK`
|
|
237
|
+
};
|
|
238
|
+
} else {
|
|
239
|
+
return {
|
|
240
|
+
warn: true,
|
|
241
|
+
message: `${componentIssues} component(s) have missing files`,
|
|
242
|
+
suggestion: 'Check your component directories'
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
} catch (error) {
|
|
246
|
+
return {
|
|
247
|
+
warn: true,
|
|
248
|
+
message: `Cannot check components: ${error.message}`,
|
|
249
|
+
suggestion: 'Verify your project structure'
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Comando principal de diagnóstico
|
|
256
|
+
*/
|
|
257
|
+
export default async function runDiagnostics() {
|
|
258
|
+
Print.newLine();
|
|
259
|
+
Print.title('🔍 Running Slice.js Diagnostics...');
|
|
260
|
+
Print.newLine();
|
|
261
|
+
|
|
262
|
+
const checks = [
|
|
263
|
+
{ name: 'Node.js Version', fn: checkNodeVersion },
|
|
264
|
+
{ name: 'Project Structure', fn: checkDirectoryStructure },
|
|
265
|
+
{ name: 'Configuration', fn: checkConfig },
|
|
266
|
+
{ name: 'Port Availability', fn: checkPort },
|
|
267
|
+
{ name: 'Dependencies', fn: checkDependencies },
|
|
268
|
+
{ name: 'Components', fn: checkComponents }
|
|
269
|
+
];
|
|
270
|
+
|
|
271
|
+
const results = [];
|
|
272
|
+
|
|
273
|
+
for (const check of checks) {
|
|
274
|
+
const result = await check.fn();
|
|
275
|
+
results.push({ ...result, name: check.name });
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Crear tabla de resultados
|
|
279
|
+
const table = new Table({
|
|
280
|
+
head: [chalk.cyan.bold('Check'), chalk.cyan.bold('Status'), chalk.cyan.bold('Details')],
|
|
281
|
+
colWidths: [25, 10, 55],
|
|
282
|
+
style: {
|
|
283
|
+
head: [],
|
|
284
|
+
border: ['gray']
|
|
285
|
+
},
|
|
286
|
+
wordWrap: true
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
results.forEach(result => {
|
|
290
|
+
let status;
|
|
291
|
+
if (result.pass) {
|
|
292
|
+
status = chalk.green('✅ PASS');
|
|
293
|
+
} else if (result.warn) {
|
|
294
|
+
status = chalk.yellow('⚠️ WARN');
|
|
295
|
+
} else {
|
|
296
|
+
status = chalk.red('❌ FAIL');
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const details = result.suggestion
|
|
300
|
+
? `${result.message}\n${chalk.gray('→ ' + result.suggestion)}`
|
|
301
|
+
: result.message;
|
|
302
|
+
|
|
303
|
+
table.push([result.name, status, details]);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
console.log(table.toString());
|
|
307
|
+
|
|
308
|
+
// Resumen
|
|
309
|
+
const issues = results.filter(r => !r.pass && !r.warn).length;
|
|
310
|
+
const warnings = results.filter(r => r.warn).length;
|
|
311
|
+
const passed = results.filter(r => r.pass).length;
|
|
312
|
+
|
|
313
|
+
Print.newLine();
|
|
314
|
+
Print.separator();
|
|
315
|
+
|
|
316
|
+
if (issues === 0 && warnings === 0) {
|
|
317
|
+
Print.success('All checks passed! 🎉');
|
|
318
|
+
Print.info('Your Slice.js project is correctly configured');
|
|
319
|
+
} else {
|
|
320
|
+
console.log(chalk.bold('📊 Summary:'));
|
|
321
|
+
console.log(chalk.green(` ✅ Passed: ${passed}`));
|
|
322
|
+
if (warnings > 0) console.log(chalk.yellow(` ⚠️ Warnings: ${warnings}`));
|
|
323
|
+
if (issues > 0) console.log(chalk.red(` ❌ Issues: ${issues}`));
|
|
324
|
+
|
|
325
|
+
Print.newLine();
|
|
326
|
+
|
|
327
|
+
if (issues > 0) {
|
|
328
|
+
Print.warning('Fix the issues above to ensure proper functionality');
|
|
329
|
+
} else {
|
|
330
|
+
Print.info('Warnings are non-critical but should be addressed');
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
Print.separator();
|
|
335
|
+
}
|
package/commands/init/init.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
+
import ora from 'ora';
|
|
4
5
|
import Print from '../Print.js';
|
|
5
6
|
|
|
6
7
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -27,40 +28,43 @@ export default async function initializeProject(projectType) {
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
// 1. COPIAR LA CARPETA API (mantener lógica original)
|
|
31
|
+
const apiSpinner = ora('Copying API structure...').start();
|
|
30
32
|
try {
|
|
31
33
|
if (!fs.existsSync(apiDir)) throw new Error(`No se encontró la carpeta api: ${apiDir}`);
|
|
32
34
|
await fs.copy(apiDir, destinationApi, { recursive: true });
|
|
33
|
-
|
|
35
|
+
apiSpinner.succeed('API structure created successfully');
|
|
34
36
|
} catch (error) {
|
|
35
|
-
|
|
37
|
+
apiSpinner.fail('Error copying API structure');
|
|
38
|
+
Print.error(error.message);
|
|
36
39
|
return;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
// 2. CREAR ESTRUCTURA SRC BÁSICA (sin copiar componentes Visual)
|
|
43
|
+
const srcSpinner = ora('Creating src structure...').start();
|
|
40
44
|
try {
|
|
41
45
|
if (!fs.existsSync(srcDir)) throw new Error(`No se encontró la carpeta src: ${srcDir}`);
|
|
42
|
-
|
|
46
|
+
|
|
43
47
|
// Copiar solo los archivos base de src, excluyendo Components/Visual
|
|
44
48
|
await fs.ensureDir(destinationSrc);
|
|
45
|
-
|
|
49
|
+
|
|
46
50
|
// Copiar archivos y carpetas de src excepto Components/Visual
|
|
47
51
|
const srcItems = await fs.readdir(srcDir);
|
|
48
|
-
|
|
52
|
+
|
|
49
53
|
for (const item of srcItems) {
|
|
50
54
|
const srcItemPath = path.join(srcDir, item);
|
|
51
55
|
const destItemPath = path.join(destinationSrc, item);
|
|
52
56
|
const stat = await fs.stat(srcItemPath);
|
|
53
|
-
|
|
57
|
+
|
|
54
58
|
if (stat.isDirectory()) {
|
|
55
59
|
if (item === 'Components') {
|
|
56
60
|
// Crear estructura de Components pero sin copiar Visual
|
|
57
61
|
await fs.ensureDir(destItemPath);
|
|
58
|
-
|
|
62
|
+
|
|
59
63
|
const componentItems = await fs.readdir(srcItemPath);
|
|
60
64
|
for (const componentItem of componentItems) {
|
|
61
65
|
const componentItemPath = path.join(srcItemPath, componentItem);
|
|
62
66
|
const destComponentItemPath = path.join(destItemPath, componentItem);
|
|
63
|
-
|
|
67
|
+
|
|
64
68
|
if (componentItem !== 'Visual') {
|
|
65
69
|
// Copiar Service y otros tipos de components
|
|
66
70
|
await fs.copy(componentItemPath, destComponentItemPath, { recursive: true });
|
|
@@ -78,50 +82,50 @@ export default async function initializeProject(projectType) {
|
|
|
78
82
|
await fs.copy(srcItemPath, destItemPath);
|
|
79
83
|
}
|
|
80
84
|
}
|
|
81
|
-
|
|
82
|
-
|
|
85
|
+
|
|
86
|
+
srcSpinner.succeed('Source structure created successfully');
|
|
83
87
|
} catch (error) {
|
|
84
|
-
|
|
88
|
+
srcSpinner.fail('Error creating source structure');
|
|
89
|
+
Print.error(error.message);
|
|
85
90
|
return;
|
|
86
91
|
}
|
|
87
92
|
|
|
88
93
|
// 3. DESCARGAR TODOS LOS COMPONENTES VISUAL DESDE EL REPOSITORIO OFICIAL
|
|
94
|
+
const componentsSpinner = ora('Loading component registry...').start();
|
|
89
95
|
try {
|
|
90
|
-
Print.info('Downloading all Visual components from official repository...');
|
|
91
|
-
|
|
92
96
|
const registry = new ComponentRegistry();
|
|
93
97
|
await registry.loadRegistry();
|
|
94
|
-
|
|
98
|
+
|
|
95
99
|
// Obtener TODOS los componentes Visual disponibles
|
|
96
100
|
const allVisualComponents = await getAllVisualComponents(registry);
|
|
97
|
-
|
|
101
|
+
|
|
98
102
|
if (allVisualComponents.length > 0) {
|
|
99
|
-
|
|
100
|
-
|
|
103
|
+
componentsSpinner.text = `Installing ${allVisualComponents.length} Visual components...`;
|
|
104
|
+
|
|
101
105
|
const results = await registry.installMultipleComponents(
|
|
102
|
-
allVisualComponents,
|
|
103
|
-
'Visual',
|
|
106
|
+
allVisualComponents,
|
|
107
|
+
'Visual',
|
|
104
108
|
true // force = true para instalación inicial
|
|
105
109
|
);
|
|
106
|
-
|
|
110
|
+
|
|
107
111
|
const successful = results.filter(r => r.success).length;
|
|
108
112
|
const failed = results.filter(r => !r.success).length;
|
|
109
|
-
|
|
110
|
-
if (successful > 0) {
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
113
|
+
|
|
114
|
+
if (successful > 0 && failed === 0) {
|
|
115
|
+
componentsSpinner.succeed(`All ${successful} Visual components installed successfully`);
|
|
116
|
+
} else if (successful > 0) {
|
|
117
|
+
componentsSpinner.warn(`${successful} components installed, ${failed} failed`);
|
|
118
|
+
Print.info('You can install failed components later using "slice get <component-name>"');
|
|
119
|
+
} else {
|
|
120
|
+
componentsSpinner.fail('Failed to install Visual components');
|
|
117
121
|
}
|
|
118
122
|
} else {
|
|
119
|
-
|
|
123
|
+
componentsSpinner.warn('No Visual components found in registry');
|
|
120
124
|
Print.info('You can add components later using "slice get <component-name>"');
|
|
121
125
|
}
|
|
122
|
-
|
|
126
|
+
|
|
123
127
|
} catch (error) {
|
|
124
|
-
|
|
128
|
+
componentsSpinner.fail('Could not download Visual components from official repository');
|
|
125
129
|
Print.error(`Repository error: ${error.message}`);
|
|
126
130
|
Print.info('Project initialized without Visual components');
|
|
127
131
|
Print.info('You can add them later using "slice get <component-name>"');
|
|
@@ -133,7 +137,7 @@ export default async function initializeProject(projectType) {
|
|
|
133
137
|
console.log(' slice browse - View available components');
|
|
134
138
|
console.log(' slice get Button - Install specific components');
|
|
135
139
|
console.log(' slice sync - Update all components to latest versions');
|
|
136
|
-
|
|
140
|
+
|
|
137
141
|
} catch (error) {
|
|
138
142
|
Print.error('Error inesperado al inicializar el proyecto:', error.message);
|
|
139
143
|
}
|
|
@@ -147,8 +151,8 @@ export default async function initializeProject(projectType) {
|
|
|
147
151
|
async function getAllVisualComponents(registry) {
|
|
148
152
|
const availableComponents = registry.getAvailableComponents('Visual');
|
|
149
153
|
const allVisualComponents = Object.keys(availableComponents);
|
|
150
|
-
|
|
154
|
+
|
|
151
155
|
Print.info(`Found ${allVisualComponents.length} Visual components in official repository`);
|
|
152
|
-
|
|
156
|
+
|
|
153
157
|
return allVisualComponents;
|
|
154
158
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
+
import Table from 'cli-table3';
|
|
5
|
+
import chalk from 'chalk';
|
|
4
6
|
import Print from '../Print.js';
|
|
5
7
|
|
|
6
8
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -34,7 +36,6 @@ const loadConfig = () => {
|
|
|
34
36
|
const listComponents = (folderPath) => {
|
|
35
37
|
try {
|
|
36
38
|
if (!fs.existsSync(folderPath)) {
|
|
37
|
-
Print.warning(`Component directory not found: ${folderPath}`);
|
|
38
39
|
return [];
|
|
39
40
|
}
|
|
40
41
|
const result = fs.readdirSync(folderPath);
|
|
@@ -45,6 +46,19 @@ const listComponents = (folderPath) => {
|
|
|
45
46
|
}
|
|
46
47
|
};
|
|
47
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Cuenta archivos en un directorio de componente
|
|
51
|
+
*/
|
|
52
|
+
const countComponentFiles = (componentPath) => {
|
|
53
|
+
try {
|
|
54
|
+
if (!fs.existsSync(componentPath)) return 0;
|
|
55
|
+
const files = fs.readdirSync(componentPath);
|
|
56
|
+
return files.filter(f => fs.statSync(path.join(componentPath, f)).isFile()).length;
|
|
57
|
+
} catch {
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
48
62
|
/**
|
|
49
63
|
* Obtiene los componentes dinámicamente desde sliceConfig.json
|
|
50
64
|
* @returns {object} - Mapeo de componentes con su categoría
|
|
@@ -53,29 +67,27 @@ const getComponents = () => {
|
|
|
53
67
|
const config = loadConfig();
|
|
54
68
|
if (!config) return {};
|
|
55
69
|
|
|
56
|
-
//const isProduction = config.production.enabled===true;
|
|
57
70
|
const folderSuffix = 'src'; // Siempre usar 'src' para desarrollo
|
|
58
|
-
|
|
59
|
-
const componentPaths = config.paths?.components || {}; // Obtiene dinámicamente las rutas de los componentes
|
|
71
|
+
const componentPaths = config.paths?.components || {};
|
|
60
72
|
let allComponents = new Map();
|
|
61
73
|
|
|
62
74
|
Object.entries(componentPaths).forEach(([category, { path: folderPath }]) => {
|
|
63
75
|
const fullPath = path.join(__dirname, `../../../../${folderSuffix}`, folderPath);
|
|
64
76
|
const files = listComponents(fullPath);
|
|
65
77
|
|
|
66
|
-
|
|
67
78
|
files.forEach(file => {
|
|
68
|
-
const
|
|
69
|
-
|
|
79
|
+
const componentPath = path.join(fullPath, file);
|
|
80
|
+
if (fs.statSync(componentPath).isDirectory()) {
|
|
81
|
+
const fileCount = countComponentFiles(componentPath);
|
|
82
|
+
allComponents.set(file, { category, files: fileCount });
|
|
83
|
+
}
|
|
70
84
|
});
|
|
71
85
|
});
|
|
72
86
|
|
|
73
|
-
|
|
74
|
-
|
|
75
87
|
return Object.fromEntries(allComponents);
|
|
76
88
|
};
|
|
77
89
|
|
|
78
|
-
function listComponentsReal(){
|
|
90
|
+
function listComponentsReal() {
|
|
79
91
|
try {
|
|
80
92
|
// Obtener componentes dinámicamente
|
|
81
93
|
const components = getComponents();
|
|
@@ -86,26 +98,76 @@ function listComponentsReal(){
|
|
|
86
98
|
return;
|
|
87
99
|
}
|
|
88
100
|
|
|
101
|
+
// Crear tabla con cli-table3
|
|
102
|
+
const table = new Table({
|
|
103
|
+
head: [
|
|
104
|
+
chalk.cyan.bold('Component'),
|
|
105
|
+
chalk.cyan.bold('Category'),
|
|
106
|
+
chalk.cyan.bold('Files')
|
|
107
|
+
],
|
|
108
|
+
colWidths: [30, 20, 10],
|
|
109
|
+
style: {
|
|
110
|
+
head: [],
|
|
111
|
+
border: ['gray']
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Agrupar por categoría para mejor visualización
|
|
116
|
+
const byCategory = {};
|
|
117
|
+
Object.entries(components).forEach(([name, data]) => {
|
|
118
|
+
if (!byCategory[data.category]) {
|
|
119
|
+
byCategory[data.category] = [];
|
|
120
|
+
}
|
|
121
|
+
byCategory[data.category].push({ name, files: data.files });
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Agregar filas a la tabla
|
|
125
|
+
Object.entries(byCategory).forEach(([category, comps]) => {
|
|
126
|
+
comps.forEach((comp, index) => {
|
|
127
|
+
if (index === 0) {
|
|
128
|
+
// Primera fila de la categoría
|
|
129
|
+
table.push([
|
|
130
|
+
chalk.bold(comp.name),
|
|
131
|
+
chalk.yellow(category),
|
|
132
|
+
comp.files.toString()
|
|
133
|
+
]);
|
|
134
|
+
} else {
|
|
135
|
+
// Resto de componentes en la categoría
|
|
136
|
+
table.push([
|
|
137
|
+
chalk.bold(comp.name),
|
|
138
|
+
chalk.gray('″'), // Ditto mark
|
|
139
|
+
comp.files.toString()
|
|
140
|
+
]);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
Print.newLine();
|
|
146
|
+
Print.title('📦 Local Components');
|
|
147
|
+
Print.newLine();
|
|
148
|
+
console.log(table.toString());
|
|
149
|
+
Print.newLine();
|
|
150
|
+
Print.info(`Total: ${Object.keys(components).length} component${Object.keys(components).length !== 1 ? 's' : ''} found`);
|
|
151
|
+
|
|
89
152
|
// Ruta donde se generará components.js
|
|
90
153
|
const outputPath = path.join(__dirname, '../../../../src/Components/components.js');
|
|
91
|
-
|
|
154
|
+
|
|
92
155
|
// Asegurar que el directorio existe
|
|
93
156
|
const outputDir = path.dirname(outputPath);
|
|
94
157
|
if (!fs.existsSync(outputDir)) {
|
|
95
158
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
96
|
-
Print.info('Created Components directory');
|
|
97
159
|
}
|
|
98
160
|
|
|
99
161
|
// Generar archivo components.js con los componentes detectados
|
|
100
|
-
|
|
162
|
+
const componentsForExport = Object.fromEntries(
|
|
163
|
+
Object.entries(components).map(([name, data]) => [name, data.category])
|
|
164
|
+
);
|
|
165
|
+
fs.writeFileSync(outputPath, `const components = ${JSON.stringify(componentsForExport, null, 2)};\n\nexport default components;\n`);
|
|
101
166
|
|
|
102
|
-
Print.success(`Component list updated successfully (${Object.keys(components).length} component${Object.keys(components).length !== 1 ? 's' : ''} found)`);
|
|
103
167
|
} catch (error) {
|
|
104
|
-
Print.error(`Failed to
|
|
168
|
+
Print.error(`Failed to list components: ${error.message}`);
|
|
105
169
|
Print.info('Make sure your project structure is correct');
|
|
106
170
|
}
|
|
107
171
|
}
|
|
108
172
|
|
|
109
173
|
export default listComponentsReal;
|
|
110
|
-
|
|
111
|
-
|