d-drive-cli 2.2.1 → 2.2.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.
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
- # D-Drive CLI v2.2.1
1
+ # D-Drive CLI v2.2.2
2
2
 
3
3
  Command-line tool for D-Drive cloud storage.
4
4
 
5
5
  ```
6
6
  ╔═══════════════════════════════════════╗
7
- ║ D-Drive CLI v2.2.1
7
+ ║ D-Drive CLI v2.2.2
8
8
  ║ Discord-based cloud storage ║
9
9
  ╚═══════════════════════════════════════╝
10
10
  ```
@@ -19,28 +19,30 @@ npm install -g d-drive-cli
19
19
  npx d-drive-cli
20
20
  ```
21
21
 
22
- After installation, use the `d-drive` command:
22
+ After installation, you can use either command:
23
+ - `d-drive` - Full command name
24
+ - `drive` - Short alias
23
25
 
24
26
  ## Quick Start
25
27
 
26
28
  ```bash
27
29
  # Interactive configuration (recommended)
28
- d-drive config
30
+ drive config
29
31
 
30
32
  # Or set API key directly
31
- d-drive config --key YOUR_API_KEY --url https://your-server/api
33
+ drive config --key YOUR_API_KEY --url https://your-server/api
32
34
 
33
35
  # Check connection
34
- d-drive info
36
+ drive info
35
37
 
36
38
  # Upload a file
37
- d-drive upload ./backup.zip
39
+ drive upload ./backup.zip
38
40
 
39
41
  # List files
40
- d-drive ls
42
+ drive ls
41
43
 
42
44
  # Download a file
43
- d-drive download /backup.zip ./local-backup.zip
45
+ drive download /backup.zip ./local-backup.zip
44
46
  ```
45
47
 
46
48
  ## Commands
@@ -49,18 +51,18 @@ d-drive download /backup.zip ./local-backup.zip
49
51
 
50
52
  ```bash
51
53
  # Interactive setup
52
- d-drive config
54
+ drive config
53
55
 
54
56
  # Set API key
55
- d-drive config --key dd_your_api_key
57
+ drive config --key dd_your_api_key
56
58
 
57
59
  # Set API URL
58
- d-drive config --url https://your-server/api
60
+ drive config --url https://your-server/api
59
61
 
60
62
  # View current config
61
- d-drive config --list
63
+ drive config --list
62
64
  # or
63
- d-drive config -l
65
+ drive config -l
64
66
  ```
65
67
 
66
68
  ### File Operations
@@ -68,92 +70,111 @@ d-drive config -l
68
70
  #### Upload
69
71
 
70
72
  ```bash
71
- # Upload single file
72
- d-drive upload ./file.txt
73
+ # Upload single file (encrypted by default)
74
+ drive upload ./file.txt
73
75
 
74
76
  # Upload to specific folder
75
- d-drive upload ./file.txt /backups/
77
+ drive upload ./file.txt /backups/
76
78
 
77
79
  # Upload directory recursively
78
- d-drive upload ./myproject /backups/ -r
79
-
80
- # Upload with encryption
81
- d-drive upload ./sensitive.txt -e
80
+ drive upload ./myproject /backups/ -r
82
81
  ```
83
82
 
83
+ > **Note:** All CLI uploads are **encrypted by default** for security. Files are encrypted server-side using AES-256-GCM encryption before storage.
84
+
84
85
  #### Download
85
86
 
86
87
  ```bash
87
- # Download file
88
- d-drive download /backups/file.txt
88
+ # Download file (automatically decrypted)
89
+ drive download /backups/file.txt
89
90
 
90
91
  # Download to specific location
91
- d-drive download /backups/file.txt ./local-file.txt
92
+ drive download /backups/file.txt ./local-file.txt
92
93
  ```
93
94
 
95
+ > **Note:** Encrypted files are automatically decrypted during download.
96
+
94
97
  #### List
95
98
 
96
99
  ```bash
97
100
  # List root directory
98
- d-drive ls
101
+ drive ls
99
102
 
100
103
  # List specific directory
101
- d-drive ls /backups
104
+ drive ls /backups
102
105
 
