canvaslms-cli 1.3.3 → 1.4.0

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.
@@ -1,205 +1,201 @@
1
- /**
2
- * Grades command
3
- */
4
-
5
- const { makeCanvasRequest } = require('../lib/api-client');
6
- const { createReadlineInterface, askQuestion } = require('../lib/interactive');
7
-
8
- async function showGrades(courseId, options) {
9
- const rl = createReadlineInterface();
10
-
11
- try {
12
- if (courseId) {
13
- // Get grades for specific course with assignment details
14
- await showCourseGrades(courseId, options, rl);
15
- } else {
16
- // Interactive course selection for grades
17
- await showInteractiveGrades(options, rl);
18
- }
19
-
20
- } catch (error) {
21
- console.error('Error fetching grades:', error.message);
22
- process.exit(1);
23
- } finally {
24
- rl.close();
25
- }
26
- }
27
-
28
- async function showCourseGrades(courseId, options, rl) {
29
- // Get course details
30
- const course = await makeCanvasRequest('get', `courses/${courseId}`);
31
-
32
- // Get overall enrollment grades
33
- const enrollments = await makeCanvasRequest('get', `courses/${courseId}/enrollments`, [
34
- 'user_id=self',
35
- 'include[]=grades'
36
- ]);
37
-
38
- if (!enrollments || enrollments.length === 0) {
39
- console.log('No enrollment found for this course.');
40
- return;
41
- }
42
-
43
- const enrollment = enrollments[0];
44
-
45
- console.log(`\nšŸ“š Grades for: ${course.name}`);
46
- console.log(`šŸ“Š Course Overview:`);
47
- console.log(` Current Score: ${enrollment.grades?.current_score || 'N/A'}%`);
48
- console.log(` Final Score: ${enrollment.grades?.final_score || 'N/A'}%`);
49
- console.log(` Current Grade: ${enrollment.grades?.current_grade || 'N/A'}`);
50
- console.log(` Final Grade: ${enrollment.grades?.final_grade || 'N/A'}`);
51
-
52
- // Get assignment grades
53
- console.log('\nšŸ“ Loading assignment grades...');
54
- const assignments = await makeCanvasRequest('get', `courses/${courseId}/assignments`, [
55
- 'include[]=submission',
56
- 'order_by=due_at',
57
- 'per_page=100'
58
- ]);
59
-
60
- if (!assignments || assignments.length === 0) {
61
- console.log('No assignments found for this course.');
62
- return;
63
- }
64
-
65
- // Filter assignments with grades
66
- const gradedAssignments = assignments.filter(assignment => {
67
- const submission = assignment.submission;
68
- return submission && (
69
- submission.score !== null ||
70
- submission.excused ||
71
- submission.missing ||
72
- submission.grade
73
- );
74
- });
75
-
76
- if (gradedAssignments.length === 0) {
77
- console.log('No graded assignments found.');
78
- return;
79
- }
80
-
81
- console.log(`\nšŸ“‹ Assignment Grades (${gradedAssignments.length} graded):`);
82
- gradedAssignments.forEach((assignment, index) => {
83
- const submission = assignment.submission;
84
- let gradeDisplay = '';
85
- let gradeColor = '';
86
-
87
- if (submission.score !== null && submission.score !== undefined) {
88
- const score = submission.score % 1 === 0 ? Math.round(submission.score) : submission.score;
89
- const total = assignment.points_possible || 0;
90
- gradeDisplay = `${score}/${total} pts`;
91
-
92
- // Color coding based on percentage
93
- if (total > 0) {
94
- const percentage = (submission.score / total) * 100;
95
- if (percentage >= 90) gradeColor = '\x1b[32m'; // Green
96
- else if (percentage >= 80) gradeColor = '\x1b[36m'; // Cyan
97
- else if (percentage >= 70) gradeColor = '\x1b[33m'; // Yellow
98
- else if (percentage >= 60) gradeColor = '\x1b[35m'; // Magenta
99
- else gradeColor = '\x1b[31m'; // Red
100
- }
101
-
102
- // Add letter grade if available
103
- if (submission.grade && isNaN(submission.grade)) {
104
- gradeDisplay = `${submission.grade} (${gradeDisplay})`;
105
- }
106
- } else if (submission.excused) {
107
- gradeDisplay = 'Excused';
108
- gradeColor = '\x1b[34m'; // Blue
109
- } else if (submission.missing) {
110
- gradeDisplay = 'Missing';
111
- gradeColor = '\x1b[31m'; // Red
112
- }
113
-
114
- console.log(`${index + 1}. ${assignment.name}`);
115
- console.log(` Grade: ${gradeColor}${gradeDisplay}\x1b[0m`);
116
-
117
- if (submission.submitted_at) {
118
- console.log(` Submitted: ${new Date(submission.submitted_at).toLocaleDateString()}`);
119
- }
120
-
121
- if (assignment.due_at) {
122
- console.log(` Due: ${new Date(assignment.due_at).toLocaleDateString()}`);
123
- }
124
-
125
- if (options.verbose && submission.grader_comments) {
126
- console.log(` Comments: ${submission.grader_comments}`);
127
- }
128
-
129
- console.log('');
130
- });
131
- }
132
-
133
- async function showInteractiveGrades(options, rl) {
134
- // Get all courses with enrollment information
135
- const courses = await makeCanvasRequest('get', 'courses', [
136
- 'enrollment_state=active',
137
- 'include[]=enrollments',
138
- 'include[]=favorites',
139
- 'include[]=total_scores'
140
- ]);
141
-
142
- if (!courses || courses.length === 0) {
143
- console.log('No courses found.');
144
- return;
145
- }
146
-
147
- // Show courses overview first
148
- console.log('šŸ“Š Grades Overview:\n');
149
-
150
- const coursesWithGrades = courses.filter(course =>
151
- course.enrollments && course.enrollments.length > 0
152
- );
153
-
154
- console.log(`Found ${coursesWithGrades.length} enrolled course(s):\n`);
155
-
156
- coursesWithGrades.forEach((course, index) => {
157
- const starIcon = course.is_favorite ? '⭐ ' : '';
158
- console.log(`${index + 1}. ${starIcon}${course.name}`);
159
-
160
- if (course.enrollments && course.enrollments.length > 0) {
161
- const enrollment = course.enrollments[0];
162
- if (enrollment.grades) {
163
- const currentScore = enrollment.grades.current_score;
164
- const currentGrade = enrollment.grades.current_grade;
165
-
166
- // Color code the grade
167
- let gradeColor = '\x1b[90m'; // Gray default
168
- if (currentScore !== null && currentScore !== undefined) {
169
- if (currentScore >= 90) gradeColor = '\x1b[32m'; // Green
170
- else if (currentScore >= 80) gradeColor = '\x1b[36m'; // Cyan
171
- else if (currentScore >= 70) gradeColor = '\x1b[33m'; // Yellow
172
- else if (currentScore >= 60) gradeColor = '\x1b[35m'; // Magenta
173
- else gradeColor = '\x1b[31m'; // Red
174
- }
175
-
176
- console.log(` Current: ${gradeColor}${currentScore || 'N/A'}% (${currentGrade || 'N/A'})\x1b[0m`);
177
- } else {
178
- console.log(` Current: \x1b[90mGrades not available\x1b[0m`);
179
- }
180
- }
181
- console.log('');
182
- });
183
-
184
- // Ask if user wants to see detailed grades for a specific course
185
- const viewDetailed = await askQuestion(rl, 'View detailed grades for a specific course? (Y/n): ');
186
-
187
- if (viewDetailed.toLowerCase() === 'n' || viewDetailed.toLowerCase() === 'no') {
188
- return;
189
- }
190
-
191
- const courseChoice = await askQuestion(rl, '\nEnter course number for detailed grades: ');
192
- const courseIndex = parseInt(courseChoice) - 1;
193
-
194
- if (courseIndex >= 0 && courseIndex < coursesWithGrades.length) {
195
- const selectedCourse = coursesWithGrades[courseIndex];
196
- console.log(`\nāœ… Selected: ${selectedCourse.name}`);
197
- await showCourseGrades(selectedCourse.id, options, rl);
198
- } else {
199
- console.log('Invalid course selection.');
200
- }
201
- }
202
-
203
- module.exports = {
204
- showGrades
205
- };
1
+ /**
2
+ * Grades command
3
+ */
4
+
5
+ import { makeCanvasRequest } from '../lib/api-client.js';
6
+ import { createReadlineInterface, askQuestion } from '../lib/interactive.js';
7
+ import chalk from 'chalk';
8
+
9
+ export async function showGrades(courseId, options) {
10
+ const rl = createReadlineInterface();
11
+
12
+ try {
13
+ if (courseId) {
14
+ // Get grades for specific course with assignment details
15
+ await showCourseGrades(courseId, options, rl);
16
+ } else {
17
+ // Interactive course selection for grades
18
+ await showInteractiveGrades(options, rl);
19
+ }
20
+
21
+ } catch (error) {
22
+ console.error(chalk.red('Error fetching grades: ') + error.message);
23
+ process.exit(1);
24
+ } finally {
25
+ rl.close();
26
+ }
27
+ }
28
+
29
+ async function showCourseGrades(courseId, options, rl) {
30
+ // Get course details
31
+ const course = await makeCanvasRequest('get', `courses/${courseId}`);
32
+
33
+ // Get overall enrollment grades
34
+ const enrollments = await makeCanvasRequest('get', `courses/${courseId}/enrollments`, [
35
+ 'user_id=self',
36
+ 'include[]=grades'
37
+ ]);
38
+
39
+ if (!enrollments || enrollments.length === 0) {
40
+ console.log(chalk.red('Error: No enrollment found for this course.'));
41
+ return;
42
+ }
43
+
44
+ const enrollment = enrollments[0];
45
+
46
+ console.log(chalk.cyan.bold('\n' + '-'.repeat(60)));
47
+ console.log(chalk.cyan.bold('Grades for: ') + course.name);
48
+ console.log(chalk.cyan('-'.repeat(60)));
49
+ console.log(chalk.white('Course Overview:'));
50
+ console.log(chalk.white(' Current Score: ') + (enrollment.grades?.current_score || 'N/A') + '%');
51
+ console.log(chalk.white(' Final Score: ') + (enrollment.grades?.final_score || 'N/A') + '%');
52
+ console.log(chalk.white(' Current Grade: ') + (enrollment.grades?.current_grade || 'N/A'));
53
+ console.log(chalk.white(' Final Grade: ') + (enrollment.grades?.final_grade || 'N/A'));
54
+
55
+ // Get assignment grades
56
+ console.log(chalk.cyan('\nLoading assignment grades...'));
57
+ const assignments = await makeCanvasRequest('get', `courses/${courseId}/assignments`, [
58
+ 'include[]=submission',
59
+ 'order_by=due_at',
60
+ 'per_page=100'
61
+ ]);
62
+
63
+ if (!assignments || assignments.length === 0) {
64
+ console.log(chalk.yellow('No assignments found for this course.'));
65
+ return;
66
+ }
67
+
68
+ // Filter assignments with grades
69
+ const gradedAssignments = assignments.filter(assignment => {
70
+ const submission = assignment.submission;
71
+ return submission && (
72
+ submission.score !== null ||
73
+ submission.excused ||
74
+ submission.missing ||
75
+ submission.grade
76
+ );
77
+ });
78
+
79
+ if (gradedAssignments.length === 0) {
80
+ console.log(chalk.yellow('No graded assignments found.'));
81
+ return;
82
+ }
83
+
84
+ console.log(chalk.green('Success: Grades loaded.'));
85
+ console.log(chalk.cyan.bold('\n' + '-'.repeat(60)));
86
+ console.log(chalk.cyan.bold(`Assignment Grades (${gradedAssignments.length} graded):`));
87
+ console.log(chalk.cyan('-'.repeat(60)));
88
+ gradedAssignments.forEach((assignment, index) => {
89
+ const submission = assignment.submission;
90
+ let gradeDisplay = '';
91
+ let gradeColor = chalk.white;
92
+
93
+ if (submission.score !== null && submission.score !== undefined) {
94
+ const score = submission.score % 1 === 0 ? Math.round(submission.score) : submission.score;
95
+ const total = assignment.points_possible || 0;
96
+ gradeDisplay = `${score}/${total} pts`;
97
+
98
+ // Color coding based on percentage
99
+ if (total > 0) {
100
+ const percentage = (submission.score / total) * 100;
101
+ if (percentage >= 90) gradeColor = chalk.green;
102
+ else if (percentage >= 80) gradeColor = chalk.cyan;
103
+ else if (percentage >= 70) gradeColor = chalk.yellow;
104
+ else if (percentage >= 60) gradeColor = chalk.magenta;
105
+ else gradeColor = chalk.red;
106
+ }
107
+
108
+ // Add letter grade if available
109
+ if (submission.grade && isNaN(submission.grade)) {
110
+ gradeDisplay = `${submission.grade} (${gradeDisplay})`;
111
+ }
112
+ } else if (submission.excused) {
113
+ gradeDisplay = 'Excused';
114
+ gradeColor = chalk.blue;
115
+ } else if (submission.missing) {
116
+ gradeDisplay = 'Missing';
117
+ gradeColor = chalk.red;
118
+ }
119
+
120
+ console.log(chalk.white(`${index + 1}. ${assignment.name}`));
121
+ console.log(' Grade: ' + gradeColor(gradeDisplay));
122
+
123
+ if (submission.submitted_at) {
124
+ console.log(' Submitted: ' + new Date(submission.submitted_at).toLocaleDateString());
125
+ }
126
+
127
+ if (assignment.due_at) {
128
+ console.log(' Due: ' + new Date(assignment.due_at).toLocaleDateString());
129
+ }
130
+
131
+ if (options.verbose && submission.grader_comments) {
132
+ console.log(' Comments: ' + submission.grader_comments);
133
+ }
134
+
135
+ console.log('');
136
+ });
137
+ }
138
+
139
+ async function showInteractiveGrades(options, rl) {
140
+ // Get all courses with enrollment information
141
+ const courses = await makeCanvasRequest('get', 'courses', [
142
+ 'enrollment_state=active',
143
+ 'include[]=enrollments',
144
+ 'include[]=favorites',
145
+ 'include[]=total_scores'
146
+ ]);
147
+
148
+ if (!courses || courses.length === 0) {
149
+ console.log(chalk.red('Error: No courses found.'));
150
+ return;
151
+ }
152
+
153
+ // Move declaration above first use
154
+ const coursesWithGrades = courses.filter(course =>
155
+ course.enrollments && course.enrollments.length > 0
156
+ );
157
+
158
+ // Show courses overview first
159
+ console.log(chalk.cyan.bold('\n' + '-'.repeat(60)));
160
+ console.log(chalk.cyan.bold('Grades Overview'));
161
+ console.log(chalk.cyan('-'.repeat(60)));
162
+ console.log(chalk.white(`Found ${coursesWithGrades.length} enrolled course(s):\n`));
163
+
164
+ coursesWithGrades.forEach((course, index) => {
165
+ let gradeColor = chalk.gray;
166
+ const enrollment = course.enrollments[0];
167
+ const currentScore = enrollment.grades?.current_score;
168
+ if (currentScore !== null && currentScore !== undefined) {
169
+ if (currentScore >= 90) gradeColor = chalk.green;
170
+ else if (currentScore >= 80) gradeColor = chalk.cyan;
171
+ else if (currentScore >= 70) gradeColor = chalk.yellow;
172
+ else if (currentScore >= 60) gradeColor = chalk.magenta;
173
+ else gradeColor = chalk.red;
174
+ }
175
+ console.log(chalk.white(`${index + 1}. ${course.name}`));
176
+ if (enrollment.grades) {
177
+ console.log(' Current: ' + gradeColor(`${currentScore || 'N/A'}% (${enrollment.grades.current_grade || 'N/A'})`));
178
+ } else {
179
+ console.log(' Current: ' + chalk.gray('Grades not available'));
180
+ }
181
+ console.log('');
182
+ });
183
+
184
+ // Ask if user wants to see detailed grades for a specific course
185
+ const viewDetailed = await askQuestion(rl, 'View detailed grades for a specific course? (Y/n): ');
186
+
187
+ if (viewDetailed.toLowerCase() === 'n' || viewDetailed.toLowerCase() === 'no') {
188
+ return;
189
+ }
190
+
191
+ const courseChoice = await askQuestion(rl, '\nEnter course number for detailed grades: ');
192
+ const courseIndex = parseInt(courseChoice) - 1;
193
+
194
+ if (courseIndex >= 0 && courseIndex < coursesWithGrades.length) {
195
+ const selectedCourse = coursesWithGrades[courseIndex];
196
+ console.log(chalk.green(`\nSelected: ${selectedCourse.name}`));
197
+ await showCourseGrades(selectedCourse.id, options, rl);
198
+ } else {
199
+ console.log(chalk.red('Invalid course selection.'));
200
+ }
201
+ }
package/commands/list.js CHANGED
@@ -1,70 +1,68 @@
1
- /**
2
- * List courses command
3
- */
4
-
5
- const { makeCanvasRequest } = require('../lib/api-client');
6
-
7
- async function listCourses(options) {
8
- try {
9
- const queryParams = [];
10
-
11
- // Always show only active courses
12
- queryParams.push('enrollment_state=active');
13
-
14
- // Include additional course information
15
- queryParams.push('include[]=term');
16
- queryParams.push('include[]=course_progress');
17
- queryParams.push('include[]=total_students');
18
- queryParams.push('include[]=favorites'); // Include favorite status
19
-
20
- const courses = await makeCanvasRequest('get', 'courses', queryParams);
21
-
22
- if (!courses || courses.length === 0) {
23
- console.log('No courses found.');
24
- return;
25
- }
26
-
27
- // By default, show only starred courses unless -a flag is used
28
- let filteredCourses = courses;
29
- if (!options.all) {
30
- filteredCourses = courses.filter(course => course.is_favorite);
31
-
32
- if (filteredCourses.length === 0) {
33
- console.log('No starred courses found. Use -a to see all courses.');
34
- return;
35
- }
36
- }
37
-
38
- const courseLabel = options.all ? 'enrolled course(s)' : 'starred course(s)';
39
- console.log(`Found ${filteredCourses.length} ${courseLabel}:\n`);
40
-
41
- filteredCourses.forEach((course, index) => {
42
- const starIcon = course.is_favorite ? '⭐ ' : '';
43
- console.log(`${index + 1}. ${starIcon}${course.name}`);
44
- console.log(` ID: ${course.id}`);
45
- console.log(` Code: ${course.course_code || 'N/A'}`);
46
-
47
- if (options.verbose) {
48
- console.log(` Term: ${course.term?.name || 'N/A'}`);
49
- console.log(` Students: ${course.total_students || 'N/A'}`);
50
- console.log(` Start Date: ${course.start_at ? new Date(course.start_at).toLocaleDateString() : 'N/A'}`);
51
- console.log(` End Date: ${course.end_at ? new Date(course.end_at).toLocaleDateString() : 'N/A'}`);
52
- console.log(` Workflow State: ${course.workflow_state}`);
53
-
54
- if (course.course_progress) {
55
- console.log(` Progress: ${course.course_progress.requirement_completed_count || 0}/${course.course_progress.requirement_count || 0} requirements`);
56
- }
57
- }
58
-
59
- console.log(''); // Empty line between courses
60
- });
61
-
62
- } catch (error) {
63
- console.error('Error fetching courses:', error.message);
64
- process.exit(1);
65
- }
66
- }
67
-
68
- module.exports = {
69
- listCourses
70
- };
1
+ /**
2
+ * List courses command
3
+ */
4
+
5
+ import { makeCanvasRequest } from '../lib/api-client.js';
6
+ import chalk from 'chalk';
7
+
8
+ function pad(str, len) {
9
+ return str + ' '.repeat(Math.max(0, len - str.length));
10
+ }
11
+
12
+ export async function listCourses(options) {
13
+ try {
14
+ const queryParams = [];
15
+ queryParams.push('enrollment_state=active');
16
+ queryParams.push('include[]=term');
17
+ queryParams.push('include[]=course_progress');
18
+ queryParams.push('include[]=total_students');
19
+ queryParams.push('include[]=favorites');
20
+
21
+ console.log(chalk.cyan.bold('\n' + '-'.repeat(60)));
22
+ console.log(chalk.cyan.bold('Loading courses, please wait...'));
23
+ const courses = await makeCanvasRequest('get', 'courses', queryParams);
24
+ if (!courses || courses.length === 0) {
25
+ console.log(chalk.red('Error: No courses found.'));
26
+ return;
27
+ }
28
+ let filteredCourses = courses;
29
+ if (!options.all) {
30
+ filteredCourses = courses.filter(course => course.is_favorite);
31
+ if (filteredCourses.length === 0) {
32
+ console.log(chalk.red('Error: No starred courses found. Use -a to see all courses.'));
33
+ return;
34
+ }
35
+ }
36
+ const courseLabel = options.all ? 'enrolled course(s)' : 'starred course(s)';
37
+ console.log(chalk.green(`Success: Found ${filteredCourses.length} ${courseLabel}.`));
38
+ console.log(chalk.cyan('-'.repeat(60)));
39
+ // Column headers
40
+ console.log(
41
+ pad(chalk.bold('No.'), 5) +
42
+ pad(chalk.bold('Course Name'), 35) +
43
+ pad(chalk.bold('ID'), 10) +
44
+ pad(chalk.bold('Code'), 12) +
45
+ (options.verbose ? pad(chalk.bold('Term'), 15) + pad(chalk.bold('Students'), 10) + pad(chalk.bold('Start'), 12) + pad(chalk.bold('End'), 12) + pad(chalk.bold('State'), 12) + pad(chalk.bold('Progress'), 18) : '')
46
+ );
47
+ console.log(chalk.cyan('-'.repeat(60)));
48
+ filteredCourses.forEach((course, index) => {
49
+ let line = pad(chalk.white((index + 1) + '.'), 5) +
50
+ pad(course.name, 35) +
51
+ pad(String(course.id), 10) +
52
+ pad(course.course_code || 'N/A', 12);
53
+ if (options.verbose) {
54
+ line += pad(course.term?.name || 'N/A', 15) +
55
+ pad(String(course.total_students || 'N/A'), 10) +
56
+ pad(course.start_at ? new Date(course.start_at).toLocaleDateString() : 'N/A', 12) +
57
+ pad(course.end_at ? new Date(course.end_at).toLocaleDateString() : 'N/A', 12) +
58
+ pad(course.workflow_state, 12) +
59
+ pad(course.course_progress ? `${course.course_progress.requirement_completed_count || 0}/${course.course_progress.requirement_count || 0}` : 'N/A', 18);
60
+ }
61
+ console.log(line);
62
+ });
63
+ console.log(chalk.cyan('-'.repeat(60)));
64
+ } catch (error) {
65
+ console.error(chalk.red('Error fetching courses:'), error.message);
66
+ process.exit(1);
67
+ }
68
+ }
@@ -1,34 +1,35 @@
1
- /**
2
- * Profile command
3
- */
4
-
5
- const { makeCanvasRequest } = require('../lib/api-client');
6
-
7
- async function showProfile(options) {
8
- try {
9
- const user = await makeCanvasRequest('get', 'users/self', ['include[]=email', 'include[]=locale']);
10
-
11
- console.log('User Profile:\n');
12
- console.log(`Name: ${user.name}`);
13
- console.log(`ID: ${user.id}`);
14
- console.log(`Email: ${user.email || 'N/A'}`);
15
- console.log(`Login ID: ${user.login_id || 'N/A'}`);
16
-
17
- if (options.verbose) {
18
- console.log(`Short Name: ${user.short_name || 'N/A'}`);
19
- console.log(`Sortable Name: ${user.sortable_name || 'N/A'}`);
20
- console.log(`Locale: ${user.locale || 'N/A'}`);
21
- console.log(`Time Zone: ${user.time_zone || 'N/A'}`);
22
- console.log(`Avatar URL: ${user.avatar_url || 'N/A'}`);
23
- console.log(`Created: ${user.created_at ? new Date(user.created_at).toLocaleString() : 'N/A'}`);
24
- }
25
-
26
- } catch (error) {
27
- console.error('Error fetching profile:', error.message);
28
- process.exit(1);
29
- }
30
- }
31
-
32
- module.exports = {
33
- showProfile
34
- };
1
+ /**
2
+ * Profile command
3
+ */
4
+
5
+ import { makeCanvasRequest } from '../lib/api-client.js';
6
+ import chalk from 'chalk';
7
+
8
+ export async function showProfile(options) {
9
+ try {
10
+ console.log(chalk.cyan.bold('Loading profile, please wait...'));
11
+ const user = await makeCanvasRequest('get', 'users/self', ['include[]=email', 'include[]=locale']);
12
+
13
+ console.log(chalk.cyan.bold('\n' + '-'.repeat(60)));
14
+ console.log(chalk.cyan.bold('User Profile'));
15
+ console.log(chalk.cyan('-'.repeat(60)));
16
+ console.log(chalk.white('Name: ') + user.name);
17
+ console.log(chalk.white('ID: ') + user.id);
18
+ console.log(chalk.white('Email: ') + (user.email || 'N/A'));
19
+ console.log(chalk.white('Login ID: ') + (user.login_id || 'N/A'));
20
+
21
+ if (options.verbose) {
22
+ console.log(chalk.white('Short Name: ') + (user.short_name || 'N/A'));
23
+ console.log(chalk.white('Sortable Name: ') + (user.sortable_name || 'N/A'));
24
+ console.log(chalk.white('Locale: ') + (user.locale || 'N/A'));
25
+ console.log(chalk.white('Time Zone: ') + (user.time_zone || 'N/A'));
26
+ console.log(chalk.white('Avatar URL: ') + (user.avatar_url || 'N/A'));
27
+ console.log(chalk.white('Created: ') + (user.created_at ? new Date(user.created_at).toLocaleString() : 'N/A'));
28
+ }
29
+ console.log(chalk.green('Success: Profile loaded.'));
30
+
31
+ } catch (error) {
32
+ console.error(chalk.red('Error: Failed to fetch profile: ') + error.message);
33
+ process.exit(1);
34
+ }
35
+ }