slicejs-cli 2.5.0 → 2.6.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 CHANGED
@@ -110,8 +110,11 @@ slice registry sync → slice sync
110
110
  slice version
111
111
  slice -v
112
112
 
113
- # Check for available updates
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
@@ -9,6 +9,7 @@ import getComponent, { listComponents as listRemoteComponents, syncComponents }
9
9
  import startServer from "./commands/startServer/startServer.js";
10
10
  import runDiagnostics from "./commands/doctor/doctor.js";
11
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";
@@ -340,25 +341,12 @@ sliceClient
340
341
  sliceClient
341
342
  .command("update")
342
343
  .alias("upgrade")
343
- .description("Check for and show available updates for CLI and framework")
344
- .action(async () => {
345
- Print.info("Checking for updates...");
346
-
347
- try {
348
- const updateInfo = await versionChecker.checkForUpdates(false);
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
- }
344
+ .description("Update CLI and framework to latest versions")
345
+ .option("-y, --yes", "Skip confirmation and update all packages automatically")
346
+ .option("--cli", "Update only the Slice.js CLI")
347
+ .option("-f, --framework", "Update only the Slice.js Framework")
348
+ .action(async (options) => {
349
+ await updateManager.checkAndPromptUpdates(options);
362
350
  });
363
351
 
364
352
  // DOCTOR COMMAND - Diagnose project issues
@@ -34,8 +34,9 @@ async function checkNodeVersion() {
34
34
  * Verifica la estructura de directorios
35
35
  */
36
36
  async function checkDirectoryStructure() {
37
- const srcPath = path.join(process.cwd(), 'src');
38
- const apiPath = path.join(process.cwd(), 'api');
37
+ const projectRoot = path.join(__dirname, '../../../../');
38
+ const srcPath = path.join(projectRoot, 'src');
39
+ const apiPath = path.join(projectRoot, 'api');
39
40
 
40
41
  const srcExists = await fs.pathExists(srcPath);
41
42
  const apiExists = await fs.pathExists(apiPath);
@@ -62,7 +63,7 @@ async function checkDirectoryStructure() {
62
63
  * Verifica sliceConfig.json
63
64
  */
64
65
  async function checkConfig() {
65
- const configPath = path.join(process.cwd(), 'src', 'sliceConfig.json');
66
+ const configPath = path.join(__dirname, '../../../../src/sliceConfig.json');
66
67
 
67
68
  if (!await fs.pathExists(configPath)) {
68
69
  return {
@@ -100,7 +101,7 @@ async function checkConfig() {
100
101
  * Verifica disponibilidad del puerto
101
102
  */
102
103
  async function checkPort() {
103
- const configPath = path.join(process.cwd(), 'src', 'sliceConfig.json');
104
+ const configPath = path.join(__dirname, '../../../../src/sliceConfig.json');
104
105
  let port = 3000;
105
106
 
106
107
  try {
@@ -144,7 +145,7 @@ async function checkPort() {
144
145
  * Verifica dependencias en package.json
145
146
  */
146
147
  async function checkDependencies() {
147
- const packagePath = path.join(process.cwd(), 'package.json');
148
+ const packagePath = path.join(__dirname, '../../../../package.json');
148
149
 
149
150
  if (!await fs.pathExists(packagePath)) {
150
151
  return {
@@ -188,7 +189,8 @@ async function checkDependencies() {
188
189
  * Verifica integridad de componentes
189
190
  */
190
191
  async function checkComponents() {
191
- const configPath = path.join(process.cwd(), 'src', 'sliceConfig.json');
192
+ const configPath = path.join(__dirname, '../../../../src/sliceConfig.json');
193
+ const projectRoot = path.join(__dirname, '../../../../');
192
194
 
193
195
  if (!await fs.pathExists(configPath)) {
194
196
  return {
@@ -206,7 +208,7 @@ async function checkComponents() {
206
208
  let componentIssues = 0;
207
209
 
208
210
  for (const [category, { path: compPath }] of Object.entries(componentPaths)) {
209
- const fullPath = path.join(process.cwd(), 'src', compPath);
211
+ const fullPath = path.join(projectRoot, 'src', compPath);
210
212
 
211
213
  if (await fs.pathExists(fullPath)) {
212
214
  const items = await fs.readdir(fullPath);
@@ -0,0 +1,277 @@
1
+ // commands/utils/updateManager.js
2
+
3
+ import { exec } from "child_process";
4
+ import { promisify } from "util";
5
+ import inquirer from "inquirer";
6
+ import ora from "ora";
7
+ import Print from "../Print.js";
8
+ import versionChecker from "./versionChecker.js";
9
+
10
+ const execAsync = promisify(exec);
11
+
12
+ class UpdateManager {
13
+ constructor() {
14
+ this.packagesToUpdate = [];
15
+ }
16
+
17
+ /**
18
+ * Check for available updates and return structured info
19
+ */
20
+ async checkForUpdates() {
21
+ try {
22
+ const updateInfo = await versionChecker.checkForUpdates(true); // Silent mode
23
+
24
+ if (!updateInfo) {
25
+ return null;
26
+ }
27
+
28
+ const updates = [];
29
+
30
+ if (updateInfo.cli.status === 'outdated') {
31
+ updates.push({
32
+ name: 'slicejs-cli',
33
+ displayName: 'Slice.js CLI',
34
+ current: updateInfo.cli.current,
35
+ latest: updateInfo.cli.latest,
36
+ type: 'cli'
37
+ });
38
+ }
39
+
40
+ if (updateInfo.framework.status === 'outdated') {
41
+ updates.push({
42
+ name: 'slicejs-web-framework',
43
+ displayName: 'Slice.js Framework',
44
+ current: updateInfo.framework.current,
45
+ latest: updateInfo.framework.latest,
46
+ type: 'framework'
47
+ });
48
+ }
49
+
50
+ return {
51
+ hasUpdates: updates.length > 0,
52
+ updates,
53
+ allCurrent: updateInfo.cli.status === 'current' && updateInfo.framework.status === 'current'
54
+ };
55
+ } catch (error) {
56
+ Print.error(`Checking for updates: ${error.message}`);
57
+ return null;
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Display available updates in a formatted way
63
+ */
64
+ displayUpdates(updateInfo) {
65
+ if (!updateInfo || !updateInfo.hasUpdates) {
66
+ return;
67
+ }
68
+
69
+ console.log('');
70
+ Print.warning('📦 Actualizaciones Disponibles:');
71
+ console.log('');
72
+
73
+ updateInfo.updates.forEach(pkg => {
74
+ console.log(` ${pkg.type === 'cli' ? '🔧' : '⚡'} ${pkg.displayName}`);
75
+ console.log(` ${pkg.current} → ${pkg.latest}`);
76
+ });
77
+
78
+ console.log('');
79
+ console.log(' 📚 Changelog: https://github.com/VKneider/slice.js/releases');
80
+ console.log('');
81
+ }
82
+
83
+ /**
84
+ * Prompt user to select which packages to update
85
+ */
86
+ async promptForUpdates(updateInfo, options = {}) {
87
+ if (!updateInfo || !updateInfo.hasUpdates) {
88
+ return [];
89
+ }
90
+
91
+ // If --yes flag is set, return all updates
92
+ if (options.yes) {
93
+ return updateInfo.updates.map(pkg => pkg.name);
94
+ }
95
+
96
+ // If specific package flags are set
97
+ if (options.cli || options.framework) {
98
+ const selected = [];
99
+ if (options.cli) {
100
+ const cliUpdate = updateInfo.updates.find(pkg => pkg.type === 'cli');
101
+ if (cliUpdate) selected.push(cliUpdate.name);
102
+ }
103
+ if (options.framework) {
104
+ const frameworkUpdate = updateInfo.updates.find(pkg => pkg.type === 'framework');
105
+ if (frameworkUpdate) selected.push(frameworkUpdate.name);
106
+ }
107
+ return selected;
108
+ }
109
+
110
+ // Interactive selection
111
+ const choices = updateInfo.updates.map(pkg => ({
112
+ name: `${pkg.displayName} (${pkg.current} → ${pkg.latest})`,
113
+ value: pkg.name,
114
+ checked: true
115
+ }));
116
+
117
+ const answers = await inquirer.prompt([
118
+ {
119
+ type: 'checkbox',
120
+ name: 'packages',
121
+ message: '¿Qué paquetes deseas actualizar?',
122
+ choices,
123
+ validate: (answer) => {
124
+ if (answer.length === 0) {
125
+ return 'Debes seleccionar al menos un paquete';
126
+ }
127
+ return true;
128
+ }
129
+ }
130
+ ]);
131
+
132
+ return answers.packages;
133
+ }
134
+
135
+ /**
136
+ * Execute npm update command for a specific package
137
+ */
138
+ async updatePackage(packageName) {
139
+ try {
140
+ const command = `npm install ${packageName}@latest`;
141
+ const { stdout, stderr } = await execAsync(command);
142
+
143
+ return {
144
+ success: true,
145
+ packageName,
146
+ stdout,
147
+ stderr
148
+ };
149
+ } catch (error) {
150
+ return {
151
+ success: false,
152
+ packageName,
153
+ error: error.message
154
+ };
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Update multiple packages with progress indication
160
+ */
161
+ async installUpdates(packages) {
162
+ const results = [];
163
+
164
+ for (const packageName of packages) {
165
+ const spinner = ora(`Actualizando ${packageName}...`).start();
166
+
167
+ try {
168
+ const result = await this.updatePackage(packageName);
169
+
170
+ if (result.success) {
171
+ spinner.succeed(`${packageName} actualizado exitosamente`);
172
+ results.push({ packageName, success: true });
173
+ } else {
174
+ spinner.fail(`Error actualizando ${packageName}`);
175
+ Print.error(`Detalles: ${result.error}`);
176
+ results.push({ packageName, success: false, error: result.error });
177
+ }
178
+ } catch (error) {
179
+ spinner.fail(`Error actualizando ${packageName}`);
180
+ Print.error(`Detalles: ${error.message}`);
181
+ results.push({ packageName, success: false, error: error.message });
182
+ }
183
+ }
184
+
185
+ return results;
186
+ }
187
+
188
+ /**
189
+ * Main method to check and prompt for updates
190
+ */
191
+ async checkAndPromptUpdates(options = {}) {
192
+ const spinner = ora('Verificando actualizaciones...').start();
193
+
194
+ try {
195
+ const updateInfo = await this.checkForUpdates();
196
+ spinner.stop();
197
+
198
+ if (!updateInfo) {
199
+ Print.error('No se pudo verificar actualizaciones. Verifica tu conexión a internet.');
200
+ return false;
201
+ }
202
+
203
+ if (updateInfo.allCurrent) {
204
+ Print.success('✅ Todos los componentes están actualizados!');
205
+ return true;
206
+ }
207
+
208
+ if (!updateInfo.hasUpdates) {
209
+ Print.success('✅ Todos los componentes están actualizados!');
210
+ return true;
211
+ }
212
+
213
+ // Display available updates
214
+ this.displayUpdates(updateInfo);
215
+
216
+ // Get packages to update
217
+ const packagesToUpdate = await this.promptForUpdates(updateInfo, options);
218
+
219
+ if (!packagesToUpdate || packagesToUpdate.length === 0) {
220
+ Print.info('No se seleccionaron paquetes para actualizar.');
221
+ return false;
222
+ }
223
+
224
+ // Confirm installation if not auto-confirmed
225
+ if (!options.yes && !options.cli && !options.framework) {
226
+ const { confirm } = await inquirer.prompt([
227
+ {
228
+ type: 'confirm',
229
+ name: 'confirm',
230
+ message: '¿Deseas continuar con la actualización?',
231
+ default: true
232
+ }
233
+ ]);
234
+
235
+ if (!confirm) {
236
+ Print.info('Actualización cancelada.');
237
+ return false;
238
+ }
239
+ }
240
+
241
+ console.log(''); // Line break
242
+ Print.info('📥 Instalando actualizaciones...');
243
+ console.log('');
244
+
245
+ // Install updates
246
+ const results = await this.installUpdates(packagesToUpdate);
247
+
248
+ // Summary
249
+ console.log('');
250
+ const successCount = results.filter(r => r.success).length;
251
+ const failCount = results.filter(r => !r.success).length;
252
+
253
+ if (failCount === 0) {
254
+ Print.success(`✅ ${successCount} paquete(s) actualizado(s) exitosamente!`);
255
+ } else {
256
+ Print.warning(`⚠️ ${successCount} exitoso(s), ${failCount} fallido(s)`);
257
+ }
258
+
259
+ if (successCount > 0) {
260
+ console.log('');
261
+ Print.info('💡 Se recomienda reiniciar el servidor de desarrollo si está ejecutándose.');
262
+ }
263
+
264
+ return failCount === 0;
265
+
266
+ } catch (error) {
267
+ spinner.stop();
268
+ Print.error(`Error durante la actualización: ${error.message}`);
269
+ return false;
270
+ }
271
+ }
272
+ }
273
+
274
+ // Singleton instance
275
+ const updateManager = new UpdateManager();
276
+
277
+ export default updateManager;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slicejs-cli",
3
- "version": "2.5.0",
3
+ "version": "2.6.0",
4
4
  "description": "Command client for developing web applications with Slice.js framework",
5
5
  "main": "client.js",
6
6
  "bin": {