103
106
  # Long format with details
104
- d-drive ls -l
105
- d-drive ls /backups -l
107
+ drive ls -l
108
+ drive ls /backups -l
106
109
  ```
107
110
 
108
111
  #### Delete
109
-
110
- ```bash
111
- # Delete file (with confirmation)
112
- d-drive rm /old-file.txt
112
+ , moves to recycle bin)
113
+ drive rm /old-file.txt
113
114
 
114
115
  # Force delete without confirmation
115
- d-drive rm /old-file.txt -f
116
+ drive rm /old-file.txt -f
117
+ ```
116
118
 
117
- # Delete directory recursively
118
- d-drive rm /old-folder -r
119
+ > **Note:** Deleted files are moved to the recycle bin and can be restored via the web interface. The `-r` flag is accepted but directory deletion operates the same way (moves entire directory to recycle bin).elete directory recursively
120
+ drive rm /old-folder -r
119
121
  ```
120
122
 
121
123
  #### Copy
122
124
 
123
125
  ```bash
124
126
  # Create a copy of a file
125
- d-drive cp /backups/file.txt
127
+ drive cp /backups/file.txt
126
128
  # Creates: /backups/file (1).txt
127
129
  ```
128
130
 
129
131
  ### Task Management
130
-
131
- D-Drive supports SFTP backup tasks that can be managed via CLI.
132
+ Tasks run on a schedule (cron) to automatically backup files from remote SFTP servers.
132
133
 
133
134
  ```bash
134
- # List all tasks
135
- d-drive tasks ls
135
+ # List all tasks with status
136
+ drive tasks ls
136
137
 
137
- # Run a task immediately
138
- d-drive tasks run <task-id>
138
+ # Run a task immediately (ignores schedule)
139
+ drive tasks run <task-id>
139
140
 
140
141
  # Stop a running task
141
- d-drive tasks stop <task-id>
142
+ drive tasks stop <task-id>
143
+
144
+ # Enable a task (allows scheduled runs)
145
+ drive tasks enable <task-id>
146
+
147
+ # Disable a task (prevents scheduled runs)
148
+ drive tasks disable <task-id>
142
149
 
143
- # Enable/disable a task
144
- d-drive tasks enable <task-id>
145
- d-drive tasks disable <task-id>
150
+ # Delete a task (with confirmation)
151
+ drive tasks rm <task-id>
146
152
 
147
- # Delete a task
148
- d-drive tasks rm <task-id>
149
- d-drive tasks rm <task-id> -f # Force delete
153
+ # Force delete without confirmation
154
+ drive tasks rm <task-id> -f
155
+ ```
156
+
157
+ **Task List Output:**
158
+ ```
159
+ 📋 SFTP Backup Tasks:
160
+ ────────────────────────────────────────────────────────
161
+ ID: clmxyz123...
162
+ Name: Daily Backup
163
+ Status: ✓ Running (5m 23s) | ⏸ Stopped | ✓ Enabled
164
+ Schedule: 0 2 * * * (daily at 2:00 AM)
165
+ SFTP: user@server.example.com:22 → /backups/
166
+ Compression: GZIP | Keep: 5 files
167
+ ────────────────────────────────────────────────────────
168
+ ```
169
+
170
+ > **Note:** Tasks can only be created/edited via the web interface. The CLI allows management and execution only.ve tasks rm <task-id> -f # Force delete
150
171
  ```
151
172
 
152
173
  ### Info & Status
153
174
 
154
175
  ```bash
155
176
  # Show connection status and user info
156
- d-drive info
177
+ drive info
157
178
  ```
158
179
 
159
180
  Output:
@@ -171,9 +192,9 @@ User: YourUsername
171
192
 
172
193
  ```bash
173
194
  # Start interactive mode
174
- d-drive interactive
195
+ drive interactive
175
196
  # or
