slicejs-cli 2.3.0 → 2.3.2
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/client.js +75 -22
- package/commands/Validations.js +9 -4
- package/commands/createComponent/VisualComponentTemplate.js +33 -25
- package/commands/createComponent/createComponent.js +76 -36
- package/commands/deleteComponent/deleteComponent.js +44 -13
- package/commands/getComponent/getComponent.js +81 -31
- package/commands/listComponents/listComponents.js +41 -13
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -115,8 +115,9 @@ componentCommand
|
|
|
115
115
|
await runWithVersionCheck(async () => {
|
|
116
116
|
const categories = getCategories();
|
|
117
117
|
if (categories.length === 0) {
|
|
118
|
-
Print.error("No categories
|
|
119
|
-
Print.info("Run 'slice init' to initialize your project");
|
|
118
|
+
Print.error("No categories found in your project configuration");
|
|
119
|
+
Print.info("Run 'slice init' to initialize your project first");
|
|
120
|
+
Print.commandExample("Initialize project", "slice init");
|
|
120
121
|
return;
|
|
121
122
|
}
|
|
122
123
|
|
|
@@ -125,7 +126,13 @@ componentCommand
|
|
|
125
126
|
type: "input",
|
|
126
127
|
name: "componentName",
|
|
127
128
|
message: "Enter the component name:",
|
|
128
|
-
validate: (input) =>
|
|
129
|
+
validate: (input) => {
|
|
130
|
+
if (!input) return "Component name cannot be empty";
|
|
131
|
+
if (!/^[a-zA-Z][a-zA-Z0-9]*$/.test(input)) {
|
|
132
|
+
return "Component name must start with a letter and contain only alphanumeric characters";
|
|
133
|
+
}
|
|
134
|
+
return true;
|
|
135
|
+
},
|
|
129
136
|
},
|
|
130
137
|
{
|
|
131
138
|
type: "list",
|
|
@@ -134,25 +141,10 @@ componentCommand
|
|
|
134
141
|
choices: categories,
|
|
135
142
|
}
|
|
136
143
|
]);
|
|
137
|
-
|
|
138
|
-
if (validations.getCategoryType(answers.category) === 'Visual') {
|
|
139
|
-
const properties = await inquirer.prompt([
|
|
140
|
-
{
|
|
141
|
-
type: "input",
|
|
142
|
-
name: "properties",
|
|
143
|
-
message: "Enter the properties (comma separated):",
|
|
144
|
-
default: ""
|
|
145
|
-
},
|
|
146
|
-
]);
|
|
147
|
-
answers.properties = properties.properties
|
|
148
|
-
? properties.properties.split(",").map((prop) => prop.trim()).filter(Boolean)
|
|
149
|
-
: [];
|
|
150
|
-
} else {
|
|
151
|
-
answers.properties = [];
|
|
152
|
-
}
|
|
153
144
|
|
|
154
|
-
|
|
155
|
-
|
|
145
|
+
const result = createComponent(answers.componentName, answers.category);
|
|
146
|
+
if (result) {
|
|
147
|
+
Print.success(`Component '${answers.componentName}' created successfully in category '${answers.category}'`);
|
|
156
148
|
Print.info("Listing updated components:");
|
|
157
149
|
listComponents();
|
|
158
150
|
}
|
|
@@ -186,7 +178,68 @@ componentCommand
|
|
|
186
178
|
}
|
|
187
179
|
|
|
188
180
|
try {
|
|
189
|
-
|
|
181
|
+
// Paso 1: Seleccionar categoría
|
|
182
|
+
const categoryAnswer = await inquirer.prompt([
|
|
183
|
+
{
|
|
184
|
+
type: "list",
|
|
185
|
+
name: "category",
|
|
186
|
+
message: "Select the component category:",
|
|
187
|
+
choices: categories,
|
|
188
|
+
}
|
|
189
|
+
]);
|
|
190
|
+
|
|
191
|
+
// Paso 2: Listar componentes de esa categoría
|
|
192
|
+
const config = loadConfig();
|
|
193
|
+
if (!config) {
|
|
194
|
+
Print.error("Could not load configuration");
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const categoryPath = config.paths.components[categoryAnswer.category].path;
|
|
199
|
+
const fullPath = path.join(__dirname, "../../src", categoryPath);
|
|
200
|
+
|
|
201
|
+
if (!fs.existsSync(fullPath)) {
|
|
202
|
+
Print.error(`Category path does not exist: ${categoryPath}`);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const components = fs.readdirSync(fullPath).filter(item => {
|
|
207
|
+
const itemPath = path.join(fullPath, item);
|
|
208
|
+
return fs.statSync(itemPath).isDirectory();
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
if (components.length === 0) {
|
|
212
|
+
Print.info(`No components found in category '${categoryAnswer.category}'`);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Paso 3: Seleccionar componente a eliminar
|
|
217
|
+
const componentAnswer = await inquirer.prompt([
|
|
218
|
+
{
|
|
219
|
+
type: "list",
|
|
220
|
+
name: "componentName",
|
|
221
|
+
message: "Select the component to delete:",
|
|
222
|
+
choices: components,
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
type: "confirm",
|
|
226
|
+
name: "confirm",
|
|
227
|
+
message: (answers) => `Are you sure you want to delete '${answers.componentName}'?`,
|
|
228
|
+
default: false,
|
|
229
|
+
}
|
|
230
|
+
]);
|
|
231
|
+
|
|
232
|
+
if (!componentAnswer.confirm) {
|
|
233
|
+
Print.info("Delete operation cancelled");
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Paso 4: Eliminar el componente
|
|
238
|
+
if (deleteComponent(componentAnswer.componentName, categoryAnswer.category)) {
|
|
239
|
+
Print.success(`Component ${componentAnswer.componentName} deleted successfully`);
|
|
240
|
+
Print.info("Listing updated components:");
|
|
241
|
+
listComponents();
|
|
242
|
+
}
|
|
190
243
|
} catch (error) {
|
|
191
244
|
Print.error(`Deleting component: ${error.message}`);
|
|
192
245
|
}
|
package/commands/Validations.js
CHANGED
|
@@ -21,13 +21,16 @@ class Validations {
|
|
|
21
21
|
try {
|
|
22
22
|
const configPath = path.join(__dirname, '../../../src/sliceConfig.json');
|
|
23
23
|
if (!fs.existsSync(configPath)) {
|
|
24
|
-
|
|
24
|
+
console.error('\x1b[31m', '❌ Error: sliceConfig.json not found', '\x1b[0m');
|
|
25
|
+
console.log('\x1b[36m', 'ℹ️ Info: Run "slice init" to initialize your project', '\x1b[0m');
|
|
26
|
+
return null;
|
|
25
27
|
}
|
|
26
28
|
const rawData = fs.readFileSync(configPath, 'utf-8');
|
|
27
29
|
|
|
28
30
|
return JSON.parse(rawData);
|
|
29
31
|
} catch (error) {
|
|
30
|
-
console.error(
|
|
32
|
+
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');
|
|
31
34
|
return null;
|
|
32
35
|
}
|
|
33
36
|
}
|
|
@@ -59,7 +62,8 @@ class Validations {
|
|
|
59
62
|
const componentFilePath = path.join(__dirname, '../../../src/Components/components.js');
|
|
60
63
|
|
|
61
64
|
if (!fs.existsSync(componentFilePath)) {
|
|
62
|
-
console.error('❌
|
|
65
|
+
console.error('\x1b[31m', '❌ Error: components.js not found in expected path', '\x1b[0m');
|
|
66
|
+
console.log('\x1b[36m', 'ℹ️ Info: Run "slice component list" to generate components.js', '\x1b[0m');
|
|
63
67
|
return false;
|
|
64
68
|
}
|
|
65
69
|
|
|
@@ -69,7 +73,8 @@ class Validations {
|
|
|
69
73
|
return components.hasOwnProperty(componentName);
|
|
70
74
|
|
|
71
75
|
} catch (error) {
|
|
72
|
-
console.error('
|
|
76
|
+
console.error('\x1b[31m', `❌ Error checking component existence: ${error.message}`, '\x1b[0m');
|
|
77
|
+
console.log('\x1b[36m', 'ℹ️ Info: The components.js file may be corrupted', '\x1b[0m');
|
|
73
78
|
return false;
|
|
74
79
|
}
|
|
75
80
|
}
|
|
@@ -1,28 +1,35 @@
|
|
|
1
1
|
export default class componentTemplates{
|
|
2
2
|
|
|
3
|
-
static visual(componentName
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
static visual(componentName){
|
|
4
|
+
return `export default class ${componentName} extends HTMLElement {
|
|
5
|
+
|
|
6
|
+
static props = {
|
|
7
|
+
// Define your component props here
|
|
8
|
+
// Example:
|
|
9
|
+
/*
|
|
10
|
+
"value": {
|
|
11
|
+
type: 'string',
|
|
12
|
+
default: 'Button',
|
|
13
|
+
required: false
|
|
14
|
+
},
|
|
15
|
+
*/
|
|
7
16
|
}
|
|
8
17
|
|
|
9
|
-
set ${prop}(value) {
|
|
10
|
-
this._${prop} = value;
|
|
11
|
-
}
|
|
12
|
-
`).join('\n');
|
|
13
|
-
|
|
14
|
-
return `export default class ${componentName} extends HTMLElement {
|
|
15
18
|
constructor(props) {
|
|
16
19
|
super();
|
|
17
20
|
slice.attachTemplate(this);
|
|
18
|
-
|
|
19
21
|
slice.controller.setComponentProps(this, props);
|
|
20
|
-
this.debuggerProps = [${props.map(prop => `"${prop}"`).join(',')}];
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
init() {
|
|
24
|
+
init() {
|
|
25
|
+
// Component initialization logic (can be async)
|
|
26
|
+
}
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
update() {
|
|
29
|
+
// Component update logic (can be async)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Add your custom methods here
|
|
26
33
|
}
|
|
27
34
|
|
|
28
35
|
customElements.define("slice-${componentName.toLowerCase()}", ${componentName});
|
|
@@ -30,18 +37,19 @@ customElements.define("slice-${componentName.toLowerCase()}", ${componentName});
|
|
|
30
37
|
}
|
|
31
38
|
|
|
32
39
|
static service(componentName) {
|
|
33
|
-
|
|
34
|
-
|
|
35
40
|
return `export default class ${componentName} {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
41
|
+
constructor(props) {
|
|
42
|
+
// Initialize service with props
|
|
43
|
+
this.props = props || {};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
init() {
|
|
47
|
+
// Service initialization logic (can be async)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Add your service methods here
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
45
53
|
}
|
|
46
54
|
}
|
|
47
55
|
|
|
@@ -7,29 +7,39 @@ import Validations from '../Validations.js';
|
|
|
7
7
|
import Print from '../Print.js';
|
|
8
8
|
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
9
9
|
|
|
10
|
-
function createComponent(componentName, category
|
|
10
|
+
function createComponent(componentName, category) {
|
|
11
|
+
// Validación: Nombre de componente requerido
|
|
11
12
|
if (!componentName) {
|
|
12
13
|
Print.error('Component name is required');
|
|
13
|
-
|
|
14
|
+
Print.commandExample("Create a component", "slice component create");
|
|
15
|
+
return false;
|
|
14
16
|
}
|
|
15
17
|
|
|
18
|
+
// Validación: Nombre de componente válido
|
|
16
19
|
if (!Validations.isValidComponentName(componentName)) {
|
|
17
|
-
Print.error(
|
|
18
|
-
|
|
20
|
+
Print.error(`Invalid component name: '${componentName}'`);
|
|
21
|
+
Print.info('Component name must start with a letter and contain only alphanumeric characters');
|
|
22
|
+
Print.commandExample("Valid names", "Button, UserCard, NavBar");
|
|
23
|
+
Print.commandExample("Invalid names", "1Button, user-card, Nav_Bar");
|
|
24
|
+
return false;
|
|
19
25
|
}
|
|
20
26
|
|
|
27
|
+
// Validación: Componente ya existe
|
|
21
28
|
if(Validations.componentExists(componentName)){
|
|
22
|
-
Print.error(`Component '${componentName}' already exists
|
|
23
|
-
|
|
29
|
+
Print.error(`Component '${componentName}' already exists in your project`);
|
|
30
|
+
Print.info('Please use a different name or delete the existing component first');
|
|
31
|
+
Print.commandExample("Delete component", "slice component delete");
|
|
32
|
+
return false;
|
|
24
33
|
}
|
|
25
34
|
|
|
35
|
+
// Validación: Categoría válida
|
|
26
36
|
let flagCategory = Validations.isValidCategory(category);
|
|
27
37
|
|
|
28
|
-
|
|
29
|
-
|
|
30
38
|
if (!flagCategory.isValid) {
|
|
31
|
-
Print.error(
|
|
32
|
-
|
|
39
|
+
Print.error(`Invalid category: '${category}'`);
|
|
40
|
+
const availableCategories = Object.keys(Validations.getCategories()).join(', ');
|
|
41
|
+
Print.info(`Available categories: ${availableCategories}`);
|
|
42
|
+
return false;
|
|
33
43
|
}
|
|
34
44
|
category = flagCategory.category;
|
|
35
45
|
|
|
@@ -40,46 +50,76 @@ function createComponent(componentName, category, properties) {
|
|
|
40
50
|
|
|
41
51
|
const type = Validations.getCategoryType(category);
|
|
42
52
|
|
|
43
|
-
|
|
44
|
-
if(type==='Visual'){
|
|
45
|
-
template = componentTemplates.visual(className
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if(type==='Service'){
|
|
53
|
+
// Generar template según el tipo
|
|
54
|
+
if(type === 'Visual'){
|
|
55
|
+
template = componentTemplates.visual(className);
|
|
56
|
+
} else if(type === 'Service'){
|
|
49
57
|
template = componentTemplates.service(className);
|
|
50
|
-
|
|
58
|
+
} else {
|
|
59
|
+
Print.error(`Unsupported component type: '${type}'`);
|
|
60
|
+
Print.info('Only Visual and Service components are currently supported');
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
51
63
|
|
|
52
64
|
const categoryPath = Validations.getCategoryPath(category);
|
|
53
65
|
|
|
54
|
-
|
|
55
|
-
// Determinar la ruta del archivo
|
|
66
|
+
// Determinar la ruta del directorio del componente
|
|
56
67
|
let componentDir = path.join(__dirname, '../../../../src/', categoryPath, className);
|
|
57
|
-
componentDir=componentDir.slice(1);
|
|
58
|
-
fs.ensureDirSync(componentDir);
|
|
68
|
+
componentDir = componentDir.slice(1);
|
|
59
69
|
|
|
70
|
+
try {
|
|
71
|
+
// Crear directorio del componente
|
|
72
|
+
fs.ensureDirSync(componentDir);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
Print.error(`Failed to create component directory: '${componentDir}'`);
|
|
75
|
+
Print.info(`Error details: ${error.message}`);
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
60
78
|
|
|
61
79
|
// Determinar la ruta del archivo
|
|
62
80
|
let componentPath = path.join(componentDir, fileName);
|
|
63
81
|
|
|
64
|
-
|
|
65
|
-
// Verificar si el archivo ya existe
|
|
82
|
+
// Verificar si el archivo ya existe (doble verificación)
|
|
66
83
|
if (fs.existsSync(componentPath)) {
|
|
67
|
-
Print.error(`Component '${
|
|
68
|
-
|
|
84
|
+
Print.error(`Component file already exists at: '${componentPath}'`);
|
|
85
|
+
Print.info('This component may have been created outside the CLI');
|
|
86
|
+
return false;
|
|
69
87
|
}
|
|
70
88
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
89
|
+
try {
|
|
90
|
+
// Escribir el código del componente en el archivo
|
|
91
|
+
fs.writeFileSync(componentPath, template);
|
|
92
|
+
|
|
93
|
+
// Si es Visual, crear archivos adicionales (CSS y HTML)
|
|
94
|
+
if(type === 'Visual'){
|
|
95
|
+
const cssPath = `${componentDir}/${className}.css`;
|
|
96
|
+
const htmlPath = `${componentDir}/${className}.html`;
|
|
97
|
+
|
|
98
|
+
fs.writeFileSync(cssPath, '/* Styles for ' + componentName + ' component */\n');
|
|
99
|
+
fs.writeFileSync(htmlPath, `<div class="${componentName.toLowerCase()}">\n ${componentName}\n</div>`);
|
|
100
|
+
|
|
101
|
+
Print.info(`Created files: ${fileName}, ${className}.css, ${className}.html`);
|
|
102
|
+
} else {
|
|
103
|
+
Print.info(`Created file: ${fileName}`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return true;
|
|
107
|
+
} catch (error) {
|
|
108
|
+
Print.error(`Failed to create component files`);
|
|
109
|
+
Print.info(`Error details: ${error.message}`);
|
|
110
|
+
|
|
111
|
+
// Intentar limpiar archivos parcialmente creados
|
|
112
|
+
try {
|
|
113
|
+
if (fs.existsSync(componentDir)) {
|
|
114
|
+
fs.removeSync(componentDir);
|
|
115
|
+
Print.info('Cleaned up partial files');
|
|
116
|
+
}
|
|
117
|
+
} catch (cleanupError) {
|
|
118
|
+
Print.warning('Could not clean up partial files. You may need to delete them manually');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return false;
|
|
79
122
|
}
|
|
80
|
-
|
|
81
|
-
Print.success(`Component '${componentName}' created successfully.`);
|
|
82
|
-
return true;
|
|
83
123
|
}
|
|
84
124
|
|
|
85
125
|
|
|
@@ -5,42 +5,73 @@ import Print from '../Print.js';
|
|
|
5
5
|
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
6
6
|
|
|
7
7
|
function deleteComponent(componentName, category) {
|
|
8
|
+
// Validación: Nombre de componente requerido
|
|
8
9
|
if (!componentName) {
|
|
9
|
-
Print.error('Component name is required');
|
|
10
|
-
|
|
10
|
+
Print.error('Component name is required to delete');
|
|
11
|
+
Print.commandExample("Delete a component", "slice component delete");
|
|
12
|
+
return false;
|
|
11
13
|
}
|
|
12
14
|
|
|
15
|
+
// Validación: Nombre de componente válido
|
|
13
16
|
if (!Validations.isValidComponentName(componentName)) {
|
|
14
|
-
Print.error(
|
|
15
|
-
|
|
17
|
+
Print.error(`Invalid component name: '${componentName}'`);
|
|
18
|
+
Print.info('Component name must start with a letter and contain only alphanumeric characters');
|
|
19
|
+
return false;
|
|
16
20
|
}
|
|
17
21
|
|
|
22
|
+
// Validación: Categoría válida
|
|
18
23
|
let flagCategory = Validations.isValidCategory(category);
|
|
19
24
|
|
|
20
25
|
if (!flagCategory.isValid) {
|
|
21
|
-
Print.error(
|
|
22
|
-
|
|
26
|
+
Print.error(`Invalid category: '${category}'`);
|
|
27
|
+
const availableCategories = Object.keys(Validations.getCategories()).join(', ');
|
|
28
|
+
Print.info(`Available categories: ${availableCategories}`);
|
|
29
|
+
return false;
|
|
23
30
|
}
|
|
24
31
|
category = flagCategory.category;
|
|
25
32
|
|
|
26
33
|
const categoryPath = Validations.getCategoryPath(category);
|
|
27
34
|
|
|
28
|
-
|
|
29
35
|
// Construir la ruta del directorio del componente
|
|
30
36
|
let componentDir = path.join(__dirname, '../../../../src/', categoryPath, componentName);
|
|
31
37
|
componentDir = componentDir.slice(1);
|
|
32
38
|
|
|
33
39
|
// Verificar si el directorio del componente existe
|
|
34
40
|
if (!fs.existsSync(componentDir)) {
|
|
35
|
-
Print.error(`Component '${componentName}' does not exist
|
|
36
|
-
|
|
41
|
+
Print.error(`Component '${componentName}' does not exist in category '${category}'`);
|
|
42
|
+
Print.info('Make sure you selected the correct category');
|
|
43
|
+
Print.commandExample("List components", "slice component list");
|
|
44
|
+
return false;
|
|
37
45
|
}
|
|
38
46
|
|
|
39
|
-
//
|
|
40
|
-
|
|
47
|
+
// Verificar si es un directorio
|
|
48
|
+
try {
|
|
49
|
+
const stats = fs.statSync(componentDir);
|
|
50
|
+
if (!stats.isDirectory()) {
|
|
51
|
+
Print.error(`'${componentName}' is not a valid component directory`);
|
|
52
|
+
Print.info('Components must be stored in directories');
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
} catch (error) {
|
|
56
|
+
Print.error(`Failed to access component directory: '${componentDir}'`);
|
|
57
|
+
Print.info(`Error details: ${error.message}`);
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
41
60
|
|
|
42
|
-
|
|
43
|
-
|
|
61
|
+
// Intentar eliminar el directorio del componente y su contenido
|
|
62
|
+
try {
|
|
63
|
+
const files = fs.readdirSync(componentDir);
|
|
64
|
+
Print.info(`Deleting ${files.length} file(s) from component directory...`);
|
|
65
|
+
|
|
66
|
+
fs.removeSync(componentDir);
|
|
67
|
+
return true;
|
|
68
|
+
} catch (error) {
|
|
69
|
+
Print.error(`Failed to delete component '${componentName}'`);
|
|
70
|
+
Print.info(`Error details: ${error.message}`);
|
|
71
|
+
Print.warning('You may need to delete the component files manually');
|
|
72
|
+
Print.info(`Component location: ${componentDir}`);
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
44
75
|
}
|
|
45
76
|
|
|
46
77
|
export default deleteComponent;
|
|
@@ -39,32 +39,62 @@ class ComponentRegistry {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
async loadRegistry() {
|
|
42
|
-
|
|
42
|
+
Print.info('Loading component registry from official repository...');
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const response = await fetch(COMPONENTS_REGISTRY_URL);
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (!response.ok) {
|
|
48
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
49
|
-
}
|
|
47
|
+
if (!response.ok) {
|
|
48
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
49
|
+
}
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
const content = await response.text();
|
|
52
|
+
|
|
53
|
+
// Parse the components.js file content
|
|
54
|
+
const match = content.match(/const components = ({[\s\S]*?});/);
|
|
55
|
+
if (!match) {
|
|
56
|
+
throw new Error('Invalid components.js format from repository');
|
|
57
|
+
}
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
const allComponents = eval('(' + match[1] + ')');
|
|
60
|
+
|
|
61
|
+
// ✅ NUEVO: FILTRAR solo componentes Visual y Service
|
|
62
|
+
this.componentsRegistry = this.filterOfficialComponents(allComponents);
|
|
63
|
+
|
|
64
|
+
Print.success('Component registry loaded successfully');
|
|
65
|
+
|
|
66
|
+
} catch (error) {
|
|
67
|
+
Print.error(`Loading component registry: ${error.message}`);
|
|
68
|
+
Print.info('Check your internet connection and repository accessibility');
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Filtra el registry para incluir SOLO componentes de categorías Visual y Service
|
|
75
|
+
* Excluye AppComponents y cualquier otra categoría
|
|
76
|
+
* @param {object} allComponents - Objeto con todos los componentes del registry
|
|
77
|
+
* @returns {object} - Objeto filtrado solo con Visual y Service
|
|
78
|
+
*/
|
|
79
|
+
filterOfficialComponents(allComponents) {
|
|
80
|
+
const filtered = {};
|
|
81
|
+
let excludedCount = 0;
|
|
82
|
+
|
|
83
|
+
Object.entries(allComponents).forEach(([name, category]) => {
|
|
84
|
+
// Solo incluir componentes de categoría Visual o Service
|
|
85
|
+
if (category === 'Visual' || category === 'Service') {
|
|
86
|
+
filtered[name] = category;
|
|
87
|
+
} else {
|
|
88
|
+
excludedCount++;
|
|
66
89
|
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (excludedCount > 0) {
|
|
93
|
+
Print.info(`Filtered out ${excludedCount} non-Visual/Service components from registry`);
|
|
67
94
|
}
|
|
95
|
+
|
|
96
|
+
return filtered;
|
|
97
|
+
}
|
|
68
98
|
|
|
69
99
|
async getLocalComponents() {
|
|
70
100
|
try {
|
|
@@ -287,19 +317,39 @@ class ComponentRegistry {
|
|
|
287
317
|
}
|
|
288
318
|
|
|
289
319
|
async installComponent(componentName, category, force = false) {
|
|
290
|
-
|
|
320
|
+
const availableComponents = this.getAvailableComponents(category);
|
|
321
|
+
|
|
322
|
+
if (!availableComponents[componentName]) {
|
|
323
|
+
throw new Error(`Componente '${componentName}' no encontrado en la categoría '${category}' del repositorio oficial`);
|
|
324
|
+
}
|
|
291
325
|
|
|
292
|
-
|
|
293
|
-
|
|
326
|
+
// ✅ MEJORADO: Detectar si validations tiene acceso a la configuración
|
|
327
|
+
let categoryPath;
|
|
328
|
+
const hasValidConfig = validations.config &&
|
|
329
|
+
validations.config.paths &&
|
|
330
|
+
validations.config.paths.components &&
|
|
331
|
+
validations.config.paths.components[category];
|
|
332
|
+
|
|
333
|
+
if (hasValidConfig) {
|
|
334
|
+
// Usar validations cuando la config está disponible
|
|
335
|
+
categoryPath = validations.getCategoryPath(category);
|
|
336
|
+
} else {
|
|
337
|
+
// Usar rutas por defecto cuando no hay config (durante init o error)
|
|
338
|
+
if (category === 'Visual') {
|
|
339
|
+
categoryPath = '/Components/Visual';
|
|
340
|
+
} else if (category === 'Service') {
|
|
341
|
+
categoryPath = '/Components/Service';
|
|
342
|
+
} else {
|
|
343
|
+
throw new Error(`Unknown category: ${category}`);
|
|
294
344
|
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const isProduction = this.config?.production?.enabled === true;
|
|
348
|
+
const folderSuffix = isProduction ? 'dist' : 'src';
|
|
349
|
+
|
|
350
|
+
const targetPath = path.join(__dirname, `../../../../${folderSuffix}`, categoryPath, componentName);
|
|
351
|
+
|
|
295
352
|
|
|
296
|
-
const categoryPath = validations.getCategoryPath(category);
|
|
297
|
-
|
|
298
|
-
// ✅ CORREGIDO: Usar 4 niveles para compatibilidad con node_modules
|
|
299
|
-
const isProduction = this.config?.production?.enabled === true;
|
|
300
|
-
const folderSuffix = isProduction ? 'dist' : 'src';
|
|
301
|
-
|
|
302
|
-
const targetPath = path.join(__dirname, `../../../../${folderSuffix}`, categoryPath, componentName);
|
|
303
353
|
|
|
304
354
|
// Check if component already exists
|
|
305
355
|
if (await fs.pathExists(targetPath) && !force) {
|
|
@@ -12,10 +12,16 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
12
12
|
const loadConfig = () => {
|
|
13
13
|
try {
|
|
14
14
|
const configPath = path.join(__dirname, '../../../../src/sliceConfig.json');
|
|
15
|
+
if (!fs.existsSync(configPath)) {
|
|
16
|
+
Print.error('sliceConfig.json not found');
|
|
17
|
+
Print.info('Run "slice init" to initialize your project');
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
15
20
|
const rawData = fs.readFileSync(configPath, 'utf-8');
|
|
16
21
|
return JSON.parse(rawData);
|
|
17
22
|
} catch (error) {
|
|
18
|
-
|
|
23
|
+
Print.error(`Failed to load configuration: ${error.message}`);
|
|
24
|
+
Print.info('Check that sliceConfig.json is valid JSON');
|
|
19
25
|
return null;
|
|
20
26
|
}
|
|
21
27
|
};
|
|
@@ -27,10 +33,14 @@ const loadConfig = () => {
|
|
|
27
33
|
*/
|
|
28
34
|
const listComponents = (folderPath) => {
|
|
29
35
|
try {
|
|
30
|
-
|
|
36
|
+
if (!fs.existsSync(folderPath)) {
|
|
37
|
+
Print.warning(`Component directory not found: ${folderPath}`);
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
const result = fs.readdirSync(folderPath);
|
|
31
41
|
return result;
|
|
32
42
|
} catch (error) {
|
|
33
|
-
|
|
43
|
+
Print.error(`Failed to read directory ${folderPath}: ${error.message}`);
|
|
34
44
|
return [];
|
|
35
45
|
}
|
|
36
46
|
};
|
|
@@ -66,16 +76,34 @@ const getComponents = () => {
|
|
|
66
76
|
};
|
|
67
77
|
|
|
68
78
|
function listComponentsReal(){
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
try {
|
|
80
|
+
// Obtener componentes dinámicamente
|
|
81
|
+
const components = getComponents();
|
|
82
|
+
|
|
83
|
+
if (Object.keys(components).length === 0) {
|
|
84
|
+
Print.warning('No components found in your project');
|
|
85
|
+
Print.info('Create your first component with "slice component create"');
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Ruta donde se generará components.js
|
|
90
|
+
const outputPath = path.join(__dirname, '../../../../src/Components/components.js');
|
|
91
|
+
|
|
92
|
+
// Asegurar que el directorio existe
|
|
93
|
+
const outputDir = path.dirname(outputPath);
|
|
94
|
+
if (!fs.existsSync(outputDir)) {
|
|
95
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
96
|
+
Print.info('Created Components directory');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Generar archivo components.js con los componentes detectados
|
|
100
|
+
fs.writeFileSync(outputPath, `const components = ${JSON.stringify(components, null, 2)};\n\nexport default components;\n`);
|
|
101
|
+
|
|
102
|
+
Print.success(`Component list updated successfully (${Object.keys(components).length} component${Object.keys(components).length !== 1 ? 's' : ''} found)`);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
Print.error(`Failed to update component list: ${error.message}`);
|
|
105
|
+
Print.info('Make sure your project structure is correct');
|
|
106
|
+
}
|
|
79
107
|
}
|
|
80
108
|
|
|
81
109
|
export default listComponentsReal;
|