package-installer-cli 1.2.0 → 1.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/dist/commands/add.js +127 -84
- data/dist/commands/analyze.js +45 -37
- data/dist/commands/cache.js +141 -6
- data/dist/commands/check.js +121 -72
- data/dist/commands/clean.js +232 -93
- data/dist/commands/clone.js +65 -44
- data/dist/commands/create.js +76 -53
- data/dist/commands/deploy.js +28 -22
- data/dist/commands/doctor.js +26 -28
- data/dist/commands/env.js +44 -32
- data/dist/commands/update.js +598 -113
- data/dist/commands/upgrade-cli.js +30 -24
- data/dist/index.js +61 -16
- data/dist/utils/banner.js +3 -3
- data/dist/utils/cacheManager.js +57 -124
- data/dist/utils/dependencyInstaller.js +0 -2
- data/dist/utils/featureInstaller.js +404 -122
- data/dist/utils/helpFormatter.js +117 -0
- data/dist/utils/pathResolver.js +34 -72
- data/dist/utils/utils.js +20 -5
- metadata +3 -2
data/dist/commands/clean.js
CHANGED
|
@@ -5,37 +5,56 @@ import chalk from 'chalk';
|
|
|
5
5
|
import ora from 'ora';
|
|
6
6
|
import fs from 'fs-extra';
|
|
7
7
|
import path from 'path';
|
|
8
|
-
import {
|
|
8
|
+
import { createStandardHelp } from '../utils/helpFormatter.js';
|
|
9
|
+
import { displayCommandBanner } from '../utils/banner.js';
|
|
9
10
|
/**
|
|
10
11
|
* Display help for clean command
|
|
11
12
|
*/
|
|
12
13
|
export function showCleanHelp() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
14
|
+
const helpConfig = {
|
|
15
|
+
commandName: 'Clean',
|
|
16
|
+
emoji: '🧹',
|
|
17
|
+
description: 'Clean development artifacts, caches, and temporary files.\nSafely removes common build outputs, dependency caches, and temporary files to free up disk space and clean your project.',
|
|
18
|
+
usage: [
|
|
19
|
+
'clean [options]',
|
|
20
|
+
'cleanup [options] # alias'
|
|
21
|
+
],
|
|
22
|
+
options: [
|
|
23
|
+
{ flag: '--node-modules', description: 'Clean node_modules directories' },
|
|
24
|
+
{ flag: '--build', description: 'Clean build/dist directories' },
|
|
25
|
+
{ flag: '--cache', description: 'Clean package manager caches' },
|
|
26
|
+
{ flag: '--logs', description: 'Clean log files and debug outputs' },
|
|
27
|
+
{ flag: '--all', description: 'Clean everything (safe operation)' },
|
|
28
|
+
{ flag: '--deep', description: 'Deep clean (includes lock files)' },
|
|
29
|
+
{ flag: '--dry-run', description: 'Preview what would be cleaned' }
|
|
30
|
+
],
|
|
31
|
+
examples: [
|
|
32
|
+
{ command: 'clean --build', description: 'Clean build directories only' },
|
|
33
|
+
{ command: 'clean --node-modules', description: 'Clean node_modules directories' },
|
|
34
|
+
{ command: 'clean --all --dry-run', description: 'Preview what would be cleaned' },
|
|
35
|
+
{ command: 'clean --deep', description: 'Deep clean with lock files' },
|
|
36
|
+
{ command: 'clean --cache', description: 'Clean package manager caches' },
|
|
37
|
+
{ command: 'cleanup --all', description: 'Use alias command' }
|
|
38
|
+
],
|
|
39
|
+
additionalSections: [
|
|
40
|
+
{
|
|
41
|
+
title: 'Clean Targets',
|
|
42
|
+
items: [
|
|
43
|
+
'Build Outputs: dist, build, .next, out, target',
|
|
44
|
+
'Dependencies: node_modules, .pnpm-store',
|
|
45
|
+
'Caches: .cache, .npm, .yarn, __pycache__',
|
|
46
|
+
'Logs: *.log, npm-debug.log, yarn-error.log',
|
|
47
|
+
'Temp Files: .DS_Store, Thumbs.db, *.tmp'
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
tips: [
|
|
52
|
+
'Always use --dry-run first to preview changes',
|
|
53
|
+
'Deep clean removes lock files and requires dependency reinstall',
|
|
54
|
+
'Use --cache to clean package manager caches for more space'
|
|
55
|
+
]
|
|
56
|
+
};
|
|
57
|
+
createStandardHelp(helpConfig);
|
|
39
58
|
}
|
|
40
59
|
/**
|
|
41
60
|
* Main clean command function
|
|
@@ -46,63 +65,63 @@ export async function cleanCommand(options = {}) {
|
|
|
46
65
|
showCleanHelp();
|
|
47
66
|
return;
|
|
48
67
|
}
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
console.log(banner);
|
|
68
|
+
// Display command banner
|
|
69
|
+
displayCommandBanner('Clean', 'Clean development artifacts, caches, and temporary files from your project');
|
|
70
|
+
console.log(chalk.hex('#ffa502')('🧹 Project Cleaner\n'));
|
|
53
71
|
const projectPath = process.cwd();
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
if (options['node-modules'])
|
|
63
|
-
cleanTargets.push('node-modules');
|
|
64
|
-
if (options['build'])
|
|
65
|
-
cleanTargets.push('build');
|
|
66
|
-
if (options['cache'])
|
|
67
|
-
cleanTargets.push('cache');
|
|
68
|
-
if (options['logs'])
|
|
69
|
-
cleanTargets.push('logs');
|
|
70
|
-
if (options['deep'])
|
|
71
|
-
cleanTargets.push('lock-files');
|
|
72
|
-
}
|
|
73
|
-
if (cleanTargets.length === 0) {
|
|
74
|
-
console.log(chalk.yellow('No clean targets specified. Use --help for options.'));
|
|
72
|
+
const isDryRun = options['dryRun'] || options['dry-run'];
|
|
73
|
+
// Determine what to clean based on flags
|
|
74
|
+
const targets = determineCleanTargets(options);
|
|
75
|
+
if (targets.length === 0) {
|
|
76
|
+
console.log(chalk.yellow('⚠️ No clean targets specified. Use --help for available options.'));
|
|
77
|
+
console.log(chalk.gray('💡 Tip: Use --all for a safe clean of common artifacts'));
|
|
75
78
|
return;
|
|
76
79
|
}
|
|
77
|
-
if (
|
|
78
|
-
console.log(chalk.
|
|
80
|
+
if (isDryRun) {
|
|
81
|
+
console.log(chalk.cyan('🔍 DRY RUN - Preview of what would be cleaned:\n'));
|
|
79
82
|
}
|
|
80
|
-
|
|
83
|
+
else {
|
|
84
|
+
console.log(chalk.cyan('🧹 Starting cleanup process...\n'));
|
|
85
|
+
}
|
|
86
|
+
const spinner = ora(chalk.hex('#ffa502')(isDryRun ? 'Analyzing files...' : 'Cleaning project...')).start();
|
|
81
87
|
try {
|
|
82
|
-
let
|
|
88
|
+
let totalSize = 0;
|
|
83
89
|
const results = [];
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
-
|
|
90
|
+
let itemsCleaned = 0;
|
|
91
|
+
for (const target of targets) {
|
|
92
|
+
spinner.text = `${isDryRun ? 'Analyzing' : 'Cleaning'} ${target.name}...`;
|
|
93
|
+
const targetSize = await cleanTarget(projectPath, target, isDryRun);
|
|
94
|
+
if (targetSize > 0) {
|
|
95
|
+
totalSize += targetSize;
|
|
96
|
+
itemsCleaned++;
|
|
97
|
+
results.push(`${target.name}: ${formatFileSize(targetSize)}`);
|
|
91
98
|
}
|
|
92
99
|
}
|
|
93
100
|
spinner.stop();
|
|
94
|
-
if (
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
if (totalSize > 0) {
|
|
102
|
+
const action = isDryRun ? 'would be cleaned' : 'cleaned';
|
|
103
|
+
console.log(chalk.green(`\n✅ ${isDryRun ? 'Analysis' : 'Cleanup'} completed!`));
|
|
104
|
+
console.log(chalk.white(`📊 Total ${action}: ${chalk.bold(formatFileSize(totalSize))}`));
|
|
105
|
+
console.log(chalk.white(`📁 Items ${action}: ${chalk.bold(itemsCleaned)}`));
|
|
106
|
+
if (results.length > 0) {
|
|
107
|
+
console.log(chalk.cyan('\n📋 Breakdown:'));
|
|
108
|
+
results.forEach(result => {
|
|
109
|
+
console.log(chalk.gray(` • ${result}`));
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
if (isDryRun) {
|
|
113
|
+
console.log(chalk.yellow('\n💡 Run without --dry-run to actually clean these files'));
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
console.log(chalk.green('\n🎉 Project successfully cleaned!'));
|
|
117
|
+
}
|
|
99
118
|
}
|
|
100
119
|
else {
|
|
101
|
-
console.log(chalk.
|
|
120
|
+
console.log(chalk.green('✨ Nothing to clean - project is already tidy!'));
|
|
102
121
|
}
|
|
103
122
|
}
|
|
104
123
|
catch (error) {
|
|
105
|
-
spinner.fail(chalk.red('❌ Failed to clean project'));
|
|
124
|
+
spinner.fail(chalk.red(isDryRun ? '❌ Failed to analyze files' : '❌ Failed to clean project'));
|
|
106
125
|
console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
107
126
|
process.exit(1);
|
|
108
127
|
}
|
|
@@ -112,49 +131,59 @@ export async function cleanCommand(options = {}) {
|
|
|
112
131
|
*/
|
|
113
132
|
function determineCleanTargets(options) {
|
|
114
133
|
const targets = [];
|
|
115
|
-
|
|
134
|
+
// Handle --node-modules flag
|
|
135
|
+
if (options.all || options['nodeModules'] || options['node-modules']) {
|
|
116
136
|
targets.push({
|
|
117
137
|
name: 'node_modules',
|
|
118
|
-
patterns: ['**/node_modules'],
|
|
138
|
+
patterns: ['node_modules', '**/node_modules'],
|
|
119
139
|
description: 'Node.js dependencies'
|
|
120
140
|
});
|
|
121
141
|
}
|
|
142
|
+
// Handle --build flag
|
|
122
143
|
if (options.all || options.build) {
|
|
123
144
|
targets.push({
|
|
124
145
|
name: 'build outputs',
|
|
125
|
-
patterns: ['dist', 'build', '.next', 'out', 'target/debug', 'target/release'],
|
|
146
|
+
patterns: ['dist', 'build', '.next', 'out', 'target/debug', 'target/release', '.output', '.nuxt'],
|
|
126
147
|
description: 'Build outputs and compiled files'
|
|
127
148
|
});
|
|
128
149
|
}
|
|
150
|
+
// Handle --cache flag
|
|
129
151
|
if (options.all || options.cache) {
|
|
130
152
|
targets.push({
|
|
131
|
-
name: 'caches',
|
|
132
|
-
patterns: ['.cache', '.npm', '.yarn', '.pnpm-store', '__pycache__'],
|
|
153
|
+
name: 'package manager caches',
|
|
154
|
+
patterns: ['.cache', '.npm', '.yarn', '.pnpm-store', '.pnpm', '__pycache__', '.pytest_cache', 'target/debug/deps', 'target/release/deps'],
|
|
133
155
|
description: 'Package manager and build caches'
|
|
134
156
|
});
|
|
135
157
|
}
|
|
158
|
+
// Handle --logs flag
|
|
136
159
|
if (options.all || options.logs) {
|
|
137
160
|
targets.push({
|
|
138
|
-
name: '
|
|
139
|
-
patterns: ['*.log', 'logs
|
|
140
|
-
description: 'Log files'
|
|
161
|
+
name: 'log files',
|
|
162
|
+
patterns: ['*.log', 'logs', 'log', '*.log.*', 'npm-debug.log*', 'yarn-debug.log*', 'yarn-error.log*'],
|
|
163
|
+
description: 'Log files and debug outputs'
|
|
141
164
|
});
|
|
142
165
|
}
|
|
166
|
+
// Handle --deep flag (includes lock files)
|
|
143
167
|
if (options.deep) {
|
|
144
168
|
targets.push({
|
|
145
|
-
name: 'lock files',
|
|
146
|
-
patterns: ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'Cargo.lock'],
|
|
169
|
+
name: 'dependency lock files',
|
|
170
|
+
patterns: ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'Cargo.lock', 'Pipfile.lock', 'poetry.lock'],
|
|
147
171
|
description: 'Dependency lock files (requires reinstall)'
|
|
148
172
|
});
|
|
149
|
-
|
|
150
|
-
// Default to safe clean if no options specified
|
|
151
|
-
if (targets.length === 0) {
|
|
173
|
+
// Add more aggressive cleaning for deep clean
|
|
152
174
|
targets.push({
|
|
153
|
-
name: '
|
|
154
|
-
patterns: ['
|
|
155
|
-
description: '
|
|
175
|
+
name: 'temporary files',
|
|
176
|
+
patterns: ['.tmp', 'tmp', '.temp', 'temp', '.DS_Store', 'Thumbs.db', '*.tmp', '*.temp'],
|
|
177
|
+
description: 'Temporary files and system artifacts'
|
|
156
178
|
});
|
|
157
179
|
}
|
|
180
|
+
// If no specific options are provided and not --all, show available options
|
|
181
|
+
const hasSpecificOption = options['nodeModules'] || options['node-modules'] ||
|
|
182
|
+
options.build || options.cache || options.logs ||
|
|
183
|
+
options.deep || options.all;
|
|
184
|
+
if (!hasSpecificOption) {
|
|
185
|
+
return []; // Return empty to show help message
|
|
186
|
+
}
|
|
158
187
|
return targets;
|
|
159
188
|
}
|
|
160
189
|
/**
|
|
@@ -163,22 +192,132 @@ function determineCleanTargets(options) {
|
|
|
163
192
|
async function cleanTarget(projectPath, target, dryRun) {
|
|
164
193
|
let totalSize = 0;
|
|
165
194
|
for (const pattern of target.patterns) {
|
|
166
|
-
const fullPath = path.join(projectPath, pattern);
|
|
167
195
|
try {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
196
|
+
// Handle different pattern types
|
|
197
|
+
if (pattern.includes('*')) {
|
|
198
|
+
// Handle glob patterns
|
|
199
|
+
totalSize += await cleanGlobPattern(projectPath, pattern, dryRun);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
// Handle direct paths
|
|
203
|
+
const fullPath = path.join(projectPath, pattern);
|
|
204
|
+
if (await fs.pathExists(fullPath)) {
|
|
205
|
+
const size = await getDirectorySize(fullPath);
|
|
206
|
+
totalSize += size;
|
|
207
|
+
if (!dryRun && size > 0) {
|
|
208
|
+
await fs.remove(fullPath);
|
|
209
|
+
}
|
|
173
210
|
}
|
|
174
211
|
}
|
|
175
212
|
}
|
|
176
213
|
catch (error) {
|
|
177
|
-
//
|
|
214
|
+
// Silently ignore permission errors or other filesystem issues
|
|
215
|
+
// This is expected behavior for clean operations
|
|
178
216
|
}
|
|
179
217
|
}
|
|
180
218
|
return totalSize;
|
|
181
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Clean files matching a glob pattern
|
|
222
|
+
*/
|
|
223
|
+
async function cleanGlobPattern(projectPath, pattern, dryRun) {
|
|
224
|
+
let totalSize = 0;
|
|
225
|
+
try {
|
|
226
|
+
// Import glob dynamically
|
|
227
|
+
const { glob } = await import('glob');
|
|
228
|
+
const matches = await glob(pattern, {
|
|
229
|
+
cwd: projectPath,
|
|
230
|
+
absolute: false,
|
|
231
|
+
dot: true,
|
|
232
|
+
ignore: ['node_modules/node_modules/**'] // Avoid nested node_modules issues
|
|
233
|
+
});
|
|
234
|
+
const matchArray = Array.isArray(matches) ? matches : [matches];
|
|
235
|
+
for (const match of matchArray) {
|
|
236
|
+
if (!match)
|
|
237
|
+
continue;
|
|
238
|
+
const fullPath = path.join(projectPath, match);
|
|
239
|
+
try {
|
|
240
|
+
if (await fs.pathExists(fullPath)) {
|
|
241
|
+
const size = await getDirectorySize(fullPath);
|
|
242
|
+
totalSize += size;
|
|
243
|
+
if (!dryRun && size > 0) {
|
|
244
|
+
await fs.remove(fullPath);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
// Skip files that can't be accessed
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
// Fallback to simple directory walking for pattern matching
|
|
255
|
+
totalSize += await fallbackPatternMatch(projectPath, pattern, dryRun);
|
|
256
|
+
}
|
|
257
|
+
return totalSize;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Fallback pattern matching when glob is not available
|
|
261
|
+
*/
|
|
262
|
+
async function fallbackPatternMatch(projectPath, pattern, dryRun) {
|
|
263
|
+
let totalSize = 0;
|
|
264
|
+
// Handle common patterns manually
|
|
265
|
+
if (pattern.includes('**')) {
|
|
266
|
+
// Recursive pattern - search directories
|
|
267
|
+
const basePattern = pattern.replace('**/', '').replace('*', '');
|
|
268
|
+
await walkDirectory(projectPath, async (filePath) => {
|
|
269
|
+
if (filePath.includes(basePattern)) {
|
|
270
|
+
try {
|
|
271
|
+
const size = await getDirectorySize(filePath);
|
|
272
|
+
totalSize += size;
|
|
273
|
+
if (!dryRun && size > 0) {
|
|
274
|
+
await fs.remove(filePath);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
// Skip on error
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
// Simple pattern
|
|
285
|
+
const simplePattern = pattern.replace('*', '');
|
|
286
|
+
const fullPath = path.join(projectPath, simplePattern);
|
|
287
|
+
if (await fs.pathExists(fullPath)) {
|
|
288
|
+
const size = await getDirectorySize(fullPath);
|
|
289
|
+
totalSize += size;
|
|
290
|
+
if (!dryRun && size > 0) {
|
|
291
|
+
await fs.remove(fullPath);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return totalSize;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Walk directory recursively
|
|
299
|
+
*/
|
|
300
|
+
async function walkDirectory(dir, callback) {
|
|
301
|
+
try {
|
|
302
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
303
|
+
for (const entry of entries) {
|
|
304
|
+
const fullPath = path.join(dir, entry.name);
|
|
305
|
+
if (entry.isDirectory()) {
|
|
306
|
+
await callback(fullPath);
|
|
307
|
+
// Recurse into subdirectory (with depth limit to avoid infinite loops)
|
|
308
|
+
if (!entry.name.startsWith('.') && entry.name !== 'node_modules') {
|
|
309
|
+
await walkDirectory(fullPath, callback);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
await callback(fullPath);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
// Skip directories that can't be read
|
|
319
|
+
}
|
|
320
|
+
}
|
|
182
321
|
/**
|
|
183
322
|
* Get directory size recursively
|
|
184
323
|
*/
|
data/dist/commands/clone.js
CHANGED
|
@@ -1,54 +1,73 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import gradient from 'gradient-string';
|
|
3
|
-
import boxen from 'boxen';
|
|
4
2
|
import path from 'path';
|
|
5
3
|
import { cloneRepo as cloneRepoUtil } from '../utils/cloneUtils.js';
|
|
6
4
|
import { CacheManager } from '../utils/cacheUtils.js';
|
|
5
|
+
import { createStandardHelp } from '../utils/helpFormatter.js';
|
|
7
6
|
/**
|
|
8
|
-
* Display help for clone command
|
|
7
|
+
* Display help for clone command using standardized format
|
|
9
8
|
*/
|
|
10
9
|
export function showCloneHelp() {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
10
|
+
const helpConfig = {
|
|
11
|
+
commandName: 'Clone',
|
|
12
|
+
emoji: '📥',
|
|
13
|
+
description: 'Clone any public repository from GitHub, GitLab, BitBucket, or SourceHut.\nAutomatically installs dependencies, creates .env files, and tracks usage.',
|
|
14
|
+
usage: [
|
|
15
|
+
'clone <user/repo> [project-name] [options]',
|
|
16
|
+
'clone [options]'
|
|
17
|
+
],
|
|
18
|
+
options: [
|
|
19
|
+
{ flag: '--offline', description: 'Use cached templates if available' },
|
|
20
|
+
{ flag: '--no-deps', description: 'Skip dependency installation' },
|
|
21
|
+
{ flag: '--no-git', description: 'Skip git initialization' },
|
|
22
|
+
{ flag: '--shallow', description: 'Create shallow clone (faster)' },
|
|
23
|
+
{ flag: '--branch <name>', description: 'Clone specific branch' },
|
|
24
|
+
{ flag: '--template', description: 'Treat as template repository' }
|
|
25
|
+
],
|
|
26
|
+
examples: [
|
|
27
|
+
{ command: 'clone facebook/react', description: 'Clone from GitHub' },
|
|
28
|
+
{ command: 'clone facebook/react my-app', description: 'Clone with custom name' },
|
|
29
|
+
{ command: 'clone gitlab:user/project', description: 'Clone from GitLab' },
|
|
30
|
+
{ command: 'clone bitbucket:user/repo', description: 'Clone from BitBucket' },
|
|
31
|
+
{ command: 'clone sourcehut:user/repo', description: 'Clone from SourceHut' },
|
|
32
|
+
{ command: 'clone user/repo --offline', description: 'Use cached version' },
|
|
33
|
+
{ command: 'clone user/repo --no-deps', description: 'Skip dependencies' },
|
|
34
|
+
{ command: 'clone user/repo --shallow', description: 'Shallow clone' }
|
|
35
|
+
],
|
|
36
|
+
additionalSections: [
|
|
37
|
+
{
|
|
38
|
+
title: 'Supported Platforms',
|
|
39
|
+
items: [
|
|
40
|
+
'GitHub (default): user/repo',
|
|
41
|
+
'GitLab: gitlab:user/repo',
|
|
42
|
+
'BitBucket: bitbucket:user/repo',
|
|
43
|
+
'SourceHut: sourcehut:user/repo'
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
title: 'Features',
|
|
48
|
+
items: [
|
|
49
|
+
'Automatic dependency installation',
|
|
50
|
+
'Environment file creation from templates',
|
|
51
|
+
'Git repository initialization',
|
|
52
|
+
'Usage tracking and history',
|
|
53
|
+
'Offline mode with cached templates',
|
|
54
|
+
'Shallow cloning for faster downloads',
|
|
55
|
+
'Branch-specific cloning'
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
tips: [
|
|
60
|
+
'Use --offline flag for cached repositories to work without internet',
|
|
61
|
+
'Shallow clones are faster but have limited git history'
|
|
62
|
+
]
|
|
63
|
+
};
|
|
64
|
+
createStandardHelp(helpConfig);
|
|
46
65
|
}
|
|
47
66
|
export async function cloneRepo(userRepo, projectName, options = {}) {
|
|
48
67
|
const startTime = Date.now();
|
|
49
68
|
const cacheManager = new CacheManager();
|
|
50
69
|
// Check for help flag
|
|
51
|
-
if (
|
|
70
|
+
if (options.help || options['-h'] || options['--help']) {
|
|
52
71
|
showCloneHelp();
|
|
53
72
|
return;
|
|
54
73
|
}
|
|
@@ -58,12 +77,14 @@ export async function cloneRepo(userRepo, projectName, options = {}) {
|
|
|
58
77
|
actualProjectName = path.basename(process.cwd());
|
|
59
78
|
console.log(chalk.cyan(`Using current directory name: ${chalk.bold(actualProjectName)}`));
|
|
60
79
|
}
|
|
61
|
-
//
|
|
62
|
-
const args = process.argv.slice(3);
|
|
80
|
+
// Configure clone options from passed options
|
|
63
81
|
const cloneOptions = {
|
|
64
|
-
offline:
|
|
65
|
-
noDeps:
|
|
66
|
-
noGit:
|
|
82
|
+
offline: options.offline || false,
|
|
83
|
+
noDeps: options.noDeps || options['no-deps'] || false,
|
|
84
|
+
noGit: options.noGit || options['no-git'] || false,
|
|
85
|
+
shallow: options.shallow || false,
|
|
86
|
+
branch: options.branch || null,
|
|
87
|
+
template: options.template || false,
|
|
67
88
|
...options
|
|
68
89
|
};
|
|
69
90
|
try {
|