176
- d-drive i
197
+ drive i
177
198
  ```
178
199
 
179
200
  Interactive mode provides a menu-driven interface for all operations.
@@ -185,47 +206,225 @@ Interactive mode provides a menu-driven interface for all operations.
185
206
  3. Scroll to **API Keys** section
186
207
  4. Click **Create API Key**
187
208
  5. Copy the key (starts with `dd_`)
188
- 6. Use in CLI: `d-drive config --key dd_your_key`
209
+ 6. Use in CLI: `drive config --key dd_your_key`
189
210
 
190
211
  ## Examples
191
212
 
192
213
  ### Backup a Project
193
214
 
194
215
  ```bash
195
- # Create a backup of your project
196
- d-drive upload ./my-project /backups/my-project/ -r
216
+ # Create an encrypted backup of your project
217
+ drive upload ./my-project /backups/my-project/ -r
197
218
 
198
- # List backups
199
- d-drive ls /backups/my-project -l
219
+ # List backups with details
220
+ drive ls /backups/my-project -l
200
221
  ```
201
222
 
202
223
  ### Automated Backup Script
203
224
 
204
225
  ```bash
205
226
  #!/bin/bash
206
- # backup.sh
227
+ # backup.sh - Daily project backup
207
228
 
208
229
  DATE=$(date +%Y-%m-%d)
209
- d-drive upload ./data "/backups/$DATE/"
210
- echo "Backup completed: $DATE"
230
+ PROJECT_NAME="my-app"
231
+
232
+ echo "Starting backup for $PROJECT_NAME on $DATE..."
233
+
234
+ # Upload with automatic encryption
235
+ drive upload ./ "/backups/$PROJECT_NAME/$DATE/" -r
236
+
237
+ if [ $? -eq 0 ]; then
238
+ echo "✓ Backup completed successfully: $DATE"
239
+
240
+ # List to verify
241
+ drive ls "/backups/$PROJECT_NAME/" -l
242
+ else
243
+ echo "✗ Backup failed!"
244
+ exit 1
245
+ fi
246
+ ```configure the CLI using environment variables instead of `drive config`:
247
+
248
+ ```bash
249
+ # Set in your shell profile (~/.bashrc, ~/.zshrc, etc.)
250
+ export DDRIVE_API_KEY=dd_your_api_key_here
251
+ export DDRIVE_API_URL=https://your-server/api
252
+
253
+ # Or use inline for single commands
254
+ DDRIVE_API_KEY=dd_key123 drive ls /
211
255
  ```
212
256
 
213
- ### Download and Restore
257
+ **Variables:**
258
+ - `DDRIVE_API_KEY` - Your D-Drive API key (starts with `dd_`)
259
+ - `DDRIVE_API_URL` - API base URL (default: `https://localhost/api`)
260
+
261
+ **Priority:**
262
+ 1. Environment variables (highest)
263
+ 2. Config file (`~/.ddrive-cli-config`)
264
+ 3. Default values (lowest)
214
265
 
