@zoobbe/cli 1.1.1 → 1.2.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.
@@ -255,6 +255,78 @@ card
255
255
  }
256
256
  });
257
257
 
258
+ card
259
+ .command('label <cardId>')
260
+ .description('Add or remove a label on a card')
261
+ .option('-b, --board <boardId>', 'Board ID (auto-detected from card if not specified)')
262
+ .option('-r, --remove', 'Remove the label instead of adding it')
263
+ .action(async (cardId, options) => {
264
+ try {
265
+ // Fetch card to get board info
266
+ const cardData = await withSpinner('Fetching card...', () =>
267
+ client.get(`/cards/${cardId}`)
268
+ );
269
+ const c = cardData.card || cardData.data || cardData;
270
+ const boardId = options.board || c.boardShortId || c.board;
271
+
272
+ if (!boardId) {
273
+ return error('Could not determine board. Use -b <boardId>.');
274
+ }
275
+
276
+ // Get available labels from the board
277
+ const labelsData = await client.get(`/boards/${boardId}/labels`);
278
+ const labels = labelsData.labels || labelsData.data || labelsData;
279
+ const labelArr = Array.isArray(labels) ? labels : [];
280
+
281
+ if (labelArr.length === 0) {
282
+ return error('No labels found on this board.');
283
+ }
284
+
285
+ // Get current card labels
286
+ const cardLabelsData = await client.get(`/cards/${cardId}/labels`);
287
+ const cardLabels = cardLabelsData.labels || cardLabelsData.data || [];
288
+ const cardLabelIds = new Set(cardLabels.map(l => l._id));
289
+
290
+ // Show available labels with status
291
+ console.log();
292
+ console.log(chalk.bold(' Available labels:'));
293
+ labelArr.forEach((l, i) => {
294
+ const active = cardLabelIds.has(l._id) ? chalk.green(' [active]') : '';
295
+ const name = l.text || l.color || 'Unnamed';
296
+ console.log(` ${i + 1}. ${name}${active}`);
297
+ });
298
+ console.log();
299
+
300
+ // Prompt user to pick a label
301
+ const inquirer = require('inquirer');
302
+ const { labelIndex } = await inquirer.prompt([{
303
+ type: 'input',
304
+ name: 'labelIndex',
305
+ message: options.remove ? 'Label # to remove:' : 'Label # to add:',
306
+ validate: v => {
307
+ const n = parseInt(v);
308
+ return (n >= 1 && n <= labelArr.length) ? true : `Enter 1-${labelArr.length}`;
309
+ },
310
+ }]);
311
+
312
+ const label = labelArr[parseInt(labelIndex) - 1];
313
+
314
+ if (options.remove) {
315
+ await withSpinner('Removing label...', () =>
316
+ client.delete(`/cards/${cardId}/labels/${label._id}`)
317
+ );
318
+ success(`Removed label "${label.text || label.color}" from card ${cardId}`);
319
+ } else {
320
+ await withSpinner('Adding label...', () =>
321
+ client.put(`/cards/${cardId}/labels/${label._id}`, { boardId })
322
+ );
323
+ success(`Added label "${label.text || label.color}" to card ${cardId}`);
324
+ }
325
+ } catch (err) {
326
+ error(`Failed to update label: ${err.message}`);
327
+ }
328
+ });
329
+
258
330
  card
259
331
  .command('done <cardId>')
260
332
  .description('Mark a card as complete')
@@ -299,4 +371,299 @@ card
299
371
  }
300
372
  });
301
373
 
