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 +282 -71
- package/dist/commands/config.js +2 -2
- package/dist/commands/delete.js +4 -0
- package/dist/commands/download.js +2 -0
- package/dist/commands/list.js +12 -3
- package/dist/index.js +3 -2
- package/package.json +10 -9
- package/src/commands/config.ts +2 -2
- package/src/commands/delete.ts +5 -0
- package/src/commands/download.ts +2 -0
- package/src/commands/list.ts +14 -3
- package/src/index.ts +3 -2
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# D-Drive CLI v2.2.
|
|
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.
|
|
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
|
|
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
|
-
|
|
30
|
+
drive config
|
|
29
31
|
|
|
30
32
|
# Or set API key directly
|
|
31
|
-
|
|
33
|
+
drive config --key YOUR_API_KEY --url https://your-server/api
|
|
32
34
|
|
|
33
35
|
# Check connection
|
|
34
|
-
|
|
36
|
+
drive info
|
|
35
37
|
|
|
36
38
|
# Upload a file
|
|
37
|
-
|
|
39
|
+
drive upload ./backup.zip
|
|
38
40
|
|
|
39
41
|
# List files
|
|
40
|
-
|
|
42
|
+
drive ls
|
|
41
43
|
|
|
42
44
|
# Download a file
|
|
43
|
-
|
|
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
|
-
|
|
54
|
+
drive config
|
|
53
55
|
|
|
54
56
|
# Set API key
|
|
55
|
-
|
|
57
|
+
drive config --key dd_your_api_key
|
|
56
58
|
|
|
57
59
|
# Set API URL
|
|
58
|
-
|
|
60
|
+
drive config --url https://your-server/api
|
|
59
61
|
|
|
60
62
|
# View current config
|
|
61
|
-
|
|
63
|
+
drive config --list
|
|
62
64
|
# or
|
|
63
|
-
|
|
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
|
-
|
|
73
|
+
# Upload single file (encrypted by default)
|
|
74
|
+
drive upload ./file.txt
|
|
73
75
|
|
|
74
76
|
# Upload to specific folder
|
|
75
|
-
|
|
77
|
+
drive upload ./file.txt /backups/
|
|
76
78
|
|
|
77
79
|
# Upload directory recursively
|
|
78
|
-
|
|
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
|
-
|
|
88
|
+
# Download file (automatically decrypted)
|
|
89
|
+
drive download /backups/file.txt
|
|
89
90
|
|
|
90
91
|
# Download to specific location
|
|
91
|
-
|
|
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
|
-
|
|
101
|
+
drive ls
|
|
99
102
|
|
|
100
103
|
# List specific directory
|
|
101
|
-
|
|
104
|
+
drive ls /backups
|
|
102
105
|
|
|
103
106
|
# Long format with details
|
|
104
|
-
|
|
105
|
-
|
|
107
|
+
drive ls -l
|
|
108
|
+
drive ls /backups -l
|
|
106
109
|
```
|
|
107
110
|
|
|
108
111
|
#### Delete
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
|
|
116
|
+
drive rm /old-file.txt -f
|
|
117
|
+
```
|
|
116
118
|
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
|
|
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
|
-
|
|
135
|
+
# List all tasks with status
|
|
136
|
+
drive tasks ls
|
|
136
137
|
|
|
137
|
-
# Run a task immediately
|
|
138
|
-
|
|
138
|
+
# Run a task immediately (ignores schedule)
|
|
139
|
+
drive tasks run <task-id>
|
|
139
140
|
|
|
140
141
|
# Stop a running task
|
|
141
|
-
|
|
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
|
-
#
|
|
144
|
-
|
|
145
|
-
d-drive tasks disable <task-id>
|
|
150
|
+
# Delete a task (with confirmation)
|
|
151
|
+
drive tasks rm <task-id>
|
|
146
152
|
|
|
147
|
-
#
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
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
|
-
|
|
195
|
+
drive interactive
|
|
175
196
|
# or
|
|
176
|
-
|
|
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: `
|
|
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
|
|
196
|
-
|
|
216
|
+
# Create an encrypted backup of your project
|
|
217
|
+
drive upload ./my-project /backups/my-project/ -r
|
|
197
218
|
|
|
198
|
-
# List backups
|
|
199
|
-
|
|
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
|
-
|
|
210
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
251
|
-
-
|
|
252
|
-
-
|
|
253
|
-
- Improved
|
|
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
|
package/dist/commands/config.js
CHANGED
|
@@ -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
|
|
30
|
-
const validateUrl = apiUrl.replace(/\/$/, '') + '/
|
|
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}`,
|
package/dist/commands/delete.js
CHANGED
|
@@ -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...';
|
package/dist/commands/list.js
CHANGED
|
@@ -61,13 +61,22 @@ async function listCommand(remotePath = '/', options) {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
function findFolderByPath(files, targetPath) {
|
|
64
|
-
//
|
|
65
|
-
const
|
|
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.
|
|
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.
|
|
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
|
-
"
|
|
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
|
-
"
|
|
40
|
-
"
|
|
40
|
+
"ts-node": "^10.9.2",
|
|
41
|
+
"typescript": "^5.9.3"
|
|
41
42
|
}
|
|
42
43
|
}
|
package/src/commands/config.ts
CHANGED
|
@@ -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
|
|
35
|
-
const validateUrl = apiUrl.replace(/\/$/, '') + '/
|
|
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}`,
|
package/src/commands/delete.ts
CHANGED
|
@@ -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([
|
package/src/commands/download.ts
CHANGED
|
@@ -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
|
|
package/src/commands/list.ts
CHANGED
|
@@ -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
|
-
//
|
|
75
|
-
const
|
|
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.
|
|
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();
|