slicejs-cli 3.6.2 → 3.6.3

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.
@@ -19,12 +19,12 @@ const COMPONENTS_REGISTRY_URL = 'https://raw.githubusercontent.com/VKneider/slic
19
19
  */
20
20
  const loadConfig = () => sharedLoadConfig(import.meta.url);
21
21
 
22
- const fetchWithRetry = async (url, retries = 3, baseDelay = 500) => {
22
+ const fetchWithRetry = async (url, retries = 3, baseDelay = 500, binary = false) => {
23
23
  for (let attempt = 0; attempt <= retries; attempt++) {
24
24
  try {
25
25
  const response = await fetch(url);
26
26
  if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);
27
- return await response.text();
27
+ return binary ? await response.arrayBuffer() : await response.text();
28
28
  } catch (e) {
29
29
  if (attempt === retries) throw e;
30
30
  const delay = baseDelay * Math.pow(2, attempt);
@@ -185,6 +185,9 @@ filterOfficialComponents(allComponents) {
185
185
  // Logical routing components only need JS
186
186
  if (['Route', 'MultiRoute', 'Link'].includes(name)) {
187
187
  files = [`${name}.js`];
188
+ } else if (name === 'Icon') {
189
+ // Icon component needs font files to render glyphs
190
+ files = [`${name}.js`, `${name}.html`, `${name}.css`, 'slc.eot', 'slc.woff2', 'slc.woff', 'slc.ttf', 'slc.svg'];
188
191
  } else {
189
192
  // Normal visual components need JS, HTML, CSS
190
193
  files = [`${name}.js`, `${name}.html`, `${name}.css`];
@@ -218,12 +221,18 @@ filterOfficialComponents(allComponents) {
218
221
  const total = component.files.length;
219
222
  let done = 0;
220
223
  const spinner = ora(`Downloading ${componentName} 0/${total}`).start();
224
+ const BINARY_EXTENSIONS = ['.eot', '.woff2', '.woff', '.ttf'];
221
225
  const worker = async (fileName) => {
222
226
  const url = `${DOCS_REPO_BASE_URL}/${category}/${componentName}/${fileName}`;
223
227
  const localPath = path.join(targetPath, fileName);
228
+ const isBinary = BINARY_EXTENSIONS.some(ext => fileName.endsWith(ext));
224
229
  try {
225
- const content = await fetchWithRetry(url);
226
- await fs.writeFile(localPath, content, 'utf8');
230
+ const content = await fetchWithRetry(url, 3, 500, isBinary);
231
+ if (isBinary) {
232
+ await fs.writeFile(localPath, Buffer.from(content));
233
+ } else {
234
+ await fs.writeFile(localPath, content, 'utf8');
235
+ }
227
236
  downloadedFiles.push(fileName);
228
237
  } catch (error) {
229
238
  Print.downloadError(fileName);
@@ -300,6 +300,7 @@ export default async function initializeProject(options = {}) {
300
300
  }
301
301
 
302
302
  // 3. DOWNLOAD ALL VISUAL COMPONENTS FROM OFFICIAL REPOSITORY
303
+ let visualResults = [];
303
304
  const componentsSpinner = ora('Loading component registry...').start();
304
305
  try {
305
306
  const registry = new ComponentRegistry();
@@ -307,25 +308,23 @@ export default async function initializeProject(options = {}) {
307
308
 
308
309
  // Install only the Visual components the starter project uses.
309
310
  const allVisualComponents = STARTER_VISUAL_COMPONENTS;
310
- Print.info(`Installing ${allVisualComponents.length} starter Visual components: ${allVisualComponents.join(', ')}`);
311
311
 
312
312
  if (allVisualComponents.length > 0) {
313
313
  componentsSpinner.text = `Installing ${allVisualComponents.length} starter Visual components...`;
314
314
 
315
- const results = await registry.installMultipleComponents(
315
+ visualResults = await registry.installMultipleComponents(
316
316
  allVisualComponents,
317
317
  'Visual',
318
318
  true // force = true for initial installation
319
319
  );
320
320
 
321
- const successful = results.filter(r => r.success).length;
322
- const failed = results.filter(r => !r.success).length;
321
+ const successful = visualResults.filter(r => r.success).length;
322
+ const failed = visualResults.filter(r => !r.success).length;
323
323
 
324
324
  if (successful > 0 && failed === 0) {
325
325
  componentsSpinner.succeed(`All ${successful} Visual components installed successfully`);
326
326
  } else if (successful > 0) {
327
327
  componentsSpinner.warn(`${successful} components installed, ${failed} failed`);
328
- Print.info(`You can install failed components later using "${packageManager} run get -- <component-name>"`);
329
328
  } else {
330
329
  componentsSpinner.fail('Failed to install Visual components');
331
330
  }
@@ -342,29 +341,28 @@ export default async function initializeProject(options = {}) {
342
341
  }
343
342
 
344
343
  // 3b. DOWNLOAD STARTER SERVICE COMPONENTS FROM OFFICIAL REPOSITORY
344
+ let serviceResults = [];
345
345
  const serviceSpinner = ora('Installing starter Service components...').start();
346
346
  try {
347
347
  const registry = new ComponentRegistry();
348
348
  await registry.loadRegistry();
349
349
 
350
350
  if (STARTER_SERVICE_COMPONENTS.length > 0) {
351
- Print.info(`Installing ${STARTER_SERVICE_COMPONENTS.length} starter Service components: ${STARTER_SERVICE_COMPONENTS.join(', ')}`);
352
351
  serviceSpinner.text = `Installing ${STARTER_SERVICE_COMPONENTS.length} starter Service components...`;
353
352
 
354
- const results = await registry.installMultipleComponents(
353
+ serviceResults = await registry.installMultipleComponents(
355
354
  STARTER_SERVICE_COMPONENTS,
356
355
  'Service',
357
356
  true // force = true for initial installation
358
357
  );
359
358
 
360
- const successful = results.filter(r => r.success).length;
361
- const failed = results.filter(r => !r.success).length;
359
+ const successful = serviceResults.filter(r => r.success).length;
360
+ const failed = serviceResults.filter(r => !r.success).length;
362
361
 
363
362
  if (successful > 0 && failed === 0) {
364
363
  serviceSpinner.succeed(`All ${successful} Service components installed successfully`);
365
364
  } else if (successful > 0) {
366
365
  serviceSpinner.warn(`${successful} Service components installed, ${failed} failed`);
367
- Print.info(`You can install failed components later using "${packageManager} run get -- <component-name>"`);
368
366
  } else {
369
367
  serviceSpinner.fail('Failed to install Service components');
370
368
  }
@@ -442,6 +440,12 @@ export default async function initializeProject(options = {}) {
442
440
  }
443
441
 
444
442
  const projectName = path.basename(process.cwd());
443
+
444
+ const failedCount = [...visualResults, ...serviceResults].filter(r => !r.success).length;
445
+ if (failedCount > 0) {
446
+ Print.warning(`${failedCount} component(s) failed to install — run "${packageManager} run get -- <name>" to retry`);
447
+ }
448
+
445
449
  Print.success(`Project initialized successfully in "${projectName}/"`);
446
450
  Print.newLine();
447
451
  Print.title('Next steps:');
@@ -11,7 +11,7 @@ export default function setupWatcher(serverProcess, onRestart) {
11
11
  Print.info('Watch mode enabled - monitoring file changes...');
12
12
  Print.newLine();
13
13
 
14
- const watcher = chokidar.watch(['src/**/*', 'api/**/*'], {
14
+ const watcher = chokidar.watch(['api/**/*'], {
15
15
  ignored: [
16
16
  /(^|[\/\\])\../, // hidden files
17
17
  '**/node_modules/**',
@@ -29,33 +29,20 @@ export default function setupWatcher(serverProcess, onRestart) {
29
29
 
30
30
  let reloadTimeout;
31
31
 
32
+ const handleChange = (changedPath) => {
33
+ clearTimeout(reloadTimeout);
34
+ reloadTimeout = setTimeout(() => {
35
+ if (onRestart) {
36
+ console.log(chalk.yellow('🔄 API change detected, restarting server...'));
37
+ onRestart(changedPath);
38
+ }
39
+ }, 500);
40
+ };
41
+
32
42
  watcher
33
- .on('change', (path) => {
34
- // Debounce to avoid multiple reloads
35
- clearTimeout(reloadTimeout);
36
- reloadTimeout = setTimeout(() => {
37
- if(onRestart) {
38
- console.log(chalk.yellow('🔄 Changes detected, restarting server...'));
39
- onRestart(path);
40
- } else {
41
- console.log(chalk.yellow('🔄 Changes detected, server will reload automatically... (No handler)'));
42
- }
43
- }, 500);
44
- })
45
- .on('add', (path) => {
46
- // console.log(chalk.green(`➕ New file added: ${path}`));
47
- clearTimeout(reloadTimeout);
48
- reloadTimeout = setTimeout(() => {
49
- if (onRestart) onRestart(path);
50
- }, 500);
51
- })
52
- .on('unlink', (path) => {
53
- // console.log(chalk.red(`➖ File removed: ${path}`));
54
- clearTimeout(reloadTimeout);
55
- reloadTimeout = setTimeout(() => {
56
- if (onRestart) onRestart(path);
57
- }, 500);
58
- })
43
+ .on('change', handleChange)
44
+ .on('add', handleChange)
45
+ .on('unlink', handleChange)
59
46
  .on('error', (error) => {
60
47
  Print.error(`Watcher error: ${error.message}`);
61
48
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slicejs-cli",
3
- "version": "3.6.2",
3
+ "version": "3.6.3",
4
4
  "description": "Command client for developing web applications with Slice.js framework",
5
5
  "main": "client.js",
6
6
  "bin": {