slicejs-cli 3.4.0 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/AGENTS.md +247 -0
  2. package/client.js +63 -64
  3. package/commands/Print.js +11 -15
  4. package/commands/Validations.js +12 -23
  5. package/commands/buildProduction/buildProduction.js +23 -26
  6. package/commands/bundle/bundle.js +10 -11
  7. package/commands/createComponent/createComponent.js +14 -16
  8. package/commands/deleteComponent/deleteComponent.js +6 -6
  9. package/commands/doctor/doctor.js +11 -14
  10. package/commands/getComponent/getComponent.js +99 -162
  11. package/commands/init/init.js +25 -21
  12. package/commands/listComponents/listComponents.js +18 -21
  13. package/commands/startServer/startServer.js +21 -24
  14. package/commands/startServer/watchServer.js +7 -7
  15. package/commands/types/types.js +53 -18
  16. package/commands/utils/PathHelper.js +9 -2
  17. package/commands/utils/VersionChecker.js +3 -3
  18. package/commands/utils/bundling/DependencyAnalyzer.js +8 -16
  19. package/commands/utils/loadConfig.js +31 -0
  20. package/commands/utils/updateManager.js +3 -4
  21. package/docs/superpowers/specs/2026-05-10-pwa-generate-design.md +105 -105
  22. package/package.json +15 -3
  23. package/post.js +2 -2
  24. package/tests/bundle-generator.test.js +3 -20
  25. package/tests/component-registry-parse.test.js +34 -0
  26. package/tests/fixtures/components.js +8 -0
  27. package/tests/fixtures/sliceConfig.json +74 -0
  28. package/tests/getcomponent.test.js +407 -0
  29. package/tests/helpers/setup.js +97 -0
  30. package/tests/init-command-contract.test.js +46 -0
  31. package/tests/local-cli-delegation.test.js +7 -5
  32. package/tests/path-helper.test.js +206 -0
  33. package/tests/types-breakage.test.js +491 -0
  34. package/tests/types-generator-errors.test.js +361 -0
  35. package/tests/types-generator.test.js +172 -184
@@ -1,18 +1,15 @@
1
- // commands/buildProduction/buildProduction.js - VERSIÓN LIMPIA
1
+ // commands/buildProduction/buildProduction.js - CLEAN VERSION
2
2
 
3
3
  import fs from 'fs-extra';
4
4
  import path from 'path';
5
- import { fileURLToPath } from 'url';
6
5
  import { minify as terserMinify } from 'terser';
7
6
  import { minify } from 'html-minifier-terser';
8
7
  import CleanCSS from 'clean-css';
9
8
  import Print from '../Print.js';
10
9
  import { getSrcPath, getDistPath, getConfigPath } from '../utils/PathHelper.js';
11
10
 
12
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
-
14
11
  /**
15
- * Carga la configuración desde sliceConfig.json
12
+ * Loads configuration from sliceConfig.json
16
13
  */