266
+ **View current configuration:**
215
267
  ```bash
268
+ drive config --list
269
+ # List available backups
270
+ drive ls /backups/ -l
271
+
216
272
  # Download latest backup
217
- d-drive download /backups/2026-01-24/data.tar.gz ./restore/
273
+ drive download /backups/2026-01-24/data.tar.gz ./restore/
218
274
 
219
275
  # Extract
220
- tar -xzf ./restore/data.tar.gz
276
+ tar -xzf ./restore/data.tar.gz -C ./restore/
277
+
278
+ echo "Restore complete!"
279
+ ```
280
+
281
+ ### Monitor Task Status
282
+
283
+ ```bash
284
+ #!/bin/bash
285
+ # check-tasks.sh - Monitor backup task status
286
+
287
+ echo "Checking SFTP backup tasks..."
288
+ drive tasks ls
289
+
290
+ # Run a specific task
291
+ TASK_ID="clmxyz123..."
292
+ echo "Running task $TASK_ID..."
293
+ drive tasks run $TASK_ID
294
+ **Causes:**
295
+ - Server is not running
296
+ - Incorrect API URL
297
+ - Network/firewall issues
298
+ - SSL/TLS certificate problems
299
+
300
+ **Solutions:**
301
+ ```bash
302
+ # Check your configuration
303
+ drive config --list
304
+
305
+ # Test with correct URL (include /api path)
306
+ drive config --url https://your-server/api
307
+
308
+ # Verify server is accessible
309
+ curl https://your-server/api/setup/status
310
+
311
+ # For local development with self-signed certs
312
+ export NODE_TLS_REJECT_UNAUTHORIZED=0 # Not recommended for production!
313
+ ```
314
+
315
+ ### "Invalid API key"
316
+ **Causes:**
317
+ - API key is incorrect or expired
318
+ - Missing `dd_` prefix
319
+ - Extra spaces or characters
320
+
321
+ **Solutions:**
322
+ ```bash
323
+ # Generate a new API key:
324
+ # 1. Open D-Drive web interface
325
+ # 2. Go to Settings → API Keys
326
+ # 3. Click "Create API Key"
327
+ # 4. Copy the full key (including dd_ prefix)
328
+
329
+ # Configure with new key
330
+ drive config --key dd_your_new_key_here
331
+
332
+ # Verify it works
333
+ drive info
334
+ ```
335
+
336
+ ### "Permission denied"
337
+ **Causes:**
338
+ - Using wrong account/API key
339
+ - File/folder doesn't belong to you
340
+ - Insufficient permissions
341
+
342
+ **Solutions:**
343
+ ```bash
344
+ # Check which user you're authenticated as
345
+ drive info
346
+
347
+ # Ensure you're using the correct API key
348
+ drive config --list
221
349
  ```
222
350
 
223
- ## Environment Variables
351
+ ### "File not found" when listing nested folders
352
+ **Causes:**
353
+ - Folder path typo
354
+ - Folder doesn't exist
355
+ - Path should start with /
356
+
357
+ **Solutions:**
358
+ ```bash
359
+ # List root to see available folders
360
+ drive ls /
361
+
362
+ # Use absolute paths
363
+ drive ls /backups/subfolder
364
+
365
+ # Use long format to see full paths
366
+ drive ls / -l
367
+ ```
368
+
369
+ ### Upload/Download Progress Not Showing
370
+ **Causes:**
371
+ - File is too small (progress skipped)
372
+ - Terminal doesn't support progress bars
373
+
374
+ **Solutions:**
375
+ - Progress bars automatically appear for larger files
376
+ - Check that your terminal supports ANSI escape codes
377
+ - Try in a different terminal (iTerm2, gnome-terminal, etc.)
224
378
 
225
- You can also configure the CLI using environment variables:
379
+ ### Task Won't Run
380
+ **Causes:**
381
+ - Task is disabled
382
+ - Another task instance is already running
383
+ - SFTP credentials are invalid
384
+ - Network connectivity issues
226
385
 
386
+ **Solutions:**
227
387
  ```bash
228
- export DDRIVE_API_KEY=dd_your_api_key
388
+ # Check task status
389
+ drive tasks ls
390
+
391
+ # Enable if disabled
392
+ drive tasks enable <task-id>
393
+
394
+ # If shows "Running" but stuck, stop and restart
395
+ drive tasks stop <task-id>
396
+ drive tasks run <task-id>
397
+
398
+ # Check server logs for detailed errors
399
+ ```
400
+
401
+ ### npm Installation Issues
402
+ **MacOS/Linux:**
403
+ ```bash
404
+ # Permission errors - use one of these methods:
405
+
406
+ # Method 1: Install globally with correct permissions
407
+ sudo npm install -g d-drive-cli
408
+
409
+ # Method 2: Use npx (no installation needed)
410
+ npx d-drive-cli ls /
411
+
412
+ # Method 3: Configure npm to use different directory
413
+ mkdir ~/.npm-global
414
+ npm config set prefix '~/.npm-global'
415
+ echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc
416
+ source ~/.bashrc
417
+ npm install -g d-drive-cli
418
+ ```
419
+
420
+ **Windows:**
421
+ ```powershell
422
+ # Run PowerShell as Administrator
423
+ npm install -g d-drive-cli
424
+
425
+ # Or use npx
426
+ npx d-drive-cli ls /
427
+ ```
229
428
  export DDRIVE_API_URL=https://your-server/api
230
429
  ```
231
430
 
