slicejs-cli 2.5.1 → 2.7.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/README.md +5 -2
- package/client.js +31 -27
- package/commands/Validations.js +36 -18
- package/commands/buildProduction/buildProduction.js +12 -11
- package/commands/createComponent/createComponent.js +4 -5
- package/commands/deleteComponent/deleteComponent.js +5 -5
- package/commands/doctor/doctor.js +9 -9
- package/commands/getComponent/getComponent.js +40 -51
- package/commands/init/init.js +103 -7
- package/commands/listComponents/listComponents.js +5 -3
- package/commands/startServer/startServer.js +7 -6
- package/commands/utils/PathHelper.js +58 -0
- package/commands/utils/VersionChecker.js +9 -7
- package/commands/utils/updateManager.js +377 -0
- package/package.json +1 -1
- package/post.js +17 -138
package/README.md
CHANGED
|
@@ -110,8 +110,11 @@ slice registry sync → slice sync
|
|
|
110
110
|
slice version
|
|
111
111
|
slice -v
|
|
112
112
|
|
|
113
|
-
#
|
|
114
|
-
slice update
|
|
113
|
+
# Update CLI and Framework
|
|
114
|
+
slice update # Check and prompt for updates
|
|
115
|
+
slice update --yes # Update all automatically
|
|
116
|
+
slice update --cli # Update only CLI
|
|
117
|
+
slice update --framework # Update only Framework
|
|
115
118
|
|
|
116
119
|
# Show help
|
|
117
120
|
slice --help
|
package/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
import { program } from "commander";
|
|
3
3
|
import inquirer from "inquirer";
|
|
4
4
|
import initializeProject from "./commands/init/init.js";
|
|
@@ -8,10 +8,12 @@ import deleteComponent from "./commands/deleteComponent/deleteComponent.js";
|
|
|
8
8
|
import getComponent, { listComponents as listRemoteComponents, syncComponents } from "./commands/getComponent/getComponent.js";
|
|
9
9
|
import startServer from "./commands/startServer/startServer.js";
|
|
10
10
|
import runDiagnostics from "./commands/doctor/doctor.js";
|
|
11
|
-
import versionChecker from "./commands/utils/
|
|
11
|
+
import versionChecker from "./commands/utils/VersionChecker.js";
|
|
12
|
+
import updateManager from "./commands/utils/updateManager.js";
|
|
12
13
|
import fs from "fs";
|
|
13
14
|
import path from "path";
|
|
14
15
|
import { fileURLToPath } from "url";
|
|
16
|
+
import { getConfigPath } from "./commands/utils/PathHelper.js";
|
|
15
17
|
import validations from "./commands/Validations.js";
|
|
16
18
|
import Print from "./commands/Print.js";
|
|
17
19
|
|
|
@@ -19,7 +21,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
19
21
|
|
|
20
22
|
const loadConfig = () => {
|
|
21
23
|
try {
|
|
22
|
-
const configPath =
|
|
24
|
+
const configPath = getConfigPath(import.meta.url);
|
|
23
25
|
const rawData = fs.readFileSync(configPath, "utf-8");
|
|
24
26
|
return JSON.parse(rawData);
|
|
25
27
|
} catch (error) {
|
|
@@ -36,10 +38,13 @@ const getCategories = () => {
|
|
|
36
38
|
// Function to run version check for all commands
|
|
37
39
|
async function runWithVersionCheck(commandFunction, ...args) {
|
|
38
40
|
try {
|
|
39
|
-
|
|
41
|
+
const updateInfo = await updateManager.checkForUpdates();
|
|
42
|
+
if (updateInfo && updateInfo.hasUpdates) {
|
|
43
|
+
await updateManager.checkAndPromptUpdates({});
|
|
44
|
+
}
|
|
45
|
+
|
|
40
46
|
const result = await commandFunction(...args);
|
|
41
47
|
|
|
42
|
-
// Then check for updates (non-blocking)
|
|
43
48
|
setTimeout(() => {
|
|
44
49
|
versionChecker.checkForUpdates(false);
|
|
45
50
|
}, 100);
|
|
@@ -53,7 +58,7 @@ async function runWithVersionCheck(commandFunction, ...args) {
|
|
|
53
58
|
|
|
54
59
|
const sliceClient = program;
|
|
55
60
|
|
|
56
|
-
sliceClient.version("2.
|
|
61
|
+
sliceClient.version("2.6.1").description("CLI for managing Slice.js framework components");
|
|
57
62
|
|
|
58
63
|
// INIT COMMAND
|
|
59
64
|
sliceClient
|
|
@@ -336,29 +341,27 @@ sliceClient
|
|
|
336
341
|
});
|
|
337
342
|
});
|
|
338
343
|
|
|
344
|
+
// LIST COMMAND - Quick shortcut for listing local components
|
|
345
|
+
sliceClient
|
|
346
|
+
.command("list")
|
|
347
|
+
.description("Quick list all local components (alias for component list)")
|
|
348
|
+
.action(async () => {
|
|
349
|
+
await runWithVersionCheck(() => {
|
|
350
|
+
listComponents();
|
|
351
|
+
return Promise.resolve();
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
|
|
339
355
|
// UPDATE COMMAND
|
|
340
356
|
sliceClient
|
|
341
357
|
.command("update")
|
|
342
358
|
.alias("upgrade")
|
|
343
|
-
.description("
|
|
344
|
-
.
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
if (updateInfo) {
|
|
351
|
-
if (updateInfo.cli.status === 'current' && updateInfo.framework.status === 'current') {
|
|
352
|
-
Print.success("All components are up to date!");
|
|
353
|
-
} else {
|
|
354
|
-
Print.info("Updates available - see details above");
|
|
355
|
-
}
|
|
356
|
-
} else {
|
|
357
|
-
Print.error("Could not check for updates. Please check your internet connection");
|
|
358
|
-
}
|
|
359
|
-
} catch (error) {
|
|
360
|
-
Print.error(`Checking updates: ${error.message}`);
|
|
361
|
-
}
|
|
359
|
+
.description("Update CLI and framework to latest versions")
|
|
360
|
+
.option("-y, --yes", "Skip confirmation and update all packages automatically")
|
|
361
|
+
.option("--cli", "Update only the Slice.js CLI")
|
|
362
|
+
.option("-f, --framework", "Update only the Slice.js Framework")
|
|
363
|
+
.action(async (options) => {
|
|
364
|
+
await updateManager.checkAndPromptUpdates(options);
|
|
362
365
|
});
|
|
363
366
|
|
|
364
367
|
// DOCTOR COMMAND - Diagnose project issues
|
|
@@ -391,11 +394,12 @@ Common Usage Examples:
|
|
|
391
394
|
slice browse - Browse all available components
|
|
392
395
|
slice sync - Update local components to latest versions
|
|
393
396
|
slice component create - Create new local component
|
|
397
|
+
slice list - List all local components
|
|
394
398
|
slice doctor - Run project diagnostics
|
|
395
399
|
|
|
396
400
|
Command Categories:
|
|
397
401
|
• init, dev, start - Project lifecycle (development only)
|
|
398
|
-
• get, browse, sync
|
|
402
|
+
• get, browse, sync, list - Quick shortcuts
|
|
399
403
|
• component <cmd> - Local component management
|
|
400
404
|
• registry <cmd> - Official repository operations
|
|
401
405
|
• version, update, doctor - Maintenance commands
|
|
@@ -431,4 +435,4 @@ const helpCommand = sliceClient.command("help").description("Display help inform
|
|
|
431
435
|
sliceClient.outputHelp();
|
|
432
436
|
});
|
|
433
437
|
|
|
434
|
-
program.parse();
|
|
438
|
+
program.parse();
|
package/commands/Validations.js
CHANGED
|
@@ -1,14 +1,28 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
+
import { getConfigPath, getComponentsJsPath } from './utils/PathHelper.js';
|
|
4
5
|
|
|
5
6
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
7
|
|
|
7
8
|
class Validations {
|
|
8
9
|
constructor() {
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
10
|
+
this._config = null;
|
|
11
|
+
this._categories = null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
_ensureConfig() {
|
|
15
|
+
if (!this._config) {
|
|
16
|
+
this._config = this.loadConfig();
|
|
17
|
+
if (this._config) {
|
|
18
|
+
this._categories = this._config.paths?.components;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
11
22
|
|
|
23
|
+
get config() {
|
|
24
|
+
this._ensureConfig();
|
|
25
|
+
return this._config;
|
|
12
26
|
}
|
|
13
27
|
|
|
14
28
|
isValidComponentName(componentName) {
|
|
@@ -19,36 +33,40 @@ class Validations {
|
|
|
19
33
|
|
|
20
34
|
loadConfig() {
|
|
21
35
|
try {
|
|
22
|
-
const configPath =
|
|
36
|
+
const configPath = getConfigPath(import.meta.url);
|
|
23
37
|
if (!fs.existsSync(configPath)) {
|
|
24
|
-
|
|
25
|
-
console.log('\x1b[36m', 'ℹ️ Info: Run "slice init" to initialize your project', '\x1b[0m');
|
|
38
|
+
// Return null silently - let commands handle missing config if needed
|
|
26
39
|
return null;
|
|
27
|
-
|
|
40
|
+
}
|
|
28
41
|
const rawData = fs.readFileSync(configPath, 'utf-8');
|
|
29
|
-
|
|
42
|
+
|
|
30
43
|
return JSON.parse(rawData);
|
|
31
44
|
} catch (error) {
|
|
32
45
|
console.error('\x1b[31m', `❌ Error loading configuration: ${error.message}`, '\x1b[0m');
|
|
33
|
-
console.log('\x1b[36m', 'ℹ️ Info: Check that sliceConfig.json is valid JSON', '\x1b[0m');
|
|
34
46
|
return null;
|
|
35
47
|
}
|
|
36
48
|
}
|
|
37
49
|
|
|
38
50
|
getCategories() {
|
|
39
|
-
|
|
51
|
+
this._ensureConfig();
|
|
52
|
+
return this._categories;
|
|
40
53
|
}
|
|
41
54
|
|
|
42
55
|
getCategoryPath(category) {
|
|
43
|
-
|
|
56
|
+
this._ensureConfig();
|
|
57
|
+
return this._categories && this._categories[category] ? this._categories[category].path : null;
|
|
44
58
|
}
|
|
45
59
|
|
|
46
|
-
getCategoryType(category){
|
|
47
|
-
|
|
60
|
+
getCategoryType(category) {
|
|
61
|
+
this._ensureConfig();
|
|
62
|
+
return this._categories && this._categories[category] ? this._categories[category].type : null;
|
|
48
63
|
}
|
|
49
64
|
|
|
50
65
|
isValidCategory(category) {
|
|
51
|
-
|
|
66
|
+
this._ensureConfig();
|
|
67
|
+
if (!this._categories) return { isValid: false, category: null };
|
|
68
|
+
|
|
69
|
+
const availableCategories = Object.keys(this._categories).map(cat => cat.toLowerCase());
|
|
52
70
|
|
|
53
71
|
if (availableCategories.includes(category.toLowerCase())) {
|
|
54
72
|
return { isValid: true, category };
|
|
@@ -59,17 +77,17 @@ class Validations {
|
|
|
59
77
|
|
|
60
78
|
componentExists(componentName) {
|
|
61
79
|
try {
|
|
62
|
-
const componentFilePath =
|
|
63
|
-
|
|
80
|
+
const componentFilePath = getComponentsJsPath(import.meta.url);
|
|
81
|
+
|
|
64
82
|
if (!fs.existsSync(componentFilePath)) {
|
|
65
83
|
console.error('\x1b[31m', '❌ Error: components.js not found in expected path', '\x1b[0m');
|
|
66
84
|
console.log('\x1b[36m', 'ℹ️ Info: Run "slice component list" to generate components.js', '\x1b[0m');
|
|
67
85
|
return false;
|
|
68
86
|
}
|
|
69
|
-
|
|
87
|
+
|
|
70
88
|
const fileContent = fs.readFileSync(componentFilePath, 'utf-8');
|
|
71
89
|
const components = eval(fileContent.replace('export default', '')); // Evalúa el contenido como objeto
|
|
72
|
-
|
|
90
|
+
|
|
73
91
|
return components.hasOwnProperty(componentName);
|
|
74
92
|
|
|
75
93
|
} catch (error) {
|
|
@@ -82,4 +100,4 @@ class Validations {
|
|
|
82
100
|
|
|
83
101
|
const validations = new Validations();
|
|
84
102
|
|
|
85
|
-
export default validations;
|
|
103
|
+
export default validations;
|
|
@@ -7,6 +7,7 @@ import { minify as terserMinify } from 'terser';
|
|
|
7
7
|
import { minify } from 'html-minifier-terser';
|
|
8
8
|
import CleanCSS from 'clean-css';
|
|
9
9
|
import Print from '../Print.js';
|
|
10
|
+
import { getSrcPath, getDistPath, getConfigPath } from '../utils/PathHelper.js';
|
|
10
11
|
|
|
11
12
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
13
|
|
|
@@ -15,7 +16,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
15
16
|
*/
|
|
16
17
|
const loadConfig = () => {
|
|
17
18
|
try {
|
|
18
|
-
const configPath =
|
|
19
|
+
const configPath = getConfigPath(import.meta.url);
|
|
19
20
|
const rawData = fs.readFileSync(configPath, 'utf-8');
|
|
20
21
|
return JSON.parse(rawData);
|
|
21
22
|
} catch (error) {
|
|
@@ -28,7 +29,7 @@ const loadConfig = () => {
|
|
|
28
29
|
* Verifica dependencias necesarias para el build
|
|
29
30
|
*/
|
|
30
31
|
async function checkBuildDependencies() {
|
|
31
|
-
const srcDir =
|
|
32
|
+
const srcDir = getSrcPath(import.meta.url);
|
|
32
33
|
|
|
33
34
|
if (!await fs.pathExists(srcDir)) {
|
|
34
35
|
Print.error('Source directory (/src) not found');
|
|
@@ -103,8 +104,8 @@ async function verifyBuildIntegrity(distDir) {
|
|
|
103
104
|
* Copia sliceConfig.json al directorio dist
|
|
104
105
|
*/
|
|
105
106
|
async function copySliceConfig() {
|
|
106
|
-
const srcConfig =
|
|
107
|
-
const distConfig =
|
|
107
|
+
const srcConfig = getConfigPath(import.meta.url);
|
|
108
|
+
const distConfig = getDistPath(import.meta.url, 'sliceConfig.json');
|
|
108
109
|
|
|
109
110
|
if (await fs.pathExists(srcConfig)) {
|
|
110
111
|
await fs.copy(srcConfig, distConfig);
|
|
@@ -336,7 +337,7 @@ async function minifyHTML(srcPath, distPath) {
|
|
|
336
337
|
async function createOptimizedBundle() {
|
|
337
338
|
Print.buildProgress('Creating optimized bundle...');
|
|
338
339
|
|
|
339
|
-
const mainJSPath =
|
|
340
|
+
const mainJSPath = getDistPath(import.meta.url, 'App', 'index.js');
|
|
340
341
|
|
|
341
342
|
if (await fs.pathExists(mainJSPath)) {
|
|
342
343
|
Print.success('Main bundle optimized');
|
|
@@ -389,7 +390,7 @@ async function generateBuildStats(srcDir, distDir) {
|
|
|
389
390
|
* Analiza el build sin construir
|
|
390
391
|
*/
|
|
391
392
|
async function analyzeBuild() {
|
|
392
|
-
const distDir =
|
|
393
|
+
const distDir = getDistPath(import.meta.url);
|
|
393
394
|
|
|
394
395
|
if (!await fs.pathExists(distDir)) {
|
|
395
396
|
Print.error('No build found to analyze. Run "slice build" first.');
|
|
@@ -398,7 +399,7 @@ async function analyzeBuild() {
|
|
|
398
399
|
|
|
399
400
|
Print.info('Analyzing production build...');
|
|
400
401
|
await generateBuildStats(
|
|
401
|
-
|
|
402
|
+
getSrcPath(import.meta.url),
|
|
402
403
|
distDir
|
|
403
404
|
);
|
|
404
405
|
}
|
|
@@ -413,8 +414,8 @@ export default async function buildProduction(options = {}) {
|
|
|
413
414
|
Print.title('🔨 Building Slice.js project for production...');
|
|
414
415
|
Print.newLine();
|
|
415
416
|
|
|
416
|
-
const srcDir =
|
|
417
|
-
const distDir =
|
|
417
|
+
const srcDir = getSrcPath(import.meta.url);
|
|
418
|
+
const distDir = getDistPath(import.meta.url);
|
|
418
419
|
|
|
419
420
|
if (!await fs.pathExists(srcDir)) {
|
|
420
421
|
throw new Error('Source directory not found. Run "slice init" first.');
|
|
@@ -470,7 +471,7 @@ export async function serveProductionBuild(port) {
|
|
|
470
471
|
const defaultPort = config?.server?.port || 3001;
|
|
471
472
|
const finalPort = port || defaultPort;
|
|
472
473
|
|
|
473
|
-
const distDir =
|
|
474
|
+
const distDir = getDistPath(import.meta.url);
|
|
474
475
|
|
|
475
476
|
if (!await fs.pathExists(distDir)) {
|
|
476
477
|
throw new Error('No production build found. Run "slice build" first.');
|
|
@@ -540,4 +541,4 @@ export async function buildCommand(options = {}) {
|
|
|
540
541
|
}
|
|
541
542
|
|
|
542
543
|
return success;
|
|
543
|
-
}
|
|
544
|
+
}
|
|
@@ -5,7 +5,8 @@ import path from 'path';
|
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
6
|
import Validations from '../Validations.js';
|
|
7
7
|
import Print from '../Print.js';
|
|
8
|
-
|
|
8
|
+
import { getSrcPath } from '../utils/PathHelper.js';
|
|
9
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
10
|
|
|
10
11
|
function createComponent(componentName, category) {
|
|
11
12
|
// Validación: Nombre de componente requerido
|
|
@@ -62,10 +63,8 @@ function createComponent(componentName, category) {
|
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
const categoryPath = Validations.getCategoryPath(category);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
let componentDir = path.join(__dirname, '../../../../src/', categoryPath, className);
|
|
68
|
-
componentDir = componentDir.slice(1);
|
|
66
|
+
const categoryPathClean = categoryPath ? categoryPath.replace(/^[/\\]+/, '') : '';
|
|
67
|
+
const componentDir = getSrcPath(import.meta.url, categoryPathClean, className);
|
|
69
68
|
|
|
70
69
|
try {
|
|
71
70
|
// Crear directorio del componente
|
|
@@ -2,7 +2,9 @@ import fs from 'fs-extra';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import Validations from '../Validations.js';
|
|
4
4
|
import Print from '../Print.js';
|
|
5
|
-
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import { getSrcPath } from '../utils/PathHelper.js';
|
|
7
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
8
|
|
|
7
9
|
function deleteComponent(componentName, category) {
|
|
8
10
|
// Validación: Nombre de componente requerido
|
|
@@ -31,10 +33,8 @@ function deleteComponent(componentName, category) {
|
|
|
31
33
|
category = flagCategory.category;
|
|
32
34
|
|
|
33
35
|
const categoryPath = Validations.getCategoryPath(category);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
let componentDir = path.join(__dirname, '../../../../src/', categoryPath, componentName);
|
|
37
|
-
componentDir = componentDir.slice(1);
|
|
36
|
+
const categoryPathClean = categoryPath ? categoryPath.replace(/^[/\\]+/, '') : '';
|
|
37
|
+
const componentDir = getSrcPath(import.meta.url, categoryPathClean, componentName);
|
|
38
38
|
|
|
39
39
|
// Verificar si el directorio del componente existe
|
|
40
40
|
if (!fs.existsSync(componentDir)) {
|
|
@@ -5,6 +5,7 @@ import { createServer } from 'net';
|
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
import Table from 'cli-table3';
|
|
7
7
|
import Print from '../Print.js';
|
|
8
|
+
import { getProjectRoot, getSrcPath, getApiPath, getConfigPath, getPath } from '../utils/PathHelper.js';
|
|
8
9
|
|
|
9
10
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
11
|
|
|
@@ -34,9 +35,8 @@ async function checkNodeVersion() {
|
|
|
34
35
|
* Verifica la estructura de directorios
|
|
35
36
|
*/
|
|
36
37
|
async function checkDirectoryStructure() {
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
const apiPath = path.join(projectRoot, 'api');
|
|
38
|
+
const srcPath = getSrcPath(import.meta.url);
|
|
39
|
+
const apiPath = getApiPath(import.meta.url);
|
|
40
40
|
|
|
41
41
|
const srcExists = await fs.pathExists(srcPath);
|
|
42
42
|
const apiExists = await fs.pathExists(apiPath);
|
|
@@ -63,7 +63,7 @@ async function checkDirectoryStructure() {
|
|
|
63
63
|
* Verifica sliceConfig.json
|
|
64
64
|
*/
|
|
65
65
|
async function checkConfig() {
|
|
66
|
-
const configPath =
|
|
66
|
+
const configPath = getConfigPath(import.meta.url);
|
|
67
67
|
|
|
68
68
|
if (!await fs.pathExists(configPath)) {
|
|
69
69
|
return {
|
|
@@ -101,7 +101,7 @@ async function checkConfig() {
|
|
|
101
101
|
* Verifica disponibilidad del puerto
|
|
102
102
|
*/
|
|
103
103
|
async function checkPort() {
|
|
104
|
-
const configPath =
|
|
104
|
+
const configPath = getConfigPath(import.meta.url);
|
|
105
105
|
let port = 3000;
|
|
106
106
|
|
|
107
107
|
try {
|
|
@@ -145,7 +145,7 @@ async function checkPort() {
|
|
|
145
145
|
* Verifica dependencias en package.json
|
|
146
146
|
*/
|
|
147
147
|
async function checkDependencies() {
|
|
148
|
-
const packagePath =
|
|
148
|
+
const packagePath = getPath(import.meta.url, '', 'package.json');
|
|
149
149
|
|
|
150
150
|
if (!await fs.pathExists(packagePath)) {
|
|
151
151
|
return {
|
|
@@ -189,8 +189,8 @@ async function checkDependencies() {
|
|
|
189
189
|
* Verifica integridad de componentes
|
|
190
190
|
*/
|
|
191
191
|
async function checkComponents() {
|
|
192
|
-
const configPath =
|
|
193
|
-
|
|
192
|
+
const configPath = getConfigPath(import.meta.url);
|
|
193
|
+
const projectRoot = getProjectRoot(import.meta.url);
|
|
194
194
|
|
|
195
195
|
if (!await fs.pathExists(configPath)) {
|
|
196
196
|
return {
|
|
@@ -208,7 +208,7 @@ async function checkComponents() {
|
|
|
208
208
|
let componentIssues = 0;
|
|
209
209
|
|
|
210
210
|
for (const [category, { path: compPath }] of Object.entries(componentPaths)) {
|
|
211
|
-
const fullPath =
|
|
211
|
+
const fullPath = getSrcPath(import.meta.url, compPath);
|
|
212
212
|
|
|
213
213
|
if (await fs.pathExists(fullPath)) {
|
|
214
214
|
const items = await fs.readdir(fullPath);
|
|
@@ -6,6 +6,7 @@ import { fileURLToPath } from "url";
|
|
|
6
6
|
import inquirer from "inquirer";
|
|
7
7
|
import validations from "../Validations.js";
|
|
8
8
|
import Print from "../Print.js";
|
|
9
|
+
import { getConfigPath, getComponentsJsPath, getPath } from "../utils/PathHelper.js";
|
|
9
10
|
|
|
10
11
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
12
|
|
|
@@ -19,8 +20,7 @@ const COMPONENTS_REGISTRY_URL = 'https://raw.githubusercontent.com/VKneider/slic
|
|
|
19
20
|
*/
|
|
20
21
|
const loadConfig = () => {
|
|
21
22
|
try {
|
|
22
|
-
|
|
23
|
-
const configPath = path.join(__dirname, '../../../../src/sliceConfig.json');
|
|
23
|
+
const configPath = getConfigPath(import.meta.url);
|
|
24
24
|
if (!fs.existsSync(configPath)) {
|
|
25
25
|
throw new Error('sliceConfig.json not found in src folder');
|
|
26
26
|
}
|
|
@@ -98,8 +98,7 @@ filterOfficialComponents(allComponents) {
|
|
|
98
98
|
|
|
99
99
|
async getLocalComponents() {
|
|
100
100
|
try {
|
|
101
|
-
|
|
102
|
-
const componentsPath = path.join(__dirname, '../../../../src/Components/components.js');
|
|
101
|
+
const componentsPath = getComponentsJsPath(import.meta.url);
|
|
103
102
|
|
|
104
103
|
if (!await fs.pathExists(componentsPath)) {
|
|
105
104
|
return {};
|
|
@@ -132,8 +131,7 @@ filterOfficialComponents(allComponents) {
|
|
|
132
131
|
// ✅ CORREGIDO: Usar 4 niveles para compatibilidad con node_modules
|
|
133
132
|
const isProduction = this.config?.production?.enabled === true;
|
|
134
133
|
const folderSuffix = isProduction ? 'dist' : 'src';
|
|
135
|
-
|
|
136
|
-
const componentPath = path.join(__dirname, `../../../../${folderSuffix}`, categoryPath, name);
|
|
134
|
+
const componentPath = getPath(import.meta.url, folderSuffix, categoryPath, name);
|
|
137
135
|
|
|
138
136
|
if (fs.pathExistsSync(componentPath)) {
|
|
139
137
|
updatableComponents.push({
|
|
@@ -180,43 +178,6 @@ filterOfficialComponents(allComponents) {
|
|
|
180
178
|
return components;
|
|
181
179
|
}
|
|
182
180
|
|
|
183
|
-
displayAvailableComponents() {
|
|
184
|
-
if (!this.componentsRegistry) {
|
|
185
|
-
Print.error('❌ No se pudo cargar el registro de componentes');
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
console.log('\n📚 Componentes disponibles en el repositorio oficial de Slice.js:\n');
|
|
190
|
-
|
|
191
|
-
const visualComponents = this.getAvailableComponents('Visual');
|
|
192
|
-
const serviceComponents = this.getAvailableComponents('Service');
|
|
193
|
-
|
|
194
|
-
// ✅ SIMPLIFICADO: Solo mostrar nombres sin descripciones
|
|
195
|
-
Print.info('🎨 Visual Components (UI):');
|
|
196
|
-
Object.keys(visualComponents).forEach(name => {
|
|
197
|
-
const files = visualComponents[name].files;
|
|
198
|
-
const fileIcons = files.map(file => {
|
|
199
|
-
if (file.endsWith('.js')) return '📜';
|
|
200
|
-
if (file.endsWith('.html')) return '🌐';
|
|
201
|
-
if (file.endsWith('.css')) return '🎨';
|
|
202
|
-
return '📄';
|
|
203
|
-
}).join(' ');
|
|
204
|
-
console.log(` • ${name} ${fileIcons}`);
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
Print.info('\n⚙️ Service Components (Logic):');
|
|
208
|
-
Object.keys(serviceComponents).forEach(name => {
|
|
209
|
-
console.log(` • ${name} 📜`);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
Print.newLine();
|
|
213
|
-
Print.info(`Total: ${Object.keys(visualComponents).length} Visual + ${Object.keys(serviceComponents).length} Service components`);
|
|
214
|
-
|
|
215
|
-
console.log(`\n💡 Ejemplos de uso:`);
|
|
216
|
-
console.log(`slice get Button Card Input # Obtener componentes Visual`);
|
|
217
|
-
console.log(`slice get FetchManager --service # Obtener componente Service`);
|
|
218
|
-
console.log(`slice sync # Sincronizar componentes Visual`);
|
|
219
|
-
}
|
|
220
181
|
|
|
221
182
|
async downloadComponentFiles(componentName, category, targetPath) {
|
|
222
183
|
const component = this.getAvailableComponents(category)[componentName];
|
|
@@ -270,6 +231,36 @@ filterOfficialComponents(allComponents) {
|
|
|
270
231
|
return downloadedFiles;
|
|
271
232
|
}
|
|
272
233
|
|
|
234
|
+
async updateLocalRegistrySafe(componentName, category) {
|
|
235
|
+
const componentsPath = path.join(__dirname, '../../../../src/Components/components.js');
|
|
236
|
+
try {
|
|
237
|
+
if (!await fs.pathExists(componentsPath)) {
|
|
238
|
+
const dir = path.dirname(componentsPath);
|
|
239
|
+
await fs.ensureDir(dir);
|
|
240
|
+
const initial = `const components = {};\n\nexport default components;\n`;
|
|
241
|
+
await fs.writeFile(componentsPath, initial, 'utf8');
|
|
242
|
+
}
|
|
243
|
+
const content = await fs.readFile(componentsPath, 'utf8');
|
|
244
|
+
const match = content.match(/const components = ({[\s\S]*?});/);
|
|
245
|
+
if (!match) throw new Error('Invalid components.js format in local project');
|
|
246
|
+
const componentsObj = eval('(' + match[1] + ')');
|
|
247
|
+
if (!componentsObj[componentName]) {
|
|
248
|
+
componentsObj[componentName] = category;
|
|
249
|
+
const sorted = Object.keys(componentsObj)
|
|
250
|
+
.sort()
|
|
251
|
+
.reduce((obj, key) => { obj[key] = componentsObj[key]; return obj; }, {});
|
|
252
|
+
const newContent = `const components = ${JSON.stringify(sorted, null, 2)};\n\nexport default components;\n`;
|
|
253
|
+
await fs.writeFile(componentsPath, newContent, 'utf8');
|
|
254
|
+
Print.registryUpdate(`Registered ${componentName} in local components.js`);
|
|
255
|
+
} else {
|
|
256
|
+
Print.info(`${componentName} already exists in local registry`);
|
|
257
|
+
}
|
|
258
|
+
} catch (error) {
|
|
259
|
+
Print.error(`Updating local components.js: ${error.message}`);
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
273
264
|
async updateLocalRegistry(componentName, category) {
|
|
274
265
|
// ✅ CORREGIDO: Usar 4 niveles para compatibilidad con node_modules
|
|
275
266
|
const componentsPath = path.join(__dirname, '../../../../src/Components/components.js');
|
|
@@ -331,14 +322,12 @@ filterOfficialComponents(allComponents) {
|
|
|
331
322
|
validations.config.paths.components[category];
|
|
332
323
|
|
|
333
324
|
if (hasValidConfig) {
|
|
334
|
-
// Usar validations cuando la config está disponible
|
|
335
325
|
categoryPath = validations.getCategoryPath(category);
|
|
336
326
|
} else {
|
|
337
|
-
// Usar rutas por defecto cuando no hay config (durante init o error)
|
|
338
327
|
if (category === 'Visual') {
|
|
339
|
-
categoryPath = '
|
|
328
|
+
categoryPath = 'Components/Visual';
|
|
340
329
|
} else if (category === 'Service') {
|
|
341
|
-
categoryPath = '
|
|
330
|
+
categoryPath = 'Components/Service';
|
|
342
331
|
} else {
|
|
343
332
|
throw new Error(`Unknown category: ${category}`);
|
|
344
333
|
}
|
|
@@ -347,7 +336,8 @@ filterOfficialComponents(allComponents) {
|
|
|
347
336
|
const isProduction = this.config?.production?.enabled === true;
|
|
348
337
|
const folderSuffix = isProduction ? 'dist' : 'src';
|
|
349
338
|
|
|
350
|
-
const
|
|
339
|
+
const cleanCategoryPath = categoryPath ? categoryPath.replace(/^[/\\]+/, '') : '';
|
|
340
|
+
const targetPath = getPath(import.meta.url, folderSuffix, cleanCategoryPath, componentName);
|
|
351
341
|
|
|
352
342
|
|
|
353
343
|
|
|
@@ -375,8 +365,7 @@ filterOfficialComponents(allComponents) {
|
|
|
375
365
|
// Download component files
|
|
376
366
|
const downloadedFiles = await this.downloadComponentFiles(componentName, category, targetPath);
|
|
377
367
|
|
|
378
|
-
|
|
379
|
-
await this.updateLocalRegistry(componentName, category);
|
|
368
|
+
await this.updateLocalRegistrySafe(componentName, category);
|
|
380
369
|
|
|
381
370
|
Print.success(`${componentName} installed successfully from official repository!`);
|
|
382
371
|
console.log(`📁 Location: ${folderSuffix}/${categoryPath}/${componentName}/`);
|
|
@@ -717,4 +706,4 @@ async function syncComponents(options = {}) {
|
|
|
717
706
|
}
|
|
718
707
|
|
|
719
708
|
export default getComponents;
|
|
720
|
-
export { listComponents, syncComponents, ComponentRegistry };
|
|
709
|
+
export { listComponents, syncComponents, ComponentRegistry };
|