cskit-cli 1.0.6 → 1.0.8

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.6",
3
+ "version": "1.0.8",
4
4
  "description": "Content Suite Kit CLI - Download and manage CSK skills from private repository",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -92,31 +92,69 @@ async function setupPythonEnv(projectDir, spinner) {
92
92
  execSync(`python3 -m venv "${venvPath}"`, { stdio: 'pipe', cwd: libPythonDir });
93
93
  }
94
94
 
95
- // Install requirements with error handling
96
- spinner.text = 'Installing Python packages...';
95
+ // Parse requirements.txt
97
96
  const pipPath = path.join(venvPath, 'bin', 'pip');
97
+ const requirements = fs.readFileSync(requirementsFile, 'utf8')
98
+ .split('\n')
99
+ .map(line => line.trim())
100
+ .filter(line => line && !line.startsWith('#'));
98
101
 
99
- try {
100
- execSync(`"${pipPath}" install -r requirements.txt -q`, {
101
- stdio: 'pipe',
102
- cwd: libPythonDir
103
- });
104
- spinner.succeed(`Python environment ready (${pythonVersion})`);
102
+ if (requirements.length === 0) {
103
+ spinner.succeed('No packages to install');
105
104
  return { success: true, version: pythonVersion };
106
- } catch (pipError) {
107
- // Try installing without optional packages
108
- spinner.text = 'Retrying with core packages...';
105
+ }
106
+
107
+ // Upgrade pip first (silent)
108
+ spinner.text = 'Upgrading pip...';
109
+ try {
110
+ execSync(`"${pipPath}" install --upgrade pip -q`, { stdio: 'pipe', cwd: libPythonDir });
111
+ } catch { /* ignore pip upgrade errors */ }
112
+
113
+ // Install packages one by one with progress
114
+ spinner.stop();
115
+ console.log(chalk.dim(`\n Installing ${requirements.length} packages:\n`));
116
+
117
+ const installed = [];
118
+ const failed = [];
119
+
120
+ for (let i = 0; i < requirements.length; i++) {
121
+ const pkg = requirements[i];
122
+ const pkgName = pkg.split(/[>=<\[]/)[0]; // Extract package name
123
+ const progress = `[${i + 1}/${requirements.length}]`;
124
+
125
+ process.stdout.write(` ${chalk.dim(progress)} ${pkgName}... `);
126
+
109
127
  try {
110
- execSync(`"${pipPath}" install numpy pandas scipy pydantic rich click -q`, {
128
+ execSync(`"${pipPath}" install "${pkg}" -q`, {
111
129
  stdio: 'pipe',
112
- cwd: libPythonDir
130
+ cwd: libPythonDir,
131
+ timeout: 120000 // 2 min timeout per package
113
132
  });
114
- spinner.warn('Partial install - some optional packages failed');
115
- return { success: true, partial: true, version: pythonVersion };
116
- } catch {
117
- throw pipError;
133
+ console.log(chalk.green(''));
134
+ installed.push(pkgName);
135
+ } catch (err) {
136
+ console.log(chalk.red('✗'));
137
+ const errMsg = err.stderr ? err.stderr.toString().split('\n')[0] : err.message;
138
+ console.log(chalk.dim(` ${errMsg.slice(0, 60)}`));
139
+ failed.push(pkgName);
118
140
  }
119
141
  }
142
+
143
+ console.log('');
144
+
145
+ // Summary
146
+ if (failed.length === 0) {
147
+ spinner.succeed(`Python ready: ${installed.length} packages (${pythonVersion})`);
148
+ return { success: true, version: pythonVersion };
149
+ } else if (installed.length > 0) {
150
+ spinner.warn(`Partial: ${installed.length} ok, ${failed.length} failed`);
151
+ console.log(chalk.yellow(` Failed: ${failed.join(', ')}`));
152
+ console.log(chalk.dim(` Run manually: ${pipPath} install <package>\n`));
153
+ return { success: true, partial: true, version: pythonVersion, failed };
154
+ } else {
155
+ spinner.fail('All packages failed');
156
+ return { success: false, error: 'All packages failed to install' };
157
+ }
120
158
  } catch (error) {
121
159
  spinner.warn(`Python setup failed: ${error.message}`);
122
160
  return { success: false, error: error.message };
@@ -212,11 +250,13 @@ async function initCommand(options) {
212
250
  spinner.succeed(`Found ${releases.length} release(s)`);
213
251
  }
214
252
 
215
- // Version selection
253
+ // Version selection (show max 5 recent releases)
216
254
  let selectedVersion = 'main';
255
+ const maxVersions = 5;
217
256
 
218
257
  if (releases.length > 0 && !options.latest) {
219
- const choices = releases.map((r, i) => ({
258
+ const recentReleases = releases.slice(0, maxVersions);
259
+ const choices = recentReleases.map((r, i) => ({
220
260
  name: `${r.tag}${i === 0 ? chalk.green(' (latest)') : ''} - ${formatDate(r.published)}`,
221
261
  value: r.tag
222
262
  }));