@@ -247,14 +446,26 @@ export DDRIVE_API_URL=https://your-server/api
247
446
 
248
447
  ## Changelog
249
448
 
250
- ### v2.2.1
251
- - Fixed double output issue by removing `drive` alias
252
- - Use `d-drive` as the single command name
253
- - Improved consistency across documentation
449
+ ### v2.2.3
450
+ - **Bug fixes:**
451
+ - Fixed nested folder path resolution in `list` command
452
+ - Improved API key validation (now uses `/auth/me` endpoint)
453
+ - Added directory deletion warning message
454
+ - Better error messages for directory download attempts
455
+ - **Documentation:** Enhanced CLI README and API docs
456
+
457
+ ### v2.2.2
458
+ - **ACTUALLY** fixed double output issue (previous v2.2.1 had wrong fix)
459
+ - Added `process.exit(0)` after help display to prevent Commander.js duplicate
460
+ - Both `d-drive` and `drive` aliases work correctly
461
+
462
+ ### v2.2.1 (deprecated)
463
+ - Incorrectly removed `drive` alias thinking it caused double output
254
464
 
255
465
  ### v2.2.0
466
+ - Added `drive` command alias for easier use
256
467
  - Interactive mode with menu-driven interface
257
- - `info` command for connection status
468
+ - `drive info` command for connection status
258
469
  - Interactive configuration wizard
259
470
  - Better error messages
260
471
  - Colorized output