374
+ // ── Extended commands ──
375
+
376
+ const { confirmAction } = require('../utils/prompts');
377
+ const { formatRelativeTime } = require('../utils/format');
378
+
379
+ card
380
+ .command('update <cardId>')
381
+ .description('Update card title or description')
382
+ .option('-t, --title <title>', 'New title')
383
+ .option('-d, --description <desc>', 'New description')
384
+ .action(async (cardId, options) => {
385
+ try {
386
+ const body = {};
387
+ if (options.title) body.title = options.title;
388
+ if (options.description) body.description = options.description;
389
+ if (Object.keys(body).length === 0) return error('Provide -t or -d.');
390
+
391
+ await withSpinner('Updating card...', () =>
392
+ client.post(`/cards/update/${cardId}`, body)
393
+ );
394
+ success(`Updated card ${cardId}`);
395
+ } catch (err) {
396
+ error(`Failed to update card: ${err.message}`);
397
+ }
398
+ });
399
+
400
+ card
401
+ .command('archive <cardId>')
402
+ .description('Archive a card')
403
+ .action(async (cardId) => {
404
+ try {
405
+ await withSpinner('Archiving card...', () =>
406
+ client.post(`/cards/archive/${cardId}`)
407
+ );
408
+ success(`Archived card ${cardId}`);
409
+ } catch (err) {
410
+ error(`Failed to archive card: ${err.message}`);
411
+ }
412
+ });
413
+
414
+ card
415
+ .command('delete <cardId>')
416
+ .description('Permanently delete a card')
417
+ .option('--force', 'Skip confirmation')
418
+ .action(async (cardId, options) => {
419
+ try {
420
+ if (!options.force) {
421
+ const confirmed = await confirmAction('Permanently delete this card and all its data?');
422
+ if (!confirmed) return;
423
+ }
424
+
425
+ await withSpinner('Deleting card...', () =>
426
+ client.post(`/cards/delete/${cardId}`)
427
+ );
428
+ success(`Deleted card ${cardId}`);
429
+ } catch (err) {
430
+ error(`Failed to delete card: ${err.message}`);
431
+ }
432
+ });
433
+
434
+ card
435
+ .command('copy <cardId>')
436
+ .description('Copy a card')
437
+ .option('-l, --list <listId>', 'Target list ID (copies to same list if omitted)')
438
+ .action(async (cardId, options) => {
439
+ try {
440
+ const body = {};
441
+ if (options.list) body.targetListId = options.list;
442
+
443
+ const data = await withSpinner('Copying card...', () =>
444
+ client.post(`/cards/${cardId}/copy`, body)
445
+ );
446
+ const c = data.card || data.data || data;
447
+ success(`Copied card to: ${chalk.bold(c.title || 'Copy')} (${c.shortId || c._id})`);
448
+ } catch (err) {
449
+ error(`Failed to copy card: ${err.message}`);
450
+ }
451
+ });
452
+
453
+ card
454
+ .command('unassign <cardId>')
455
+ .description('Remove a user from a card')
456
+ .option('-u, --user <userId>', 'User ID to remove (required)')
457
+ .action(async (cardId, options) => {
458
+ try {
459
+ if (!options.user) return error('User ID is required. Use -u <userId>.');
460
+
461
+ await withSpinner('Removing member...', () =>
462
+ client.post(`/cards/${cardId}/removeMember`, { memberId: options.user })
463
+ );
464
+ success(`Removed user from card ${cardId}`);
465
+ } catch (err) {
466
+ error(`Failed to unassign card: ${err.message}`);
467
+ }
468
+ });
469
+
470
+ card
471
+ .command('members <cardId>')
472
+ .description('List members assigned to a card')
473
+ .option('-f, --format <format>', 'Output format')
474
+ .action(async (cardId, options) => {
475
+ try {
476
+ const data = await withSpinner('Fetching members...', () =>
477
+ client.get(`/cards/${cardId}/members`)
478
+ );
479
+
480
+ const members = data.members || data.data || data;
481
+ const rows = (Array.isArray(members) ? members : []).map(m => {
482
+ const user = m.user || m;
483
+ return {
484
+ name: user.userName || user.username || user.name || 'N/A',
485
+ email: user.email || 'N/A',
486
+ id: user._id || user.id || '',
487
+ };
488
+ });
489
+
490
+ output(rows, {
491
+ headers: ['Name', 'Email', 'ID'],
492
+ format: options.format,
493
+ });
494
+ } catch (err) {
495
+ error(`Failed to list members: ${err.message}`);
496
+ }
497
+ });
498
+
499
+ card
500
+ .command('comments <cardId>')
501
+ .description('List comments on a card')
502
+ .option('-f, --format <format>', 'Output format')
503
+ .action(async (cardId, options) => {
504
+ try {
505
+ const data = await withSpinner('Fetching comments...', () =>
506
+ client.get(`/cards/${cardId}/comments`)
507
+ );
508
+
509
+ const comments = data.comments || data.data || data;
510
+ const rows = (Array.isArray(comments) ? comments : []).map(c => ({
511
+ user: c.member?.userName || c.user?.userName || 'N/A',
512
+ comment: (c.comment || '').substring(0, 80),
513
+ time: formatRelativeTime(c.createdAt),
514
+ id: c._id,
515
+ }));
516
+
517
+ output(rows, {
518
+ headers: ['User', 'Comment', 'Time', 'ID'],
519
+ format: options.format,
520
+ });
521
+ } catch (err) {
522
+ error(`Failed to list comments: ${err.message}`);
523
+ }
524
+ });
525
+
526
+ card
527
+ .command('watch <cardId>')
528
+ .description('Toggle watch on a card')
529
+ .option('--unwatch', 'Unwatch the card')
530
+ .action(async (cardId, options) => {
531
+ try {
532
+ const data = await withSpinner(options.unwatch ? 'Unwatching...' : 'Watching...', () =>
533
+ client.post(`/cards/${cardId}/watch`)
534
+ );
535
+ success(data.message || 'Watch toggled');
536
+ } catch (err) {
537
+ error(`Failed to toggle watch: ${err.message}`);
538
+ }
539
+ });
540
+
541
+ card
542
+ .command('attachments <cardId>')
543
+ .description('List attachments on a card')
544
+ .option('-f, --format <format>', 'Output format')
545
+ .action(async (cardId, options) => {
546
+ try {
547
+ const data = await withSpinner('Fetching attachments...', () =>
548
+ client.get(`/cards/attachments/${cardId}`)
549
+ );
550
+
551
+ const attachments = data.attachments || data.data || data;
552
+ const rows = (Array.isArray(attachments) ? attachments : []).map(a => ({
553
+ name: a.name || a.filename || 'N/A',
554
+ type: a.type || a.mimetype || '-',
555
+ size: a.size ? `${Math.round(a.size / 1024)}KB` : '-',
556
+ id: a._id,
557
+ }));
558
+
559
+ output(rows, {
560
+ headers: ['Name', 'Type', 'Size', 'ID'],
561
+ format: options.format,
562
+ });
563
+ } catch (err) {
564
+ error(`Failed to list attachments: ${err.message}`);
565
+ }
566
+ });
567
+
568
+ card
569
+ .command('attach <cardId> <filePath>')
570
+ .description('Upload an attachment to a card')
571
+ .action(async (cardId, filePath) => {
572
+ try {
573
+ const fs = require('fs');
574
+ if (!fs.existsSync(filePath)) {
575
+ return error(`File not found: ${filePath}`);
576
+ }
577
+
578
+ const data = await withSpinner('Uploading attachment...', () =>
579
+ client.upload(`/cards/attachments/${cardId}`, filePath)
580
+ );
581
+ const a = data.attachment || data.data || data;
582
+ success(`Uploaded: ${chalk.bold(a.name || a.filename || filePath)}`);
583
+ } catch (err) {
584
+ error(`Failed to upload attachment: ${err.message}`);
585
+ }
586
+ });
587
+
588
+ card
589
+ .command('activities <cardId>')
590
+ .description('Show card activity log')
591
+ .option('--limit <n>', 'Number of activities', '20')
592
+ .option('-f, --format <format>', 'Output format')
593
+ .action(async (cardId, options) => {
594
+ try {
595
+ const data = await withSpinner('Fetching activities...', () =>
596
+ client.get(`/cards/${cardId}/activities`)
597
+ );
598
+
599
+ const activities = data.activities || data.data || data;
600
+ const actArr = Array.isArray(activities) ? activities : [];
601
+ const limited = actArr.slice(0, parseInt(options.limit));
602
+
603
+ const rows = limited.map(a => ({
604
+ action: a.action || a.type || 'unknown',
605
+ user: a.user?.userName || a.user?.name || 'N/A',
606
+ detail: (a.detail || a.description || '').substring(0, 60),
607
+ time: formatRelativeTime(a.createdAt),
608
+ }));
609
+
610
+ output(rows, {
611
+ headers: ['Action', 'User', 'Detail', 'Time'],
612
+ format: options.format,
613
+ });
614
+ } catch (err) {
615
+ error(`Failed to fetch activities: ${err.message}`);
616
+ }
617
+ });
618
+
619
+ card
620
+ .command('due <cardId> <date>')
621
+ .description('Set or remove a due date on a card')
622
+ .option('--remove', 'Remove the due date')
623
+ .action(async (cardId, date, options) => {
624
+ try {
625
+ if (options.remove) {
626
+ await withSpinner('Removing due date...', () =>
627
+ client.delete(`/cards/${cardId}/duedate`)
628
+ );
629
+ success(`Removed due date from card ${cardId}`);
630
+ } else {
631
+ await withSpinner('Setting due date...', () =>
632
+ client.post(`/cards/${cardId}/duedate`, { dueDate: date })
633
+ );
634
+ success(`Set due date to ${chalk.bold(date)} on card ${cardId}`);
635
+ }
636
+ } catch (err) {
637
+ error(`Failed to update due date: ${err.message}`);
638
+ }
639
+ });
640
+
641
+ card
642
+ .command('priority <cardId> <level>')
643
+ .description('Set card priority (low|medium|high|critical)')
644
+ .action(async (cardId, level) => {
645
+ try {
646
+ await withSpinner('Setting priority...', () =>
647
+ client.post(`/cards/${cardId}/priority`, { priority: level })
648
+ );
649
+ success(`Set priority to ${chalk.bold(level)} on card ${cardId}`);
650
+ } catch (err) {
651
+ error(`Failed to set priority: ${err.message}`);
652
+ }
653
+ });
654
+
655
+ card
656
+ .command('undone <cardId>')
657
+ .description('Mark a card as incomplete')
658
+ .action(async (cardId) => {
659
+ try {
660
+ await withSpinner('Updating card...', () =>
661
+ client.post(`/cards/update/${cardId}`, { isComplete: false })
662
+ );
663
+ success(`Card ${cardId} marked as incomplete`);
664
+ } catch (err) {
665
+ error(`Failed to update card: ${err.message}`);
666
+ }
667
+ });
668
+
302
669
  module.exports = card;
