slicejs-cli 2.0.14 → 2.1.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/client.js CHANGED
@@ -5,16 +5,16 @@ import initializeProject from "./commands/init/init.js";
5
5
  import createComponent from "./commands/createComponent/createComponent.js";
6
6
  import listComponents from "./commands/listComponents/listComponents.js";
7
7
  import deleteComponent from "./commands/deleteComponent/deleteComponent.js";
8
+ import getComponent, { listComponents as listRemoteComponents, syncComponents } from "./commands/getComponent/getComponent.js";
9
+ import versionChecker from "./commands/utils/versionChecker.js";
8
10
  import fs from "fs";
9
11
  import path from "path";
10
12
  import { fileURLToPath } from "url";
11
13
  import validations from "./commands/Validations.js";
12
-
14
+ import Print from "./commands/Print.js";
13
15
 
14
16
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
17
 
16
-
17
-
18
18
  const loadConfig = () => {
19
19
  try {
20
20
  const configPath = path.join(__dirname, "../../src/sliceConfig.json");
@@ -31,118 +31,257 @@ const getCategories = () => {
31
31
  return config && config.paths?.components ? Object.keys(config.paths.components) : [];
32
32
  };
33
33
 
34
- const sliceClient = program;
34
+ // Function to run version check for all commands
35
+ async function runWithVersionCheck(commandFunction, ...args) {
36
+ // Run the command first
37
+ const result = await commandFunction(...args);
38
+
39
+ // Then check for updates (non-blocking)
40
+ setTimeout(() => {
41
+ versionChecker.checkForUpdates(false);
42
+ }, 100);
43
+
44
+ return result;
45
+ }
35
46
 
36
- sliceClient.version("1.0.0").description("CLI for managing framework components");
47
+ const sliceClient = program;
37
48
 
38
- // COMPONENT COMMAND GROUP
39
- const componentCommand = sliceClient.command("component").description("Manage components");
49
+ sliceClient.version("2.1.0").description("CLI for managing Slice.js framework components");
40
50
 
41
- //create init command
51
+ // INIT COMMAND
42
52
  sliceClient
43
53
  .command("init")
44
- .description("Initialize a new SliceJS project")
45
- .action(() => {
46
- initializeProject();
54
+ .description("Initialize a new Slice.js project")
55
+ .action(async () => {
56
+ await runWithVersionCheck(() => {
57
+ initializeProject();
58
+ return Promise.resolve();
59
+ });
47
60
  });
48
61
 
49
- // CREATE COMPONENT
62
+ // VERSION COMMAND
63
+ sliceClient
64
+ .command("version")
65
+ .alias("v")
66
+ .description("Show version information and check for updates")
67
+ .action(async () => {
68
+ await versionChecker.showVersionInfo();
69
+ });
70
+
71
+ // COMPONENT COMMAND GROUP - For local component management
72
+ const componentCommand = sliceClient.command("component").alias("comp").description("Manage local project components");
73
+
74
+ // CREATE LOCAL COMPONENT
50
75
  componentCommand
51
76
  .command("create")
52
- .description("Create a new component")
77
+ .alias("new")
78
+ .description("Create a new component in your local project")
53
79
  .action(async () => {
54
- const categories = getCategories();
55
- if (categories.length === 0) {
56
- console.error("No categories available. Check your configuration.");
57
- return;
58
- }
80
+ await runWithVersionCheck(async () => {
81
+ const categories = getCategories();
82
+ if (categories.length === 0) {
83
+ Print.error("No categories available. Check your configuration.");
84
+ return;
85
+ }
86
+
87
+ const answers = await inquirer.prompt([
88
+ {
89
+ type: "input",
90
+ name: "componentName",
91
+ message: "Enter the component name:",
92
+ validate: (input) => (input ? true : "Component name cannot be empty"),
93
+ },
94
+ {
95
+ type: "list",
96
+ name: "category",
97
+ message: "Select the component category:",
98
+ choices: categories,
99
+ }])
59
100
 
60
- const answers = await inquirer.prompt([
61
- {
62
- type: "input",
63
- name: "componentName",
64
- message: "Enter the component name:",
65
- validate: (input) => (input ? true : "Component name cannot be empty"),
66
- },
67
- {
68
- type: "list",
69
- name: "category",
70
- message: "Select the component category:",
71
- choices: categories,
72
- }])
73
-
74
- if(validations.getCategoryType(answers.category)==='Visual'){
75
- const properties = await inquirer.prompt([
76
- {
77
- type: "input",
78
- name: "properties",
79
- message: "Enter the properties (comma separated):"
80
- },
81
- ]);
82
- answers.properties = properties.properties.split(",").map((prop) => prop.trim());
83
- } else {
84
- answers.properties = [];
101
+ if(validations.getCategoryType(answers.category)==='Visual'){
102
+ const properties = await inquirer.prompt([
103
+ {
104
+ type: "input",
105
+ name: "properties",
106
+ message: "Enter the properties (comma separated):"
107
+ },
108
+ ]);
109
+ answers.properties = properties.properties.split(",").map((prop) => prop.trim());
110
+ } else {
111
+ answers.properties = [];
112
+ }
113
+
114
+ if (createComponent(answers.componentName, answers.category, answers.properties)) {
115
+ listComponents();
85
116
  }
86
-
87
- if (createComponent(answers.componentName, answers.category, answers.properties)) {
88
- listComponents();
89
- }
117
+ });
90
118
  });
91
119
 
120
+ // LIST LOCAL COMPONENTS
121
+ componentCommand
122
+ .command("list")
123
+ .alias("ls")
124
+ .description("List all components in your local project")
125
+ .action(async () => {
126
+ await runWithVersionCheck(() => {
127
+ listComponents();
128
+ return Promise.resolve();
129
+ });
130
+ });
92
131
 
93
- // DELETE COMPONENT
132
+ // DELETE LOCAL COMPONENT
94
133
  componentCommand
95
134
  .command("delete")
96
- .description("Delete an existing component")
135
+ .alias("remove")
136
+ .description("Delete a component from your local project")
97
137
  .action(async () => {
98
- const categories = getCategories();
99
- if (categories.length === 0) {
100
- console.error("No categories available. Check your configuration.");
101
- return;
102
- }
138
+ await runWithVersionCheck(async () => {
139
+ const categories = getCategories();
140
+ if (categories.length === 0) {
141
+ Print.error("No categories available. Check your configuration.");
142
+ return;
143
+ }
144
+
145
+ deleteComponent();
146
+ });
147
+ });
148
+
149
+ // REGISTRY COMMAND GROUP - For component registry operations
150
+ const registryCommand = sliceClient.command("registry").alias("reg").description("Manage components from official Slice.js repository");
151
+
152
+ // GET COMPONENTS FROM REGISTRY
153
+ registryCommand
154
+ .command("get [components...]")
155
+ .description("Download and install components from official repository")
156
+ .option("-f, --force", "Force overwrite existing components")
157
+ .option("-s, --service", "Install Service components instead of Visual")
158
+ .action(async (components, options) => {
159
+ await runWithVersionCheck(async () => {
160
+ await getComponent(components, {
161
+ force: options.force,
162
+ service: options.service
163
+ });
164
+ });
165
+ });
103
166
 
104
- const answers = await inquirer.prompt([
105
- {
106
- type: "input",
107
- name: "componentName",
108
- message: "Enter the component name to delete:",
109
- validate: (input) => (input ? true : "Component name cannot be empty"),
110
- },
111
- {
112
- type: "list",
113
- name: "category",
114
- message: "Select the component category:",
115
- choices: categories,
116
- },
117
- ]);
118
-
119
- const confirm = await inquirer.prompt([
120
- {
121
- type: "confirm",
122
- name: "confirmation",
123
- message: `Are you sure you want to delete ${answers.componentName}?`,
124
- },
125
- ]);
126
-
127
- if (!confirm.confirmation) {
167
+ // LIST REGISTRY COMPONENTS
168
+ registryCommand
169
+ .command("list")
170
+ .alias("ls")
171
+ .description("List all available components in the official repository")
172
+ .action(async () => {
173
+ await runWithVersionCheck(async () => {
174
+ await listRemoteComponents();
175
+ });
176
+ });
177
+
178
+ // SYNC COMPONENTS FROM REGISTRY
179
+ registryCommand
180
+ .command("sync")
181
+ .description("Update all local components to latest versions from repository")
182
+ .option("-f, --force", "Force update without confirmation")
183
+ .action(async (options) => {
184
+ await runWithVersionCheck(async () => {
185
+ await syncComponents({
186
+ force: options.force
187
+ });
188
+ });
189
+ });
190
+
191
+ // SHORTCUTS - Top-level convenient commands
192
+ sliceClient
193
+ .command("get [components...]")
194
+ .description("🚀 Quick install components from registry (shortcut for registry get)")
195
+ .option("-f, --force", "Force overwrite existing components")
196
+ .option("-s, --service", "Install Service components instead of Visual")
197
+ .action(async (components, options) => {
198
+ await runWithVersionCheck(async () => {
199
+ if (!components || components.length === 0) {
200
+ Print.info("💡 Tip: Use 'slice registry list' to see available components");
201
+ Print.info("📖 Usage examples:");
202
+ console.log(" slice get Button Card Input");
203
+ console.log(" slice get FetchManager --service");
204
+ console.log(" slice registry list");
205
+ return;
206
+ }
128
207
 
129
- return;
130
- }
131
-
208
+ await getComponent(components, {
209
+ force: options.force,
210
+ service: options.service
211
+ });
212
+ });
213
+ });
132
214
 
133
- if (deleteComponent(answers.componentName, answers.category)) {
134
- listComponents();
135
- }
215
+ sliceClient
216
+ .command("browse")
217
+ .description("📚 Quick browse available components (shortcut for registry list)")
218
+ .action(async () => {
219
+ await runWithVersionCheck(async () => {
220
+ await listRemoteComponents();
221
+ });
222
+ });
136
223
 
224
+ sliceClient
225
+ .command("sync")
226
+ .description("🔄 Quick sync local components (shortcut for registry sync)")
227
+ .option("-f, --force", "Force update without confirmation")
228
+ .action(async (options) => {
229
+ await runWithVersionCheck(async () => {
230
+ await syncComponents({
231
+ force: options.force
232
+ });
233
+ });
234
+ });
137
235
 
236
+ // UPDATE COMMAND
237
+ sliceClient
238
+ .command("update")
239
+ .alias("upgrade")
240
+ .description("Check for and show available updates for CLI and framework")
241
+ .action(async () => {
242
+ Print.info("🔄 Checking for updates...");
243
+ const updateInfo = await versionChecker.checkForUpdates(false);
244
+
245
+ if (updateInfo) {
246
+ if (updateInfo.cli.status === 'current' && updateInfo.framework.status === 'current') {
247
+ Print.success("✅ All components are up to date!");
248
+ }
249
+ } else {
250
+ Print.warning("⚠️ Could not check for updates. Please check your internet connection.");
251
+ }
138
252
  });
139
253
 
140
- // LIST COMPONENTS
141
- componentCommand
142
- .command("list")
143
- .description("List all components")
144
- .action(() => {
145
- listComponents();
254
+ // Enhanced help
255
+ sliceClient
256
+ .option("--no-version-check", "Skip version check for this command")
257
+ .configureHelp({
258
+ sortSubcommands: true,
259
+ subcommandTerm: (cmd) => cmd.name() + ' ' + cmd.usage()
146
260
  });
147
261
 
148
- sliceClient.parse(process.argv);
262
+ // Custom help
263
+ sliceClient.addHelpText('after', `
264
+ 💡 Common Usage Examples:
265
+ slice init - Initialize new Slice.js project
266
+ slice get Button Card Input - Install Visual components from registry
267
+ slice get FetchManager -s - Install Service component from registry
268
+ slice browse - Browse all available components
269
+ slice sync - Update local components to latest versions
270
+ slice component create - Create new local component
271
+ slice update - Check for CLI/framework updates
272
+
273
+ 📚 Command Categories:
274
+ • init, version, update - Project setup and maintenance
275
+ • get, browse, sync - Quick registry shortcuts
276
+ • component <cmd> - Local component management
277
+ • registry <cmd> - Official repository operations
278
+
279
+ 🔗 More info: https://slice-js-docs.vercel.app/
280
+ `);
281
+
282
+ // Default action
283
+ if (!process.argv.slice(2).length) {
284
+ program.outputHelp();
285
+ }
286
+
287
+ program.parse();
@@ -0,0 +1,586 @@
1
+ // commands/getComponent/getComponent.js
2
+
3
+ import fs from "fs-extra";
4
+ import path from "path";
5
+ import { fileURLToPath } from "url";
6
+ import inquirer from "inquirer";
7
+ import validations from "../Validations.js";
8
+ import Print from "../Print.js";
9
+
10
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
+
12
+ // Base URL del repositorio de documentación de Slice.js
13
+ const DOCS_REPO_BASE_URL = 'https://raw.githubusercontent.com/VKneider/slice.js/main/src/Components';
14
+ const COMPONENTS_REGISTRY_URL = 'https://raw.githubusercontent.com/VKneider/slice.js/main/src/Components/components.js';
15
+
16
+ class ComponentRegistry {
17
+ constructor() {
18
+ this.componentsRegistry = null;
19
+ }
20
+
21
+ async loadRegistry() {
22
+ Print.info('📡 Cargando registro de componentes del repositorio oficial...');
23
+
24
+ try {
25
+ const response = await fetch(COMPONENTS_REGISTRY_URL);
26
+
27
+ if (!response.ok) {
28
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
29
+ }
30
+
31
+ const content = await response.text();
32
+
33
+ // Parse the components.js file content
34
+ const match = content.match(/const components = ({[\s\S]*?});/);
35
+ if (!match) {
36
+ throw new Error('Invalid components.js format from repository');
37
+ }
38
+
39
+ this.componentsRegistry = eval('(' + match[1] + ')');
40
+ Print.success('✅ Registro de componentes cargado exitosamente');
41
+
42
+ } catch (error) {
43
+ Print.error(`❌ Error cargando registro de componentes: ${error.message}`);
44
+ Print.info('💡 Verifica tu conexión a internet y que el repositorio sea accesible');
45
+ throw error;
46
+ }
47
+ }
48
+
49
+ async getLocalComponents() {
50
+ try {
51
+ const componentsPath = path.join(__dirname, '../../../src/Components/components.js');
52
+
53
+ if (!await fs.pathExists(componentsPath)) {
54
+ return {};
55
+ }
56
+
57
+ const content = await fs.readFile(componentsPath, 'utf8');
58
+ const match = content.match(/const components = ({[\s\S]*?});/);
59
+
60
+ if (!match) {
61
+ return {};
62
+ }
63
+
64
+ return eval('(' + match[1] + ')');
65
+ } catch (error) {
66
+ Print.warning('⚠️ No se pudo leer el registro local de componentes');
67
+ return {};
68
+ }
69
+ }
70
+
71
+ async findUpdatableComponents() {
72
+ const localComponents = await this.getLocalComponents();
73
+ const updatableComponents = [];
74
+
75
+ Object.entries(localComponents).forEach(([name, category]) => {
76
+ // Check if component exists in remote registry
77
+ if (this.componentsRegistry[name] && this.componentsRegistry[name] === category) {
78
+ // Check if local component directory exists
79
+ const categoryPath = validations.getCategoryPath(category);
80
+ const componentPath = path.join(__dirname, '../../../src', categoryPath, name);
81
+
82
+ if (fs.pathExistsSync(componentPath)) {
83
+ updatableComponents.push({
84
+ name,
85
+ category,
86
+ path: componentPath,
87
+ description: this.getComponentDescription(name, category)
88
+ });
89
+ }
90
+ }
91
+ });
92
+
93
+ return updatableComponents;
94
+ }
95
+
96
+ getAvailableComponents(category = null) {
97
+ if (!this.componentsRegistry) return {};
98
+
99
+ const components = {};
100
+ Object.entries(this.componentsRegistry).forEach(([name, componentCategory]) => {
101
+ if (!category || componentCategory === category) {
102
+ components[name] = {
103
+ name,
104
+ category: componentCategory,
105
+ files: componentCategory === 'Visual' ?
106
+ [`${name}.js`, `${name}.html`, `${name}.css`] :
107
+ [`${name}.js`],
108
+ description: this.getComponentDescription(name, componentCategory)
109
+ };
110
+ }
111
+ });
112
+
113
+ return components;
114
+ }
115
+
116
+ getComponentDescription(componentName, category) {
117
+ const descriptions = {
118
+ // Visual Components
119
+ 'Button': 'Interactive button component with customizable styling and events',
120
+ 'Card': 'Flexible container component for displaying content in card format',
121
+ 'Input': 'Form input component with validation and multiple input types support',
122
+ 'Checkbox': 'Checkbox input component with custom styling and state management',
123
+ 'Switch': 'Toggle switch component for binary state selection',
124
+ 'Select': 'Dropdown selection component with search and multi-select support',
125
+ 'Details': 'Collapsible details component for expandable content sections',
126
+ 'Grid': 'Responsive grid layout component for organizing content',
127
+ 'Icon': 'Icon display component with multiple icon libraries support',
128
+ 'Layout': 'Main layout component for application page structure',
129
+ 'Loading': 'Loading indicator component with multiple animation styles',
130
+ 'Navbar': 'Navigation bar component with responsive design and menu support',
131
+ 'TreeView': 'Hierarchical tree view component for nested data display',
132
+ 'TreeItem': 'Individual tree item component used within TreeView',
133
+ 'DropDown': 'Dropdown menu component for contextual actions',
134
+ 'Route': 'Single route component for client-side routing',
135
+ 'MultiRoute': 'Multiple route handler component for complex routing',
136
+ 'NotFound': '404 error page component for unmatched routes',
137
+
138
+ // Service Components
139
+ 'FetchManager': 'HTTP request manager service for API communication',
140
+ 'LocalStorageManager': 'Local storage management service for browser storage',
141
+ 'IndexedDbManager': 'IndexedDB database management service for client-side storage',
142
+ 'Translator': 'Internationalization service for multi-language support',
143
+ 'Link': 'Navigation link service for programmatic routing'
144
+ };
145
+
146
+ return descriptions[componentName] || `${componentName} component from Slice.js framework (${category})`;
147
+ }
148
+
149
+ async downloadComponentFiles(componentName, category, targetPath) {
150
+ const component = this.getAvailableComponents(category)[componentName];
151
+
152
+ if (!component) {
153
+ throw new Error(`Component ${componentName} not found in ${category} category`);
154
+ }
155
+
156
+ const downloadedFiles = [];
157
+ Print.info(`📥 Descargando ${componentName} desde el repositorio oficial...`);
158
+
159
+ for (const fileName of component.files) {
160
+ const githubUrl = `${DOCS_REPO_BASE_URL}/${category}/${componentName}/${fileName}`;
161
+ const localPath = path.join(targetPath, fileName);
162
+
163
+ try {
164
+ const response = await fetch(githubUrl);
165
+
166
+ if (!response.ok) {
167
+ throw new Error(`HTTP ${response.status}: ${response.statusText} para ${fileName}`);
168
+ }
169
+
170
+ const content = await response.text();
171
+ await fs.writeFile(localPath, content, 'utf8');
172
+ downloadedFiles.push(fileName);
173
+
174
+ console.log(` ✅ ${fileName}`);
175
+ } catch (error) {
176
+ Print.error(` ❌ Error descargando ${fileName}: ${error.message}`);
177
+ throw error;
178
+ }
179
+ }
180
+
181
+ return downloadedFiles;
182
+ }
183
+
184
+ async updateLocalRegistry(componentName, category) {
185
+ const componentsPath = path.join(__dirname, '../../../src/Components/components.js');
186
+
187
+ try {
188
+ let content = await fs.readFile(componentsPath, 'utf8');
189
+
190
+ // Parse existing components
191
+ const componentsMatch = content.match(/const components = ({[\s\S]*?});/);
192
+ if (!componentsMatch) {
193
+ throw new Error('Invalid components.js format in local project');
194
+ }
195
+
196
+ const componentsObj = eval('(' + componentsMatch[1] + ')');
197
+
198
+ // Add new component if it doesn't exist
199
+ if (!componentsObj[componentName]) {
200
+ componentsObj[componentName] = category;
201
+
202
+ // Generate new content
203
+ const sortedComponents = Object.keys(componentsObj)
204
+ .sort()
205
+ .reduce((obj, key) => {
206
+ obj[key] = componentsObj[key];
207
+ return obj;
208
+ }, {});
209
+
210
+ const newComponentsString = JSON.stringify(sortedComponents, null, 2)
211
+ .replace(/"/g, '"')
212
+ .replace(/: "/g, ': "')
213
+ .replace(/",\n/g, '",\n');
214
+
215
+ const newContent = `const components = ${newComponentsString}; export default components;`;
216
+
217
+ await fs.writeFile(componentsPath, newContent, 'utf8');
218
+ Print.success(`📝 Registrado ${componentName} en components.js local`);
219
+ } else {
220
+ Print.info(`📄 ${componentName} ya existe en el registro local`);
221
+ }
222
+
223
+ } catch (error) {
224
+ Print.error(`❌ Error actualizando components.js local: ${error.message}`);
225
+ throw error;
226
+ }
227
+ }
228
+
229
+ async installComponent(componentName, category, force = false) {
230
+ const availableComponents = this.getAvailableComponents(category);
231
+
232
+ if (!availableComponents[componentName]) {
233
+ throw new Error(`Componente '${componentName}' no encontrado en la categoría '${category}' del repositorio oficial`);
234
+ }
235
+
236
+ const categoryPath = validations.getCategoryPath(category);
237
+ const targetPath = path.join(__dirname, '../../../src', categoryPath, componentName);
238
+
239
+ // Check if component already exists
240
+ if (await fs.pathExists(targetPath) && !force) {
241
+ const { overwrite } = await inquirer.prompt([
242
+ {
243
+ type: 'confirm',
244
+ name: 'overwrite',
245
+ message: `El componente '${componentName}' ya existe localmente. ¿Deseas sobrescribirlo con la versión del repositorio?`,
246
+ default: false
247
+ }
248
+ ]);
249
+
250
+ if (!overwrite) {
251
+ Print.info('⏭️ Instalación cancelada por el usuario');
252
+ return false;
253
+ }
254
+ }
255
+
256
+ try {
257
+ // Create component directory
258
+ await fs.ensureDir(targetPath);
259
+
260
+ // Download component files
261
+ const downloadedFiles = await this.downloadComponentFiles(componentName, category, targetPath);
262
+
263
+ // Update components registry
264
+ await this.updateLocalRegistry(componentName, category);
265
+
266
+ Print.success(`✅ ${componentName} actualizado exitosamente desde el repositorio oficial!`);
267
+ console.log(`📁 Ubicación: src/${categoryPath}/${componentName}/`);
268
+ console.log(`📄 Archivos: ${downloadedFiles.join(', ')}`);
269
+
270
+ return true;
271
+
272
+ } catch (error) {
273
+ Print.error(`❌ Error actualizando ${componentName}: ${error.message}`);
274
+ // Clean up partial installation
275
+ if (await fs.pathExists(targetPath)) {
276
+ await fs.remove(targetPath);
277
+ }
278
+ throw error;
279
+ }
280
+ }
281
+
282
+ async installMultipleComponents(componentNames, category = 'Visual', force = false) {
283
+ const results = [];
284
+ Print.info(`🚀 Obteniendo ${componentNames.length} componentes ${category} del repositorio oficial...\n`);
285
+
286
+ for (const componentName of componentNames) {
287
+ try {
288
+ const result = await this.installComponent(componentName, category, force);
289
+ results.push({ name: componentName, success: result });
290
+ } catch (error) {
291
+ Print.error(`❌ Error con ${componentName}: ${error.message}\n`);
292
+ results.push({ name: componentName, success: false, error: error.message });
293
+ }
294
+ }
295
+
296
+ // Summary
297
+ const successful = results.filter(r => r.success).length;
298
+ const failed = results.filter(r => !r.success).length;
299
+
300
+ console.log(`\n📊 Resumen de instalación:`);
301
+ Print.success(`✅ Exitosos: ${successful}`);
302
+ if (failed > 0) {
303
+ Print.error(`❌ Fallidos: ${failed}`);
304
+ results.filter(r => !r.success).forEach(r => {
305
+ console.log(` • ${r.name}: ${r.error}`);
306
+ });
307
+ }
308
+
309
+ return results;
310
+ }
311
+
312
+ async updateAllComponents(force = false) {
313
+ Print.info('🔄 Buscando componentes actualizables...');
314
+
315
+ const updatableComponents = await this.findUpdatableComponents();
316
+
317
+ if (updatableComponents.length === 0) {
318
+ Print.info('✅ No se encontraron componentes locales que coincidan con el repositorio oficial');
319
+ Print.info('💡 Usa "npm run slice:browse" para ver componentes disponibles');
320
+ return true;
321
+ }
322
+
323
+ console.log(`\n📦 Encontrados ${updatableComponents.length} componentes actualizables:\n`);
324
+ updatableComponents.forEach(comp => {
325
+ const icon = comp.category === 'Visual' ? '🎨' : '⚙️';
326
+ console.log(`${icon} ${comp.name} (${comp.category})`);
327
+ });
328
+
329
+ if (!force) {
330
+ const { confirmUpdate } = await inquirer.prompt([
331
+ {
332
+ type: 'confirm',
333
+ name: 'confirmUpdate',
334
+ message: `¿Deseas actualizar todos estos componentes a las versiones del repositorio oficial?`,
335
+ default: true
336
+ }
337
+ ]);
338
+
339
+ if (!confirmUpdate) {
340
+ Print.info('⏭️ Actualización cancelada por el usuario');
341
+ return false;
342
+ }
343
+ }
344
+
345
+ // Group by category for efficient processing
346
+ const visualComponents = updatableComponents.filter(c => c.category === 'Visual').map(c => c.name);
347
+ const serviceComponents = updatableComponents.filter(c => c.category === 'Service').map(c => c.name);
348
+
349
+ let allResults = [];
350
+
351
+ // Update Visual components
352
+ if (visualComponents.length > 0) {
353
+ Print.info(`\n🎨 Actualizando ${visualComponents.length} componentes Visual...`);
354
+ const visualResults = await this.installMultipleComponents(visualComponents, 'Visual', true);
355
+ allResults = allResults.concat(visualResults);
356
+ }
357
+
358
+ // Update Service components
359
+ if (serviceComponents.length > 0) {
360
+ Print.info(`\n⚙️ Actualizando ${serviceComponents.length} componentes Service...`);
361
+ const serviceResults = await this.installMultipleComponents(serviceComponents, 'Service', true);
362
+ allResults = allResults.concat(serviceResults);
363
+ }
364
+
365
+ // Final summary
366
+ const totalSuccessful = allResults.filter(r => r.success).length;
367
+ const totalFailed = allResults.filter(r => !r.success).length;
368
+
369
+ console.log(`\n🎯 Resumen final de actualización:`);
370
+ Print.success(`✅ Componentes actualizados: ${totalSuccessful}`);
371
+
372
+ if (totalFailed > 0) {
373
+ Print.error(`❌ Componentes fallidos: ${totalFailed}`);
374
+ } else {
375
+ Print.success(`🚀 ¡Todos tus componentes están ahora actualizados a las últimas versiones oficiales!`);
376
+ }
377
+
378
+ return totalFailed === 0;
379
+ }
380
+
381
+ displayAvailableComponents() {
382
+ if (!this.componentsRegistry) {
383
+ Print.error('❌ No se pudo cargar el registro de componentes');
384
+ return;
385
+ }
386
+
387
+ console.log('\n📚 Componentes disponibles en el repositorio oficial de Slice.js:\n');
388
+
389
+ const visualComponents = this.getAvailableComponents('Visual');
390
+ const serviceComponents = this.getAvailableComponents('Service');
391
+
392
+ Print.info('🎨 Visual Components (UI):');
393
+ Object.entries(visualComponents).forEach(([name, info]) => {
394
+ console.log(` • ${name}: ${info.description}`);
395
+ });
396
+
397
+ Print.info('\n⚙️ Service Components (Logic):');
398
+ Object.entries(serviceComponents).forEach(([name, info]) => {
399
+ console.log(` • ${name}: ${info.description}`);
400
+ });
401
+
402
+ console.log(`\n💡 Ejemplos de uso:`);
403
+ console.log(`npm run slice:get Button Card Input`);
404
+ console.log(`npm run slice:get FetchManager --service`);
405
+ console.log(`npm run slice:sync # Actualizar componentes existentes`);
406
+ }
407
+
408
+ async interactiveInstall() {
409
+ const { componentType } = await inquirer.prompt([
410
+ {
411
+ type: 'list',
412
+ name: 'componentType',
413
+ message: 'Selecciona el tipo de componente a obtener del repositorio:',
414
+ choices: [
415
+ { name: '🎨 Visual Components (UI)', value: 'Visual' },
416
+ { name: '⚙️ Service Components (Logic)', value: 'Service' }
417
+ ]
418
+ }
419
+ ]);
420
+
421
+ const availableComponents = this.getAvailableComponents(componentType);
422
+ const componentChoices = Object.entries(availableComponents).map(([name, info]) => ({
423
+ name: `${name} - ${info.description}`,
424
+ value: name
425
+ }));
426
+
427
+ if (componentType === 'Visual') {
428
+ const { installMode } = await inquirer.prompt([
429
+ {
430
+ type: 'list',
431
+ name: 'installMode',
432
+ message: '¿Cómo deseas obtener los componentes Visual?',
433
+ choices: [
434
+ { name: 'Obtener uno solo', value: 'single' },
435
+ { name: 'Obtener múltiples', value: 'multiple' }
436
+ ]
437
+ }
438
+ ]);
439
+
440
+ if (installMode === 'multiple') {
441
+ const { selectedComponents } = await inquirer.prompt([
442
+ {
443
+ type: 'checkbox',
444
+ name: 'selectedComponents',
445
+ message: 'Selecciona los componentes Visual a obtener del repositorio:',
446
+ choices: componentChoices,
447
+ validate: (input) => {
448
+ if (input.length === 0) {
449
+ return 'Debes seleccionar al menos un componente';
450
+ }
451
+ return true;
452
+ }
453
+ }
454
+ ]);
455
+
456
+ await this.installMultipleComponents(selectedComponents, componentType);
457
+ } else {
458
+ const { selectedComponent } = await inquirer.prompt([
459
+ {
460
+ type: 'list',
461
+ name: 'selectedComponent',
462
+ message: 'Selecciona un componente Visual:',
463
+ choices: componentChoices
464
+ }
465
+ ]);
466
+
467
+ await this.installComponent(selectedComponent, componentType);
468
+ }
469
+ } else {
470
+ const { selectedComponent } = await inquirer.prompt([
471
+ {
472
+ type: 'list',
473
+ name: 'selectedComponent',
474
+ message: 'Selecciona un componente Service:',
475
+ choices: componentChoices
476
+ }
477
+ ]);
478
+
479
+ await this.installComponent(selectedComponent, componentType);
480
+ }
481
+ }
482
+
483
+ findComponentInRegistry(componentName) {
484
+ if (!this.componentsRegistry) return null;
485
+
486
+ const normalizedName = componentName.charAt(0).toUpperCase() + componentName.slice(1);
487
+
488
+ if (this.componentsRegistry[normalizedName]) {
489
+ return {
490
+ name: normalizedName,
491
+ category: this.componentsRegistry[normalizedName]
492
+ };
493
+ }
494
+
495
+ return null;
496
+ }
497
+ }
498
+
499
+ // Main get function
500
+ async function getComponents(componentNames = [], options = {}) {
501
+ const registry = new ComponentRegistry();
502
+
503
+ try {
504
+ await registry.loadRegistry();
505
+ } catch (error) {
506
+ Print.error('No se pudo cargar el registro de componentes del repositorio oficial');
507
+ Print.info('💡 Verifica tu conexión a internet y vuelve a intentar');
508
+ return false;
509
+ }
510
+
511
+ // Interactive mode if no components specified
512
+ if (!componentNames || componentNames.length === 0) {
513
+ await registry.interactiveInstall();
514
+ return true;
515
+ }
516
+
517
+ // Determine category
518
+ const category = options.service ? 'Service' : 'Visual';
519
+
520
+ if (componentNames.length === 1) {
521
+ // Single component install
522
+ const componentInfo = registry.findComponentInRegistry(componentNames[0]);
523
+
524
+ if (!componentInfo) {
525
+ Print.error(`Componente '${componentNames[0]}' no encontrado en el repositorio oficial`);
526
+ Print.info('💡 Usa "npm run slice:browse" para ver componentes disponibles');
527
+ return false;
528
+ }
529
+
530
+ // Use the category from registry unless Service is explicitly requested
531
+ const actualCategory = options.service ? 'Service' : componentInfo.category;
532
+
533
+ try {
534
+ await registry.installComponent(componentInfo.name, actualCategory, options.force);
535
+ return true;
536
+ } catch (error) {
537
+ Print.error(`Error: ${error.message}`);
538
+ return false;
539
+ }
540
+ } else {
541
+ // Multiple components install
542
+ const normalizedComponents = componentNames.map(name =>
543
+ name.charAt(0).toUpperCase() + name.slice(1)
544
+ );
545
+
546
+ try {
547
+ await registry.installMultipleComponents(normalizedComponents, category, options.force);
548
+ return true;
549
+ } catch (error) {
550
+ Print.error(`Error: ${error.message}`);
551
+ return false;
552
+ }
553
+ }
554
+ }
555
+
556
+ // List components function
557
+ async function listComponents() {
558
+ const registry = new ComponentRegistry();
559
+
560
+ try {
561
+ await registry.loadRegistry();
562
+ registry.displayAvailableComponents();
563
+ return true;
564
+ } catch (error) {
565
+ Print.error('No se pudo cargar el registro de componentes del repositorio oficial');
566
+ Print.info('💡 Verifica tu conexión a internet y vuelve a intentar');
567
+ return false;
568
+ }
569
+ }
570
+
571
+ // Sync components function - NEW
572
+ async function syncComponents(options = {}) {
573
+ const registry = new ComponentRegistry();
574
+
575
+ try {
576
+ await registry.loadRegistry();
577
+ return await registry.updateAllComponents(options.force);
578
+ } catch (error) {
579
+ Print.error('No se pudo cargar el registro de componentes del repositorio oficial');
580
+ Print.info('💡 Verifica tu conexión a internet y vuelve a intentar');
581
+ return false;
582
+ }
583
+ }
584
+
585
+ export default getComponents;
586
+ export { listComponents, syncComponents };
@@ -0,0 +1,165 @@
1
+ // commands/utils/VersionChecker.js
2
+
3
+ import fs from "fs-extra";
4
+ import path from "path";
5
+ import { fileURLToPath } from "url";
6
+ import Print from "../Print.js";
7
+
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+
10
+ class VersionChecker {
11
+ constructor() {
12
+ this.currentCliVersion = null;
13
+ this.currentFrameworkVersion = null;
14
+ this.latestCliVersion = null;
15
+ this.latestFrameworkVersion = null;
16
+ }
17
+
18
+ async getCurrentVersions() {
19
+ try {
20
+ // Get CLI version
21
+ const cliPackagePath = path.join(__dirname, '../../package.json');
22
+ const cliPackage = await fs.readJson(cliPackagePath);
23
+ this.currentCliVersion = cliPackage.version;
24
+
25
+ // Get Framework version from node_modules
26
+ const frameworkPackagePath = path.join(__dirname, '../../../../node_modules/slicejs-web-framework/package.json');
27
+ if (await fs.pathExists(frameworkPackagePath)) {
28
+ const frameworkPackage = await fs.readJson(frameworkPackagePath);
29
+ this.currentFrameworkVersion = frameworkPackage.version;
30
+ }
31
+
32
+ // Get Project's CLI version
33
+ const projectPackagePath = path.join(__dirname, '../../../../package.json');
34
+ if (await fs.pathExists(projectPackagePath)) {
35
+ const projectPackage = await fs.readJson(projectPackagePath);
36
+ if (projectPackage.dependencies && projectPackage.dependencies['slicejs-cli']) {
37
+ // This could be different from the currently running CLI version
38
+ }
39
+ }
40
+
41
+ return {
42
+ cli: this.currentCliVersion,
43
+ framework: this.currentFrameworkVersion
44
+ };
45
+ } catch (error) {
46
+ return null;
47
+ }
48
+ }
49
+
50
+ async getLatestVersions() {
51
+ try {
52
+ // Check CLI version
53
+ const cliResponse = await fetch('https://registry.npmjs.org/slicejs-cli/latest', {
54
+ headers: { 'Accept': 'application/json' }
55
+ });
56
+
57
+ if (cliResponse.ok) {
58
+ const cliData = await cliResponse.json();
59
+ this.latestCliVersion = cliData.version;
60
+ }
61
+
62
+ // Check Framework version
63
+ const frameworkResponse = await fetch('https://registry.npmjs.org/slicejs-web-framework/latest', {
64
+ headers: { 'Accept': 'application/json' }
65
+ });
66
+
67
+ if (frameworkResponse.ok) {
68
+ const frameworkData = await frameworkResponse.json();
69
+ this.latestFrameworkVersion = frameworkData.version;
70
+ }
71
+
72
+ return {
73
+ cli: this.latestCliVersion,
74
+ framework: this.latestFrameworkVersion
75
+ };
76
+ } catch (error) {
77
+ // Silent fail - don't interrupt commands for version check failures
78
+ return null;
79
+ }
80
+ }
81
+
82
+ compareVersions(current, latest) {
83
+ if (!current || !latest) return null;
84
+
85
+ const currentParts = current.split('.').map(Number);
86
+ const latestParts = latest.split('.').map(Number);
87
+
88
+ for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
89
+ const currentPart = currentParts[i] || 0;
90
+ const latestPart = latestParts[i] || 0;
91
+
92
+ if (latestPart > currentPart) return 'outdated';
93
+ if (currentPart > latestPart) return 'newer';
94
+ }
95
+
96
+ return 'current';
97
+ }
98
+
99
+ async checkForUpdates(silent = false) {
100
+ try {
101
+ const current = await this.getCurrentVersions();
102
+ if (!current) return;
103
+
104
+ const latest = await this.getLatestVersions();
105
+ if (!latest) return;
106
+
107
+ const cliStatus = this.compareVersions(current.cli, latest.cli);
108
+ const frameworkStatus = this.compareVersions(current.framework, latest.framework);
109
+
110
+ if (!silent && (cliStatus === 'outdated' || frameworkStatus === 'outdated')) {
111
+ console.log(''); // Line break
112
+ Print.warning('📦 Actualizaciones Disponibles:');
113
+
114
+ if (cliStatus === 'outdated') {
115
+ console.log(` 🔧 CLI: ${current.cli} → ${latest.cli}`);
116
+ console.log(` npm update slicejs-cli`);
117
+ }
118
+
119
+ if (frameworkStatus === 'outdated') {
120
+ console.log(` ⚡ Framework: ${current.framework} → ${latest.framework}`);
121
+ console.log(` npm update slicejs-web-framework`);
122
+ }
123
+
124
+ console.log(' 📚 Changelog: https://github.com/VKneider/slice.js/releases');
125
+ console.log(''); // Line break
126
+ }
127
+
128
+ return {
129
+ cli: { current: current.cli, latest: latest.cli, status: cliStatus },
130
+ framework: { current: current.framework, latest: latest.framework, status: frameworkStatus }
131
+ };
132
+
133
+ } catch (error) {
134
+ // Silent fail - don't interrupt commands
135
+ return null;
136
+ }
137
+ }
138
+
139
+ async showVersionInfo() {
140
+ const current = await this.getCurrentVersions();
141
+ const latest = await this.getLatestVersions();
142
+
143
+ console.log('\n📋 Información de Versiones:');
144
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
145
+
146
+ if (current?.cli) {
147
+ const cliStatus = this.compareVersions(current.cli, latest?.cli);
148
+ const statusIcon = cliStatus === 'current' ? '✅' : cliStatus === 'outdated' ? '🔄' : '🆕';
149
+ console.log(`${statusIcon} CLI: v${current.cli}${latest?.cli && latest.cli !== current.cli ? ` (latest: v${latest.cli})` : ''}`);
150
+ }
151
+
152
+ if (current?.framework) {
153
+ const frameworkStatus = this.compareVersions(current.framework, latest?.framework);
154
+ const statusIcon = frameworkStatus === 'current' ? '✅' : frameworkStatus === 'outdated' ? '🔄' : '🆕';
155
+ console.log(`${statusIcon} Framework: v${current.framework}${latest?.framework && latest.framework !== current.framework ? ` (latest: v${latest.framework})` : ''}`);
156
+ }
157
+
158
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
159
+ }
160
+ }
161
+
162
+ // Singleton instance
163
+ const versionChecker = new VersionChecker();
164
+
165
+ export default versionChecker;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slicejs-cli",
3
- "version": "2.0.14",
3
+ "version": "2.1.0",
4
4
  "description": "Command client for developing web applications with Slice.js framework",
5
5
  "main": "client.js",
6
6
  "scripts": {
@@ -20,6 +20,6 @@
20
20
  "commander": "^12.0.0",
21
21
  "fs-extra": "^11.2.0",
22
22
  "inquirer": "^12.4.2",
23
- "slicejs-web-framework": "^1.0.6"
23
+ "slicejs-web-framework": "latest"
24
24
  }
25
25
  }
package/post.js CHANGED
@@ -2,64 +2,112 @@ import fs from 'fs';
2
2
  import { fileURLToPath } from 'url';
3
3
  import path from 'path';
4
4
  import Print from './commands/Print.js';
5
- import initializeProject from './commands/init/init.js';
6
5
 
7
6
  const __filename = fileURLToPath(import.meta.url);
8
7
  const __dirname = path.dirname(__filename);
9
- const projectName = path.basename(__dirname); // Obtiene el nombre de la carpeta actual
8
+ const projectName = path.basename(__dirname);
10
9
 
11
10
  const projectPackageJsonPath = path.resolve(__dirname, '../../package.json');
12
11
 
13
- // Verifica si el archivo package.json existe
12
+ // Check if package.json file exists
14
13
  fs.promises.access(projectPackageJsonPath, fs.constants.F_OK)
15
14
  .then(() => {
16
- // El archivo package.json existe, por lo que lo leemos y agregamos los comandos
15
+ // The package.json file exists, so we read it and add the commands
17
16
  return fs.promises.readFile(projectPackageJsonPath, 'utf8');
18
17
  })
19
18
  .then(data => {
20
- // Convierte el contenido del archivo a un objeto JSON
19
+ // Convert the file content to a JSON object
21
20
  const projectPackageJson = JSON.parse(data);
22
21
 
23
- // Agrega los comandos personalizados a los scripts del proyecto
22
+ // Add custom commands to the project scripts
24
23
  projectPackageJson.scripts = projectPackageJson.scripts || {};
24
+
25
+ // Main project commands
26
+ projectPackageJson.scripts['slice:init'] = 'node node_modules/slicejs-cli/client.js init';
27
+ projectPackageJson.scripts['slice:start'] = 'node api/index.js';
28
+ projectPackageJson.scripts['slice:version'] = 'node node_modules/slicejs-cli/client.js version';
29
+ projectPackageJson.scripts['slice:update'] = 'node node_modules/slicejs-cli/client.js update';
30
+
31
+ // Local component commands
25
32
  projectPackageJson.scripts['slice:create'] = 'node node_modules/slicejs-cli/client.js component create';
26
33
  projectPackageJson.scripts['slice:list'] = 'node node_modules/slicejs-cli/client.js component list';
27
34
  projectPackageJson.scripts['slice:delete'] = 'node node_modules/slicejs-cli/client.js component delete';
28
- projectPackageJson.scripts['slice:init'] = 'node node_modules/slicejs-cli/client.js init';
35
+
36
+ // Main repository commands (most used shortcuts)
37
+ projectPackageJson.scripts['slice:get'] = 'node node_modules/slicejs-cli/client.js get';
38
+ projectPackageJson.scripts['slice:browse'] = 'node node_modules/slicejs-cli/client.js browse';
39
+ projectPackageJson.scripts['slice:sync'] = 'node node_modules/slicejs-cli/client.js sync';
40
+
41
+ // Detailed registry commands (for advanced users)
42
+ projectPackageJson.scripts['slice:registry-get'] = 'node node_modules/slicejs-cli/client.js registry get';
43
+ projectPackageJson.scripts['slice:registry-list'] = 'node node_modules/slicejs-cli/client.js registry list';
44
+ projectPackageJson.scripts['slice:registry-sync'] = 'node node_modules/slicejs-cli/client.js registry sync';
45
+
46
+ // Legacy/compatibility commands
29
47
  projectPackageJson.scripts['run'] = 'node api/index.js';
30
- projectPackageJson.scripts['slice:start'] = 'node api/index.js';
31
48
  projectPackageJson.scripts['development'] = 'node api/index.js';
32
49
 
33
- // add type module
50
+ // Module configuration
34
51
  projectPackageJson.type = 'module';
35
52
  projectPackageJson.engines = {
36
53
  "node": "20.x"
37
54
  };
38
55
 
39
- // Escribe el nuevo contenido en el package.json del proyecto
40
- fs.promises.writeFile(projectPackageJsonPath, JSON.stringify(projectPackageJson, null, 2), 'utf8');
41
- return Print.success("Run 'npm run slice:init' to initialize your project");
56
+ // Write the new content to package.json
57
+ return fs.promises.writeFile(projectPackageJsonPath, JSON.stringify(projectPackageJson, null, 2), 'utf8');
42
58
  })
43
59
  .then(() => {
44
- console.log('SliceJS CLI commands added to package.json.');
60
+ console.log('SliceJS CLI commands added to package.json');
61
+ console.log('\n🚀 Main commands:');
62
+ console.log(' npm run slice:init - Initialize Slice.js project');
63
+ console.log(' npm run slice:get Button - Get components from official repository');
64
+ console.log(' npm run slice:browse - View all available components');
65
+ console.log(' npm run slice:sync - Update local components to latest versions');
66
+ console.log(' npm run slice:start - Start development server');
67
+ console.log('\n⚙️ Local component management:');
68
+ console.log(' npm run slice:create - Create local component');
69
+ console.log(' npm run slice:list - List local components');
70
+ console.log(' npm run slice:delete - Delete local component');
71
+ console.log('\n🔧 Utilities:');
72
+ console.log(' npm run slice:version - View version information');
73
+ console.log(' npm run slice:update - Check for available updates');
74
+ console.log('\n🎯 To get started: npm run slice:init');
75
+ console.log('💡 Tip: Use "slice:sync" to keep your components updated');
45
76
  })
46
77
  .catch(err => {
47
78
  if (err.code === 'ENOENT') {
48
- // El archivo package.json no existe, así que creamos uno nuevo con los comandos
79
+ // The package.json file doesn't exist, so we create a new one with the commands
49
80
  const defaultPackageJson = {
50
- name: "project-name", // Utiliza el nombre de la carpeta como nombre del proyecto
81
+ name: projectName,
51
82
  version: '1.0.0',
52
- description: 'Project description',
83
+ description: 'Slice.js project',
53
84
  main: 'api/index.js',
54
85
  scripts: {
86
+ // Main commands
87
+ 'slice:init': 'node node_modules/slicejs-cli/client.js init',
88
+ 'slice:start': 'node node_modules/slicejs-cli/client.js start',
89
+ 'slice:version': 'node node_modules/slicejs-cli/client.js version',
90
+ 'slice:update': 'node node_modules/slicejs-cli/client.js update',
91
+
92
+ // Local components
55
93
  'slice:create': 'node node_modules/slicejs-cli/client.js component create',
56
94
  'slice:list': 'node node_modules/slicejs-cli/client.js component list',
57
95
  'slice:delete': 'node node_modules/slicejs-cli/client.js component delete',
58
- "run": "node api/index.js",
59
- "slice:start": "node api/index.js",
60
- "slice:init": "node node_modules/slicejs-cli/client.js init"
96
+
97
+ // Official repository (shortcuts)
98
+ 'slice:get': 'node node_modules/slicejs-cli/client.js get',
99
+ 'slice:browse': 'node node_modules/slicejs-cli/client.js browse',
100
+ 'slice:sync': 'node node_modules/slicejs-cli/client.js sync',
101
+
102
+ // Detailed registry
103
+ 'slice:registry-get': 'node node_modules/slicejs-cli/client.js registry get',
104
+ 'slice:registry-list': 'node node_modules/slicejs-cli/client.js registry list',
105
+ 'slice:registry-sync': 'node node_modules/slicejs-cli/client.js registry sync',
106
+
107
+ // Legacy
108
+ 'run': 'node api/index.js'
61
109
  },
62
- keywords: [],
110
+ keywords: ['slicejs', 'web-framework', 'components'],
63
111
  author: '',
64
112
  license: 'ISC',
65
113
  type: 'module',
@@ -67,18 +115,32 @@ fs.promises.access(projectPackageJsonPath, fs.constants.F_OK)
67
115
  "node": "20.x"
68
116
  }
69
117
  };
70
- // Guardamos el nuevo package.json
71
- fs.promises.writeFile(projectPackageJsonPath, JSON.stringify(defaultPackageJson, null, 2), 'utf8');
72
- return Print.success("Run 'npm run slice:init' to initialize your project");
118
+
119
+ // Save the new package.json
120
+ return fs.promises.writeFile(projectPackageJsonPath, JSON.stringify(defaultPackageJson, null, 2), 'utf8');
73
121
  } else {
74
122
  console.error('Error:', err);
123
+ throw err;
75
124
  }
76
125
  })
77
126
  .then(() => {
78
- console.log('Created package.json with SliceJS CLI commands.');
127
+ console.log('Created package.json with SliceJS CLI commands.');
128
+ console.log('\n🚀 Main commands:');
129
+ console.log(' npm run slice:init - Initialize Slice.js project');
130
+ console.log(' npm run slice:get Button - Get components from official repository');
131
+ console.log(' npm run slice:browse - View all available components');
132
+ console.log(' npm run slice:sync - Update local components to latest versions');
133
+ console.log(' npm run slice:start - Start development server');
134
+ console.log('\n⚙️ Local component management:');
135
+ console.log(' npm run slice:create - Create local component');
136
+ console.log(' npm run slice:list - List local components');
137
+ console.log(' npm run slice:delete - Delete local component');
138
+ console.log('\n🔧 Utilities:');
139
+ console.log(' npm run slice:version - View version information');
140
+ console.log(' npm run slice:update - Check for available updates');
141
+ console.log('\n🎯 To get started: npm run slice:init');
142
+ console.log('💡 Tip: Use "slice:sync" to keep your components updated');
79
143
  })
80
144
  .catch(err => {
81
- console.error('Error:', err);
82
- })
83
-
84
-
145
+ console.error('Error creating package.json:', err);
146
+ });