@@ -26,8 +26,8 @@ async function configCommand(options) {
26
26
  // Accept keys entered with or without the `dd_` prefix, and strip any accidental "Bearer " prefix
27
27
  const rawKey = options.key.replace(/^Bearer\s+/i, '').trim();
28
28
  const normalizedKey = rawKey.startsWith('dd_') ? rawKey : `dd_${rawKey}`;
29
- // Validate API key by calling a protected endpoint that accepts API keys (authenticate middleware)
30
- const validateUrl = apiUrl.replace(/\/$/, '') + '/api-keys';
29
+ // Validate API key by calling /auth/me endpoint (simpler and more reliable)
30
+ const validateUrl = apiUrl.replace(/\/$/, '') + '/auth/me';
31
31
  const response = await axios_1.default.get(validateUrl, {
32
32
  headers: {
33
33
  Authorization: `Bearer ${normalizedKey}`,
@@ -23,6 +23,10 @@ async function deleteCommand(remotePath, options) {
23
23
  }
24
24
  const file = files[0];
25
25
  spinner.stop();
26
+ // Warn if trying to delete a directory
27
+ if (file.type === 'DIRECTORY') {
28
+ console.log(chalk_1.default.yellow('Warning: This is a directory. All contents will be moved to recycle bin.'));
29
+ }
26
30
  // Confirm deletion
27
31
  if (!options.force) {
28
32
  const answers = await inquirer_1.default.prompt([
@@ -26,6 +26,8 @@ async function downloadCommand(source, destination = './', options) {
26
26
  const file = files[0];
27
27
  if (file.type === 'DIRECTORY') {
28
28
  spinner.fail(chalk_1.default.red('Cannot download directories yet'));
29
+ console.log(chalk_1.default.gray('Tip: Download individual files from the directory instead.'));
30
+ console.log(chalk_1.default.gray('Use: drive ls ' + source + ' -l'));
29
31
  return;
30
32
  }
31
33
  spinner.text = 'Downloading...';
@@ -61,13 +61,22 @@ async function listCommand(remotePath = '/', options) {
61
61
  }
62
62
  }
63
63
  function findFolderByPath(files, targetPath) {
64
- // Simple path matching - looks for folder by name in the path
65
- const pathParts = targetPath.split('/').filter(p => p);
64
+ // Build full path for each file and match against target
65
+ const normalizedTarget = targetPath.startsWith('/') ? targetPath : '/' + targetPath;
66
66
  for (const file of files) {
67
- if (file.type === 'DIRECTORY' && file.name === pathParts[0]) {
67
+ if (file.type === 'DIRECTORY' && file.path === normalizedTarget) {
68
68
  return file;
69
69
  }
70
70
  }
71
+ // Fallback: try matching by name only (for root-level folders)
72
+ const pathParts = targetPath.split('/').filter(p => p);
73
+ if (pathParts.length === 1) {
74
+ for (const file of files) {
75
+ if (file.type === 'DIRECTORY' && file.name === pathParts[0]) {
76
+ return file;
77
+ }
78
+ }
79
+ }
71
80
  return null;
72
81
  }
73
82
  function formatFileSize(bytes) {
package/dist/index.js CHANGED
@@ -20,8 +20,8 @@ const program = new commander_1.Command();
20
20
  // ASCII art banner
21
21
  const banner = `
22
22
  ${chalk_1.default.cyan('╔═══════════════════════════════════════╗')}
23
- ${chalk_1.default.cyan('║')} ${chalk_1.default.bold.white('D-Drive CLI')} ${chalk_1.default.gray('v' + (pkg.version || '2.2.0'))} ${chalk_1.default.cyan('║')}
24
- ${chalk_1.default.cyan('║')} ${chalk_1.default.gray('Discord-based cloud storage')} ${chalk_1.default.cyan('║')}
23
+ ${chalk_1.default.cyan('║')} ${chalk_1.default.bold.white('D-Drive CLI')} ${chalk_1.default.gray('v' + (pkg.version || '2.2.0'))} ${chalk_1.default.cyan(' ║')}
24
+ ${chalk_1.default.cyan('║')} ${chalk_1.default.gray('Discord-based cloud storage')} ${chalk_1.default.cyan(' ║')}
25
25
  ${chalk_1.default.cyan('╚═══════════════════════════════════════╝')}
26
26
  `;
27
27
  program
@@ -292,5 +292,6 @@ async function interactiveConfig() {
292
292
  if (process.argv.length === 2 && !process.argv.includes('-v') && !process.argv.includes('--version') && !process.argv.includes('-h') && !process.argv.includes('--help')) {
293
293
  console.log(banner);
294
294
  program.outputHelp();
295
+ process.exit(0);
295
296
  }
296
297
  program.parse();
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "d-drive-cli",
3
- "version": "2.2.1",
3
+ "version": "2.2.3",
4
4
  "description": "D-Drive CLI tool for developers - Discord cloud storage",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
- "d-drive": "./dist/index.js"
7
+ "d-drive": "./dist/index.js",
8
+ "drive": "./dist/index.js"
8
9
  },
9
10
  "scripts": {
10
11
  "build": "tsc",
@@ -20,23 +21,23 @@
20
21
  "author": "jasonzli-DEV",
21
22
  "license": "MIT",
22
23
  "dependencies": {
23
- "commander": "^11.1.0",
24
24
  "axios": "^1.6.5",
25
25
  "chalk": "^4.1.2",
26
- "ora": "^5.4.1",
26
+ "commander": "^11.1.0",
27
27
  "conf": "^10.2.0",
28
- "inquirer": "^8.2.6",
29
28
  "form-data": "^4.0.0",
30
29
  "fs-extra": "^11.2.0",
31
30
  "glob": "^10.3.10",
31
+ "inquirer": "^8.2.6",
32
+ "ora": "^5.4.1",
32
33
  "progress": "^2.0.3"
33
34
  },
34
35
  "devDependencies": {
35
- "@types/node": "^20.10.7",
36
- "@types/inquirer": "^8.2.10",
37
36
  "@types/fs-extra": "^11.0.4",
37
+ "@types/inquirer": "^8.2.10",
38
+ "@types/node": "^20.10.7",
38
39
  "@types/progress": "^2.0.7",
39
- "typescript": "^5.3.3",
40
- "ts-node": "^10.9.2"
40
+ "ts-node": "^10.9.2",
41
+ "typescript": "^5.9.3"
41
42
  }
42
43
  }
@@ -31,8 +31,8 @@ export async function configCommand(options: ConfigOptions) {
31
31
  const rawKey = options.key.replace(/^Bearer\s+/i, '').trim();
32
32
  const normalizedKey = rawKey.startsWith('dd_') ? rawKey : `dd_${rawKey}`;
33
33
 
34
- // Validate API key by calling a protected endpoint that accepts API keys (authenticate middleware)
35
- const validateUrl = apiUrl.replace(/\/$/, '') + '/api-keys';
34
+ // Validate API key by calling /auth/me endpoint (simpler and more reliable)
35
+ const validateUrl = apiUrl.replace(/\/$/, '') + '/auth/me';
36
36
  const response = await axios.get(validateUrl, {
37
37
  headers: {
38
38
  Authorization: `Bearer ${normalizedKey}`,
@@ -28,6 +28,11 @@ export async function deleteCommand(remotePath: string, options: DeleteOptions)
28
28
  const file = files[0];
29
29
  spinner.stop();
30
30
 
31
+ // Warn if trying to delete a directory
32
+ if (file.type === 'DIRECTORY') {
33
+ console.log(chalk.yellow('Warning: This is a directory. All contents will be moved to recycle bin.'));
34
+ }
35
+
31
36
  // Confirm deletion
32
37
  if (!options.force) {
33
38
  const answers = await inquirer.prompt([
@@ -34,6 +34,8 @@ export async function downloadCommand(
34
34
 
35
35
  if (file.type === 'DIRECTORY') {
36
36
  spinner.fail(chalk.red('Cannot download directories yet'));
37
+ console.log(chalk.gray('Tip: Download individual files from the directory instead.'));
38
+ console.log(chalk.gray('Use: drive ls ' + source + ' -l'));
37
39
  return;
38
40
  }
39
41
 
@@ -71,14 +71,25 @@ export async function listCommand(remotePath: string = '/', options: ListOptions
71
71
  }
72
72
 
73
73
  function findFolderByPath(files: any[], targetPath: string): any | null {
74
- // Simple path matching - looks for folder by name in the path
75
- const pathParts = targetPath.split('/').filter(p => p);
74
+ // Build full path for each file and match against target
75
+ const normalizedTarget = targetPath.startsWith('/') ? targetPath : '/' + targetPath;
76
76
 
77
77
  for (const file of files) {
78
- if (file.type === 'DIRECTORY' && file.name === pathParts[0]) {
78
+ if (file.type === 'DIRECTORY' && file.path === normalizedTarget) {
79
79
  return file;
80
80
  }
81
81
  }
82
+
83
+ // Fallback: try matching by name only (for root-level folders)
84
+ const pathParts = targetPath.split('/').filter(p => p);
85
+ if (pathParts.length === 1) {
86
+ for (const file of files) {
87
+ if (file.type === 'DIRECTORY' && file.name === pathParts[0]) {
88
+ return file;
89
+ }
90
+ }
91
+ }
92
+
82
93
  return null;
83
94
  }
84
95
 
package/src/index.ts CHANGED
@@ -18,8 +18,8 @@ const program = new Command();
18
18
  // ASCII art banner
19
19
  const banner = `
20
20
  ${chalk.cyan('╔═══════════════════════════════════════╗')}
21
- ${chalk.cyan('║')} ${chalk.bold.white('D-Drive CLI')} ${chalk.gray('v' + (pkg.version || '2.2.0'))} ${chalk.cyan('║')}
22
- ${chalk.cyan('║')} ${chalk.gray('Discord-based cloud storage')} ${chalk.cyan('║')}
21
+ ${chalk.cyan('║')} ${chalk.bold.white('D-Drive CLI')} ${chalk.gray('v' + (pkg.version || '2.2.0'))} ${chalk.cyan(' ║')}
22
+ ${chalk.cyan('║')} ${chalk.gray('Discord-based cloud storage')} ${chalk.cyan(' ║')}
23
23
  ${chalk.cyan('╚═══════════════════════════════════════╝')}
24
24
  `;
25
25
 
@@ -314,6 +314,7 @@ async function interactiveConfig() {
314
314
  if (process.argv.length === 2 && !process.argv.includes('-v') && !process.argv.includes('--version') && !process.argv.includes('-h') && !process.argv.includes('--help')) {
315
315
  console.log(banner);
316
316
  program.outputHelp();
317
+ process.exit(0);
317
318
  }
318
319
 
319
320
  program.parse();