@@ -0,0 +1,173 @@
1
+ const { Command } = require('commander');
2
+ const chalk = require('chalk');
3
+ const client = require('../lib/client');
4
+ const { output, success, error } = require('../lib/output');
5
+ const { withSpinner } = require('../utils/spinner');
6
+ const { confirmAction } = require('../utils/prompts');
7
+
8
+ const checklist = new Command('checklist')
9
+ .alias('cl')
10
+ .description('Card checklist management commands');
11
+
12
+ checklist
13
+ .command('list <cardId>')
14
+ .alias('ls')
15
+ .description('List checklists on a card')
16
+ .option('-f, --format <format>', 'Output format')
17
+ .action(async (cardId, options) => {
18
+ try {
19
+ const data = await withSpinner('Fetching checklists...', () =>
20
+ client.get(`/cards/${cardId}/checklists`)
21
+ );
22
+
23
+ const checklists = data.checklists || data.data || data;
24
+ const clArr = Array.isArray(checklists) ? checklists : [];
25
+
26
+ if (clArr.length === 0) {
27
+ return error('No checklists on this card.');
28
+ }
29
+
30
+ // Display checklists with items
31
+ for (const cl of clArr) {
32
+ const items = cl.items || [];
33
+ const done = items.filter(i => i.checked).length;
34
+ console.log();
35
+ console.log(` ${chalk.bold(cl.title)} (${cl._id}) — ${done}/${items.length} done`);
36
+ for (const item of items) {
37
+ const check = item.checked ? chalk.green('✓') : chalk.gray('○');
38
+ console.log(` ${check} ${item.title} ${chalk.gray(`(${item._id})`)}`);
39
+ }
40
+ }
41
+ console.log();
42
+ } catch (err) {
43
+ error(`Failed to list checklists: ${err.message}`);
44
+ }
45
+ });
46
+
47
+ checklist
48
+ .command('add <cardId> <title>')
49
+ .description('Add a checklist to a card')
50
+ .action(async (cardId, title) => {
51
+ try {
52
+ const data = await withSpinner('Adding checklist...', () =>
53
+ client.post(`/cards/${cardId}/checklists`, { title })
54
+ );
55
+ const cl = data.checklist || data.data || data;
56
+ success(`Added checklist: ${chalk.bold(title)} (${cl._id})`);
57
+ } catch (err) {
58
+ error(`Failed to add checklist: ${err.message}`);
59
+ }
60
+ });
61
+
62
+ checklist
63
+ .command('rename <cardId> <checklistId>')
64
+ .description('Rename a checklist')
65
+ .option('-t, --title <title>', 'New title (required)')
66
+ .action(async (cardId, checklistId, options) => {
67
+ try {
68
+ if (!options.title) return error('Title is required. Use -t <title>.');
69
+
70
+ await withSpinner('Renaming checklist...', () =>
71
+ client.put(`/cards/${cardId}/checklists/${checklistId}`, { title: options.title })
72
+ );
73
+ success(`Renamed checklist to: ${chalk.bold(options.title)}`);
74
+ } catch (err) {
75
+ error(`Failed to rename checklist: ${err.message}`);
76
+ }
77
+ });
78
+
79
+ checklist
80
+ .command('delete <cardId> <checklistId>')
81
+ .description('Delete a checklist')
82
+ .option('--force', 'Skip confirmation')
83
+ .action(async (cardId, checklistId, options) => {
84
+ try {
85
+ if (!options.force) {
86
+ const confirmed = await confirmAction('Delete this checklist and all its items?');
87
+ if (!confirmed) return;
88
+ }
89
+
90
+ await withSpinner('Deleting checklist...', () =>
91
+ client.delete(`/cards/${cardId}/checklists/${checklistId}`)
92
+ );
93
+ success(`Deleted checklist ${checklistId}`);
94
+ } catch (err) {
95
+ error(`Failed to delete checklist: ${err.message}`);
96
+ }
97
+ });
98
+
99
+ checklist
100
+ .command('add-item <cardId> <checklistId> <title>')
101
+ .description('Add an item to a checklist')
102
+ .action(async (cardId, checklistId, title) => {
103
+ try {
104
+ await withSpinner('Adding item...', () =>
105
+ client.post(`/cards/${cardId}/checklists/${checklistId}/items`, { title })
106
+ );
107
+ success(`Added item: ${chalk.bold(title)}`);
108
+ } catch (err) {
109
+ error(`Failed to add item: ${err.message}`);
110
+ }
111
+ });
112
+
113
+ checklist
114
+ .command('check <cardId> <checklistId> <itemId>')
115
+ .description('Toggle an item as complete/incomplete')
116
+ .action(async (cardId, checklistId, itemId) => {
117
+ try {
118
+ // Fetch current state to toggle
119
+ const data = await client.get(`/cards/${cardId}/checklists`);
120
+ const checklists = data.checklists || data.data || data;
121
+ let currentChecked = false;
122
+ for (const cl of (Array.isArray(checklists) ? checklists : [])) {
123
+ if (cl._id === checklistId) {
124
+ const item = (cl.items || []).find(i => i._id === itemId);
125
+ if (item) currentChecked = item.checked;
126
+ }
127
+ }
128
+
129
+ await withSpinner('Toggling item...', () =>
130
+ client.put(`/cards/${cardId}/checklists/${checklistId}/items/${itemId}`, {
131
+ checked: !currentChecked,
132
+ })
133
+ );
134
+ success(!currentChecked ? 'Item marked as complete' : 'Item marked as incomplete');
135
+ } catch (err) {
136
+ error(`Failed to toggle item: ${err.message}`);
137
+ }
138
+ });
139
+
140
+ checklist
141
+ .command('update-item <cardId> <checklistId> <itemId>')
142
+ .description('Update a checklist item title')
143
+ .option('-t, --title <title>', 'New title (required)')
144
+ .action(async (cardId, checklistId, itemId, options) => {
145
+ try {
146
+ if (!options.title) return error('Title is required. Use -t <title>.');
147
+
148
+ await withSpinner('Updating item...', () =>
149
+ client.put(`/cards/${cardId}/checklists/${checklistId}/items/${itemId}`, {
150
+ title: options.title,
151
+ })
152
+ );
153
+ success(`Updated item to: ${chalk.bold(options.title)}`);
154
+ } catch (err) {
155
+ error(`Failed to update item: ${err.message}`);
156
+ }
157
+ });
158
+
159
+ checklist
160
+ .command('delete-item <cardId> <checklistId> <itemId>')
161
+ .description('Delete a checklist item')
162
+ .action(async (cardId, checklistId, itemId) => {
163
+ try {
164
+ await withSpinner('Deleting item...', () =>
165
+ client.delete(`/cards/${cardId}/checklists/${checklistId}/items/${itemId}`)
166
+ );
167
+ success('Deleted checklist item');
168
+ } catch (err) {
169
+ error(`Failed to delete item: ${err.message}`);
170
+ }
171
+ });
172
+
173
+ module.exports = checklist;
@@ -0,0 +1,101 @@
1
+ const { Command } = require('commander');
2
+ const chalk = require('chalk');
3
+ const config = require('../lib/config');
4
+ const client = require('../lib/client');
5
+ const { output, success, error } = require('../lib/output');
6
+ const { withSpinner } = require('../utils/spinner');
7
+ const { formatRelativeTime } = require('../utils/format');
8
+
9
+ const importCmd = new Command('import')
10
+ .description('Import data from external services');
11
+
12
+ importCmd
13
+ .command('trello')
14
+ .description('Import boards from Trello')
15
+ .option('--key <key>', 'Trello API key (required)')
16
+ .option('--token <token>', 'Trello token (required)')
17
+ .action(async (options) => {
18
+ try {
19
+ if (!options.key || !options.token) {
20
+ return error('Both --key and --token are required for Trello import.');
21
+ }
22
+
23
+ const workspaceId = config.get('activeWorkspace');
24
+ if (!workspaceId) return error('No active workspace.');
25
+
26
+ const data = await withSpinner('Importing from Trello...', () =>
27
+ client.post('/trello/import', {
28
+ trelloKey: options.key,
29
+ trelloToken: options.token,
30
+ workspaceId,
31
+ })
32
+ );
33
+
34
+ const job = data.job || data.data || data;
35
+ success(`Import started: Job ${chalk.bold(job._id || job.jobId || 'created')}`);
36
+ if (job._id || job.jobId) {
37
+ console.log(` Track progress: zoobbe import status ${job._id || job.jobId}`);
38
+ }
39
+ } catch (err) {
40
+ error(`Failed to import from Trello: ${err.message}`);
41
+ }
42
+ });
43
+
44
+ importCmd
45
+ .command('status <jobId>')
46
+ .description('Check import job status')
47
+ .action(async (jobId) => {
48
+ try {
49
+ const data = await withSpinner('Fetching job status...', () =>
50
+ client.get(`/import/jobs/${jobId}`)
51
+ );
52
+
53
+ const job = data.job || data.data || data;
54
+ console.log();
55
+ console.log(chalk.bold(' Job ID: '), job._id || jobId);
56
+ console.log(chalk.bold(' Status: '), job.status || 'unknown');
57
+ console.log(chalk.bold(' Progress: '), `${job.progress ?? 0}%`);
58
+ if (job.boardsImported) {
59
+ console.log(chalk.bold(' Boards: '), job.boardsImported);
60
+ }
61
+ if (job.cardsImported) {
62
+ console.log(chalk.bold(' Cards: '), job.cardsImported);
63
+ }
64
+ if (job.error) {
65
+ console.log(chalk.bold(' Error: '), chalk.red(job.error));
66
+ }
67
+ console.log();
68
+ } catch (err) {
69
+ error(`Failed to get job status: ${err.message}`);
70
+ }
71
+ });
72
+
73
+ importCmd
74
+ .command('jobs')
75
+ .description('List import jobs')
76
+ .option('-f, --format <format>', 'Output format')
77
+ .action(async (options) => {
78
+ try {
79
+ const data = await withSpinner('Fetching jobs...', () =>
80
+ client.get('/import/jobs')
81
+ );
82
+
83
+ const jobs = data.jobs || data.data || data;
84
+ const rows = (Array.isArray(jobs) ? jobs : []).map(j => ({
85
+ source: j.source || 'trello',
86
+ status: j.status || 'unknown',
87
+ progress: `${j.progress ?? 0}%`,
88
+ created: formatRelativeTime(j.createdAt),
89
+ id: j._id,
90
+ }));
91
+
92
+ output(rows, {
93
+ headers: ['Source', 'Status', 'Progress', 'Created', 'ID'],
94
+ format: options.format,
95
+ });
96
+ } catch (err) {
97
+ error(`Failed to list jobs: ${err.message}`);
98
+ }
99
+ });
100
+
101
+ module.exports = importCmd;