cskit-cli 1.0.26 → 1.0.28

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cskit-cli",
3
- "version": "1.0.26",
3
+ "version": "1.0.28",
4
4
  "description": "Content Suite Kit CLI - Download and manage CSK skills from private repository",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -67,6 +67,7 @@ class Timeline {
67
67
  this.currentStep = -1;
68
68
  this.lastLineCount = 0;
69
69
  this.isFirstRender = true;
70
+ this.isPaused = false;
70
71
  }
71
72
 
72
73
  addStep(name) {
@@ -103,15 +104,28 @@ class Timeline {
103
104
 
104
105
  // Call before any external output (prompts, logs, etc.)
105
106
  pause() {
107
+ // Don't update in-place after external output - just continue below
106
108
  this.lastLineCount = 0;
109
+ this.isPaused = true;
107
110
  }
108
111
 
109
112
  // Re-render timeline after external output
110
113
  resume() {
114
+ if (this.isPaused) {
115
+ // Print separator and continue fresh (no in-place update)
116
+ console.log(chalk.dim(' ─'.repeat(20)));
117
+ this.isPaused = false;
118
+ }
111
119
  this.isFirstRender = true;
112
120
  this.render();
113
121
  }
114
122
 
123
+ // Print final summary (no in-place update)
124
+ printSummary() {
125
+ this.lastLineCount = 0; // Disable in-place update
126
+ this.render();
127
+ }
128
+
115
129
  render() {
116
130
  // Build output lines
117
131
  const lines = [];
@@ -125,22 +139,25 @@ class Timeline {
125
139
 
126
140
  lines.push(` ${symbol} ${num} ${name}${msg}`);
127
141
 
128
- // Show children (files, etc.)
129
- for (let j = 0; j < step.children.length; j++) {
130
- const child = step.children[j];
131
- const isLast = j === step.children.length - 1;
132
- const branch = isLast ? SYMBOLS.branchLast : SYMBOLS.branch;
133
- const prefix = child.type === 'new' ? chalk.green('+') :
134
- child.type === 'update' ? chalk.blue('~') :
135
- child.type === 'skip' ? chalk.yellow('!') :
136
- child.type === 'delete' ? chalk.red('-') :
137
- chalk.dim('');
138
- lines.push(` ${SYMBOLS.indent}${branch} ${prefix} ${child.text}`);
142
+ // Show children only for active or done steps (not pending)
143
+ if (step.status !== 'pending') {
144
+ for (let j = 0; j < step.children.length; j++) {
145
+ const child = step.children[j];
146
+ const isLast = j === step.children.length - 1;
147
+ const branch = isLast ? SYMBOLS.branchLast : SYMBOLS.branch;
148
+ const prefix = child.type === 'new' ? chalk.green('+') :
149
+ child.type === 'update' ? chalk.blue('~') :
150
+ child.type === 'skip' ? chalk.yellow('!') :
151
+ child.type === 'delete' ? chalk.red('-') :
152
+ chalk.dim('•');
153
+ lines.push(` ${SYMBOLS.indent}${branch} ${prefix} ${child.text}`);
154
+ }
139
155
  }
140
156
  }
141
157
 
142
158
  // Clear previous output (move cursor up and clear lines)
143
- if (!this.isFirstRender && this.lastLineCount > 0) {
159
+ // Only do in-place update when not paused and have previous output
160
+ if (!this.isFirstRender && this.lastLineCount > 0 && !this.isPaused) {
144
161
  // Move cursor up and clear each line
145
162
  process.stdout.write(`\x1b[${this.lastLineCount}A`);
146
163
  for (let i = 0; i < this.lastLineCount; i++) {
@@ -360,20 +377,54 @@ async function installPackages(libPythonDir, packages, timeline, stepIndex, pyth
360
377
  }
361
378
  }
362
379
 
363
- // Install packages
380
+ // Get currently installed packages (to avoid reinstalling)
381
+ let installedPkgs = new Set();
382
+ try {
383
+ const freeze = execSync(`"${pipPath}" freeze`, { stdio: 'pipe' }).toString();
384
+ freeze.split('\n').forEach(line => {
385
+ const match = line.match(/^([^=]+)==/);
386
+ if (match) installedPkgs.add(match[1].toLowerCase());
387
+ });
388
+ } catch {}
389
+
390
+ // Install/update packages
364
391
  let success = true;
392
+ let installed = 0, skipped = 0, failed = 0;
393
+
365
394
  for (const pkg of packages) {
395
+ const pkgName = pkg.name.toLowerCase();
366
396
  const pkgSpec = pkg.required || pkg.name;
397
+
398
+ // Check if already installed (skip unless it's an update)
399
+ if (installedPkgs.has(pkgName) && !pkg.current) {
400
+ timeline.addChild(stepIndex, `${pkg.name} (already installed)`, 'info');
401
+ skipped++;
402
+ continue;
403
+ }
404
+
367
405
  try {
368
- execSync(`"${pipPath}" install "${pkgSpec}" -q`, {
406
+ execSync(`"${pipPath}" install "${pkgSpec}" -q --upgrade`, {
369
407
  stdio: 'pipe',
370
408
  cwd: libPythonDir,
371
409
  timeout: 120000
372
410
  });
373
- timeline.addChild(stepIndex, `${pkg.name}`, 'new');
411
+ if (pkg.current) {
412
+ timeline.addChild(stepIndex, `${pkg.name} (${pkg.current} → updated)`, 'update');
413
+ } else {
414
+ timeline.addChild(stepIndex, `${pkg.name}`, 'new');
415
+ }
416
+ installed++;
374
417
  } catch (error) {
375
- timeline.addChild(stepIndex, `${pkg.name} (failed)`, 'skip');
376
- success = false;
418
+ // Check if it was actually installed despite error
419
+ try {
420
+ const check = execSync(`"${pipPath}" show ${pkgName}`, { stdio: 'pipe' });
421
+ timeline.addChild(stepIndex, `${pkg.name} (already installed)`, 'info');
422
+ skipped++;
423
+ } catch {
424
+ timeline.addChild(stepIndex, `${pkg.name} (failed)`, 'skip');
425
+ failed++;
426
+ success = false;
427
+ }
377
428
  }
378
429
  }
379
430
 
@@ -639,45 +690,47 @@ async function initCommand(options) {
639
690
 
640
691
  const pkgStatus = checkPythonPackages(libPythonDir);
641
692
 
693
+ // Show Python version in timeline
694
+ timeline.addChild(6, `Python ${pythonCmd === 'python3' ? pythonInfo.version : '3.x'} (${pythonCmd})`, 'update');
695
+
696
+ // Show already installed count
642
697
  if (pkgStatus.installed.length > 0) {
643
- console.log(chalk.dim('\n Already installed:'));
644
- for (const pkg of pkgStatus.installed.slice(0, 5)) {
645
- console.log(chalk.dim(` ✓ ${pkg.name} (${pkg.version})`));
646
- }
647
- if (pkgStatus.installed.length > 5) {
648
- console.log(chalk.dim(` ... and ${pkgStatus.installed.length - 5} more\n`));
649
- }
698
+ timeline.addChild(6, `${pkgStatus.installed.length} packages already installed`, 'info');
650
699
  }
651
700
 
652
701
  const allToInstall = [...pkgStatus.toInstall, ...pkgStatus.toUpdate];
653
702
 
654
703
  if (allToInstall.length === 0) {
655
- timeline.complete(6, 'All packages ready');
704
+ timeline.complete(6, `${pkgStatus.installed.length} packages ready`);
656
705
  return;
657
706
  }
658
707
 
708
+ // Show what needs to be installed/updated
659
709
  console.log(chalk.cyan('\n Packages to install/update:\n'));
660
- for (const pkg of allToInstall) {
710
+ for (const pkg of allToInstall.slice(0, 10)) {
661
711
  if (pkg.current) {
662
- console.log(` ${pkg.name}: ${pkg.current} → ${pkg.required}`);
712
+ console.log(` ~ ${pkg.name}: ${pkg.current} → ${pkg.required}`);
663
713
  } else {
664
- console.log(` ${pkg.name}: ${pkg.required || 'latest'}`);
714
+ console.log(` + ${pkg.name}: ${pkg.required || 'latest'}`);
665
715
  }
666
716
  }
717
+ if (allToInstall.length > 10) {
718
+ console.log(chalk.dim(` ... and ${allToInstall.length - 10} more`));
719
+ }
667
720
  console.log('');
668
721
 
669
722
  timeline.pause();
670
723
  const { confirmPkgs } = await inquirer.prompt([{
671
724
  type: 'confirm',
672
725
  name: 'confirmPkgs',
673
- message: `Install ${allToInstall.length} packages?`,
726
+ message: `Install/update ${allToInstall.length} packages?`,
674
727
  default: true
675
728
  }]);
676
729
  timeline.resume();
677
730
 
678
731
  if (confirmPkgs) {
679
732
  await installPackages(libPythonDir, allToInstall, timeline, 6, pythonCmd);
680
- timeline.complete(6, `${allToInstall.length} packages`);
733
+ timeline.complete(6, `${pkgStatus.installed.length + allToInstall.length} packages`);
681
734
  } else {
682
735
  timeline.skip(6, 'User skipped');
683
736
  }