17
14
  const loadConfig = () => {
18
15
  try {
@@ -26,7 +23,7 @@ const loadConfig = () => {
26
23
  };
27
24
 
28
25
  /**
29
- * Verifica dependencias necesarias para el build
26
+ * Checks necessary build dependencies
30
27
  */
31
28
  async function checkBuildDependencies() {
32
29
  const srcDir = getSrcPath(import.meta.url);
@@ -50,7 +47,7 @@ async function checkBuildDependencies() {
50
47
  }
51
48
 
52
49
  /**
53
- * Verifica que existan los archivos críticos para Slice.js
50
+ * Verifies that critical Slice.js files exist
54
51
  */
55
52
  async function verifySliceFiles(srcDir) {
56
53
  Print.info('Verifying Slice.js critical files...');
@@ -72,7 +69,7 @@ async function verifySliceFiles(srcDir) {
72
69
  }
73
70
 
74
71
  /**
75
- * Verifica la integridad del build para Slice.js
72
+ * Verifies build integrity for Slice.js
76
73
  */
77
74
  async function verifyBuildIntegrity(distDir) {
78
75
  Print.info('Verifying build integrity for Slice.js...');
@@ -101,7 +98,7 @@ async function verifyBuildIntegrity(distDir) {
101
98
  }
102
99
 
103
100
  /**
104
- * Copia sliceConfig.json al directorio dist
101
+ * Copies sliceConfig.json to the dist directory
105
102
  */
106
103
  async function copySliceConfig() {
107
104
  const srcConfig = getConfigPath(import.meta.url);
@@ -114,7 +111,7 @@ async function copySliceConfig() {
114
111
  }
115
112
 
116
113
  /**
117
- * Procesa un directorio completo
114
+ * Processes a complete directory
118
115
  */
119
116
  async function processDirectory(srcPath, distPath, baseSrcPath, options) {
120
117
  const items = await fs.readdir(srcPath);
@@ -134,7 +131,7 @@ async function processDirectory(srcPath, distPath, baseSrcPath, options) {
134
131
  }
135
132
 
136
133
  /**
137
- * Procesa un archivo individual
134
+ * Processes an individual file
138
135
  */
139
136
  async function processFile(srcFilePath, distFilePath, options) {
140
137
  const ext = path.extname(srcFilePath).toLowerCase();
@@ -200,7 +197,7 @@ async function processFile(srcFilePath, distFilePath, options) {
200
197
  }
201
198
 
202
199
  /**
203
- * Procesa el archivo components.js de forma especial
200
+ * Processes the components.js file in a special way
204
201
  */
205
202
  async function processComponentsFile(srcPath, distPath) {
206
203
  const content = await fs.readFile(srcPath, 'utf8');
@@ -229,7 +226,7 @@ async function processComponentsFile(srcPath, distPath) {
229
226
  }
230
227
 
231
228
  /**
232
- * Minifica archivos JavaScript preservando la arquitectura de Slice.js
229
+ * Minifies JavaScript files preserving Slice.js architecture
233
230
  */
234
231
  async function minifyJavaScript(srcPath, distPath) {
235
232
  const content = await fs.readFile(srcPath, 'utf8');
@@ -250,9 +247,9 @@ async function minifyJavaScript(srcPath, distPath) {
250
247
  reserved: [
251
248
  // Core Slice
252
249
  'slice', 'Slice', 'SliceJS', 'window', 'document',
253
- // Clases principales
250
+ // Main classes
254
251
  'Controller', 'StylesManager', 'Router', 'Logger', 'Debugger',
255
- // Métodos de Slice
252
+ // Slice methods
256
253
  'getClass', 'isProduction', 'getComponent', 'build', 'setTheme', 'attachTemplate',
257
254
  // Controller
258
255
  'componentCategories', 'templates', 'classes', 'requestedStyles', 'activeComponents',
@@ -269,7 +266,7 @@ async function minifyJavaScript(srcPath, distPath) {
269
266
  'onClickCallback', 'props',
270
267
  // Custom Elements
271
268
  'customElements', 'define', 'HTMLElement',
272
- // DOM APIs críticas
269
+ // Critical DOM APIs
273
270
  'addEventListener', 'removeEventListener', 'querySelector', 'querySelectorAll',
274
271
  'appendChild', 'removeChild', 'innerHTML', 'textContent', 'style', 'classList',
275
272
  // Lifecycle
@@ -308,7 +305,7 @@ async function minifyJavaScript(srcPath, distPath) {
308
305
  }
309
306
 
310
307
  /**
311
- * Minifica archivos CSS
308
+ * Minifies CSS files
312
309
  */
313
310
  async function minifyCSS(srcPath, distPath) {
314
311
  const content = await fs.readFile(srcPath, 'utf8');
@@ -334,7 +331,7 @@ async function minifyCSS(srcPath, distPath) {
334
331
  }
335
332
 
336
333
  /**
337
- * Minifica archivos HTML
334
+ * Minifies HTML files
338
335
  */
339
336
  async function minifyHTML(srcPath, distPath) {
340
337
  const content = await fs.readFile(srcPath, 'utf8');
@@ -367,7 +364,7 @@ async function minifyHTML(srcPath, distPath) {
367
364
  }
368
365
 
369
366
  /**
370
- * Crea un bundle optimizado del archivo principal
367
+ * Creates an optimized bundle of the main file
371
368
  */
372
369
  async function createOptimizedBundle() {
373
370
  Print.buildProgress('Creating optimized bundle...');
@@ -382,7 +379,7 @@ async function createOptimizedBundle() {
382
379
  }
383
380
 
384
381
  /**
385
- * Genera estadísticas del build
382
+ * Generates build statistics
386
383
  */
387
384
  async function generateBuildStats(srcDir, distDir) {
388
385
  Print.buildProgress('Generating build statistics...');
@@ -422,7 +419,7 @@ async function generateBuildStats(srcDir, distDir) {
422
419
  }
423
420
 
424
421
  /**
425
- * Analiza el build sin construir
422
+ * Analyzes the build without building
426
423
  */
427
424
  async function analyzeBuild() {
428
425
  const distDir = getDistPath(import.meta.url);
@@ -440,7 +437,7 @@ async function analyzeBuild() {
440
437
  }
441
438
 
442
439
  /**
443
- * FUNCIÓN PRINCIPAL DE BUILD
440
+ * MAIN BUILD FUNCTION
444
441
  */
445
442
  export default async function buildProduction(options = {}) {
446
443
  const startTime = Date.now();
@@ -458,7 +455,7 @@ export default async function buildProduction(options = {}) {
458
455
 
459
456
  await verifySliceFiles(srcDir);
460
457
 
461
- // Limpiar directorio dist
458
+ // Clean dist directory
462
459
  if (await fs.pathExists(distDir)) {
463
460
  if (!options.skipClean) {
464
461
  Print.info('Cleaning previous build...');
@@ -470,7 +467,7 @@ export default async function buildProduction(options = {}) {
470
467
  await fs.ensureDir(distDir);
471
468
  await copySliceConfig();
472
469
 
473
- // Procesar archivos
470
+ // Process files
474
471
  Print.info('Processing and optimizing source files for Slice.js...');
475
472
  await processDirectory(srcDir, distDir, srcDir, options);
476
473
  Print.success('All source files processed and optimized');
@@ -498,7 +495,7 @@ export default async function buildProduction(options = {}) {
498
495
  }
499
496
 
500
497
  /**
501
- * Servidor de preview para testing del build de producción
498
+ * Preview server for testing the production build
502
499
  */
503
500
  export async function serveProductionBuild(port) {
504
501
  try {
@@ -546,7 +543,7 @@ export async function serveProductionBuild(port) {
546
543
  }
547
544
 
548
545
  /**
549
- * Comando build con opciones
546
+ * Build command with options
550
547
  */
551
548
  export async function buildCommand(options = {}) {
552
549
  const config = loadConfig();
@@ -4,13 +4,14 @@ import fs from 'fs-extra';
4
4
  import DependencyAnalyzer from '../utils/bundling/DependencyAnalyzer.js';
5
5
  import BundleGenerator from '../utils/bundling/BundleGenerator.js';
6
6
  import Print from '..//Print.js';
7
+ import { getProjectRoot, getSrcPath } from '../utils/PathHelper.js';
7
8
 
8
9
  /**
9
10
  * Main bundling command
10
11
  */
11
12
  export default async function bundle(options = {}) {
12
13
  const startTime = Date.now();
13
- const projectRoot = process.cwd();
14
+ const projectRoot = getProjectRoot(import.meta.url);
14
15
 
15
16
  try {
16
17
  Print.title('📦 Slice.js Bundle Generator');
@@ -82,14 +83,14 @@ export default async function bundle(options = {}) {
82
83
  */
83
84
  async function validateProject(projectRoot) {
84
85
  const requiredPaths = [
85
- 'src/Components/components.js',
86
- 'src/routes.js'
86
+ getSrcPath(import.meta.url, 'Components', 'components.js'),
87
+ getSrcPath(import.meta.url, 'routes.js')
87
88
  ];
88
89
 
89
- for (const reqPath of requiredPaths) {
90
- const fullPath = path.join(projectRoot, reqPath);
90
+ for (const fullPath of requiredPaths) {
91
91
  if (!await fs.pathExists(fullPath)) {
92
- throw new Error(`Required file not found: ${reqPath}`);
92
+ const relativePath = path.relative(projectRoot, fullPath);
93
+ throw new Error(`Required file not found: ${relativePath}`);
93
94
  }
94
95
  }
95
96
  }
@@ -146,8 +147,7 @@ function printSummary(result, startTime) {
146
147
  * Subcommand: Clean bundles
147
148
  */
148
149
  export async function cleanBundles() {
149
- const projectRoot = process.cwd();
150
- const srcPath = path.join(projectRoot, 'src');
150
+ const srcPath = getSrcPath(import.meta.url);
151
151
 
152
152
  try {
153
153
  Print.title('🧹 Cleaning bundles...');
@@ -166,7 +166,7 @@ export async function cleanBundles() {
166
166
  }
167
167
 
168
168
  // Remove config
169
- const configPath = path.join(srcPath, 'bundle.config.json');
169
+ const configPath = getSrcPath(import.meta.url, 'bundle.config.json');
170
170
  if (await fs.pathExists(configPath)) {
171
171
  await fs.remove(configPath);
172
172
  console.log(` ✓ Deleted: bundle.config.json`);
@@ -185,8 +185,7 @@ export async function cleanBundles() {
185
185
  * Subcommand: Bundle information
186
186
  */
187
187
  export async function bundleInfo() {
188
- const projectRoot = process.cwd();
189
- const configPath = path.join(projectRoot, 'src/bundle.config.json');
188
+ const configPath = getSrcPath(import.meta.url, 'bundle.config.json');
190
189
 
191
190
  try {
192
191
  if (!await fs.pathExists(configPath)) {
@@ -2,21 +2,19 @@
2
2
  import componentTemplates from './VisualComponentTemplate.js';
3
3
  import fs from 'fs-extra';
4
4
  import path from 'path';
5
- import { fileURLToPath } from 'url';
6
5
  import Validations from '../Validations.js';
7
6
  import Print from '../Print.js';
8
7
  import { getSrcPath } from '../utils/PathHelper.js';
9
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
8
 
11
9
  function createComponent(componentName, category) {
12
- // Validación: Nombre de componente requerido
10
+ // Validation: Component name is required
13
11
  if (!componentName) {
14
12
  Print.error('Component name is required');
15
13
  Print.commandExample("Create a component", "slice component create");
16
14
  return false;
17
15
  }
18
16
 
19
- // Validación: Nombre de componente válido
17
+ // Validation: Valid component name
20
18
  if (!Validations.isValidComponentName(componentName)) {
21
19
  Print.error(`Invalid component name: '${componentName}'`);
22
20
  Print.info('Component name must start with a letter and contain only alphanumeric characters');
@@ -25,7 +23,7 @@ function createComponent(componentName, category) {
25
23
  return false;
26
24
  }
27
25
 
28
- // Validación: Componente ya existe
26
+ // Validation: Component already exists
29
27
  if(Validations.componentExists(componentName)){
30
28
  Print.error(`Component '${componentName}' already exists in your project`);
31
29
  Print.info('Please use a different name or delete the existing component first');
@@ -33,7 +31,7 @@ function createComponent(componentName, category) {
33
31
  return false;
34
32
  }
35
33
 
36
- // Validación: Categoría válida
34
+ // Validation: Valid category
37
35
  let flagCategory = Validations.isValidCategory(category);
38
36
 
39
37
  if (!flagCategory.isValid) {
@@ -44,14 +42,14 @@ function createComponent(componentName, category) {
44
42
  }
45
43
  category = flagCategory.category;
46
44
 
47
- // Crear el nombre de la clase y del archivo
45
+ // Create class name and file name
48
46
  const className = componentName.charAt(0).toUpperCase() + componentName.slice(1);
49
47
  const fileName = `${className}.js`;
50
48
  let template;
51
49
 
52
50
  const type = Validations.getCategoryType(category);
53
51
 
54
- // Generar template según el tipo
52
+ // Generate template based on type
55
53
  if(type === 'Visual'){
56
54
  template = componentTemplates.visual(className);
57
55
  } else if(type === 'Service'){
@@ -67,7 +65,7 @@ function createComponent(componentName, category) {
67
65
  const componentDir = getSrcPath(import.meta.url, categoryPathClean, className);
68
66
 
69
67
  try {
70
- // Crear directorio del componente
68
+ // Create component directory
71
69
  fs.ensureDirSync(componentDir);
72
70
  } catch (error) {
73
71
  Print.error(`Failed to create component directory: '${componentDir}'`);
@@ -75,10 +73,10 @@ function createComponent(componentName, category) {
75
73
  return false;
76
74
  }
77
75
 
78
- // Determinar la ruta del archivo
76
+ // Determine the file path
79
77
  let componentPath = path.join(componentDir, fileName);
80
78
 
81
- // Verificar si el archivo ya existe (doble verificación)
79
+ // Verify if the file already exists (double check)
82
80
  if (fs.existsSync(componentPath)) {
83
81
  Print.error(`Component file already exists at: '${componentPath}'`);
84
82
  Print.info('This component may have been created outside the CLI');
@@ -86,13 +84,13 @@ function createComponent(componentName, category) {
86
84
  }
87
85
 
88
86
  try {
89
- // Escribir el código del componente en el archivo
87
+ // Write component code to file
90
88
  fs.writeFileSync(componentPath, template);
91
89
 
92
- // Si es Visual, crear archivos adicionales (CSS y HTML)
90
+ // If Visual, create additional files (CSS and HTML)
93
91
  if(type === 'Visual'){
94
- const cssPath = `${componentDir}/${className}.css`;
95
- const htmlPath = `${componentDir}/${className}.html`;
92
+ const cssPath = path.join(componentDir, `${className}.css`);
93
+ const htmlPath = path.join(componentDir, `${className}.html`);
96
94
 
97
95
  fs.writeFileSync(cssPath, '/* Styles for ' + componentName + ' component */\n');
98
96
  fs.writeFileSync(htmlPath, `<div class="${componentName.toLowerCase()}">\n ${componentName}\n</div>`);
@@ -107,7 +105,7 @@ function createComponent(componentName, category) {
107
105
  Print.error(`Failed to create component files`);
108
106
  Print.info(`Error details: ${error.message}`);
109
107
 
110
- // Intentar limpiar archivos parcialmente creados
108
+ // Try to clean up partially created files
111
109
  try {
112
110
  if (fs.existsSync(componentDir)) {
113
111
  fs.removeSync(componentDir);
@@ -7,21 +7,21 @@ import { getSrcPath } from '../utils/PathHelper.js';
7
7
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
8
 
9
9
  function deleteComponent(componentName, category) {
10
- // Validación: Nombre de componente requerido
10
+ // Validation: Component name is required
11
11
  if (!componentName) {
12
12
  Print.error('Component name is required to delete');
13
13
  Print.commandExample("Delete a component", "slice component delete");
14
14
  return false;
15
15
  }
16
16
 
17
- // Validación: Nombre de componente válido
17
+ // Validation: Valid component name
18
18
  if (!Validations.isValidComponentName(componentName)) {
19
19
  Print.error(`Invalid component name: '${componentName}'`);
20
20
  Print.info('Component name must start with a letter and contain only alphanumeric characters');
21
21
  return false;
22
22
  }
23
23
 
24
- // Validación: Categoría válida
24
+ // Validation: Valid category
25
25
  let flagCategory = Validations.isValidCategory(category);
26
26
 
27
27
  if (!flagCategory.isValid) {
@@ -36,7 +36,7 @@ function deleteComponent(componentName, category) {
36
36
  const categoryPathClean = categoryPath ? categoryPath.replace(/^[/\\]+/, '') : '';
37
37
  const componentDir = getSrcPath(import.meta.url, categoryPathClean, componentName);
38
38
 
39
- // Verificar si el directorio del componente existe
39
+ // Check if component directory exists
40
40
  if (!fs.existsSync(componentDir)) {
41
41
  Print.error(`Component '${componentName}' does not exist in category '${category}'`);
42
42
  Print.info('Make sure you selected the correct category');
@@ -44,7 +44,7 @@ function deleteComponent(componentName, category) {
44
44
  return false;
45
45
  }
46
46
 
47
- // Verificar si es un directorio
47
+ // Verify it's a directory
48
48
  try {
49
49
  const stats = fs.statSync(componentDir);
50
50
  if (!stats.isDirectory()) {
@@ -58,7 +58,7 @@ function deleteComponent(componentName, category) {
58
58
  return false;
59
59
  }
60
60
 
61
- // Intentar eliminar el directorio del componente y su contenido
61
+ // Try to delete the component directory and its contents
62
62
  try {
63
63
  const files = fs.readdirSync(componentDir);
64
64
  Print.info(`Deleting ${files.length} file(s) from component directory...`);
@@ -1,6 +1,5 @@
1
1
  import fs from 'fs-extra';
2
2
  import path from 'path';
3
- import { fileURLToPath } from 'url';
4
3
  import { createServer } from 'net';
5
4
  import chalk from 'chalk';
6
5
  import Table from 'cli-table3';
@@ -11,10 +10,8 @@ import { promisify } from 'util';
11
10
  import { getProjectRoot, getSrcPath, getApiPath, getConfigPath, getPath } from '../utils/PathHelper.js';
12
11
  import updateManager from '../utils/updateManager.js';
13
12
 
14
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
-
16
13
  /**
17
- * Verifica la versión de Node.js
14
+ * Checks the Node.js version
18
15
  */
19
16
  async function checkNodeVersion() {
20
17
  const currentVersion = process.version;
@@ -36,7 +33,7 @@ async function checkNodeVersion() {
36
33
  }
37
34
 
38
35
  /**
39
- * Verifica la estructura de directorios
36
+ * Checks the directory structure
40
37
  */
41
38
  async function checkDirectoryStructure() {
42
39
  const srcPath = getSrcPath(import.meta.url);
@@ -64,7 +61,7 @@ async function checkDirectoryStructure() {
64
61
  }
65
62
 
66
63
  /**
67
- * Verifica sliceConfig.json
64
+ * Checks sliceConfig.json
68
65
  */
69
66
  async function checkConfig() {
70
67
  const configPath = getConfigPath(import.meta.url);
@@ -102,7 +99,7 @@ async function checkConfig() {
102
99
  }
103
100
 
104
101
  /**
105
- * Verifica disponibilidad del puerto
102
+ * Checks port availability
106
103
  */
107
104
  async function checkPort() {
108
105
  const configPath = getConfigPath(import.meta.url);
@@ -113,7 +110,7 @@ async function checkPort() {
113
110
  const config = await fs.readJson(configPath);
114
111
  port = config.server?.port || 3000;
115
112
  }
116
- } catch { }
113
+ } catch { /* config missing or unreadable — use default port */ }
117
114
 
118
115
  return new Promise((resolve) => {
119
116
  const server = createServer();
@@ -146,11 +143,11 @@ async function checkPort() {
146
143
  }
147
144
 
148
145
  /**
149
- * Verifica dependencias en package.json
146
+ * Checks dependencies in package.json
150
147
  */
151
148
  async function checkDependencies() {
152
149
  const projectRoot = getProjectRoot(import.meta.url);
153
- const packagePath = path.join(projectRoot, 'package.json');
150
+ const packagePath = getPath(import.meta.url, 'package.json');
154
151
 
155
152
  if (!await fs.pathExists(packagePath)) {
156
153
  return {
@@ -163,7 +160,7 @@ async function checkDependencies() {
163
160
  try {
164
161
  const pkg = await fs.readJson(packagePath);
165
162
  const hasFrameworkDep = pkg.dependencies?.['slicejs-web-framework'] || pkg.devDependencies?.['slicejs-web-framework'];
166
- const frameworkNodePath = path.join(projectRoot, 'node_modules', 'slicejs-web-framework', 'package.json');
163
+ const frameworkNodePath = getPath(import.meta.url, 'node_modules', 'slicejs-web-framework', 'package.json');
167
164
  const hasFrameworkNode = await fs.pathExists(frameworkNodePath);
168
165
  const hasFramework = !!(hasFrameworkDep || hasFrameworkNode);
169
166
 
@@ -194,7 +191,7 @@ async function checkDependencies() {
194
191
  }
195
192
 
196
193
  /**
197
- * Verifica integridad de componentes
194
+ * Checks component integrity
198
195
  */
199
196
  async function checkComponents() {
200
197
  const configPath = getConfigPath(import.meta.url);
@@ -228,7 +225,7 @@ async function checkComponents() {
228
225
  if (stat.isDirectory()) {
229
226
  totalComponents++;
230
227
 
231
- // Verificar archivos JS
228
+ // Check JS files
232
229
  const jsFile = path.join(itemPath, `${item}.js`);
233
230
  if (!await fs.pathExists(jsFile)) {
234
231
  componentIssues++;
@@ -260,7 +257,7 @@ async function checkComponents() {
260
257
  }
261
258
 
262
259
  /**
263
- * Comando principal de diagnóstico
260
+ * Main diagnostic command
264
261
  */
265
262
  export default async function runDiagnostics() {
266
263
  Print.newLine();