omjoshi 1.0.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.
Files changed (2) hide show
  1. package/bin/index.js +217 -0
  2. package/package.json +27 -0
package/bin/index.js ADDED
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env node
2
+
3
+ import chalk from 'chalk';
4
+ import boxen from 'boxen';
5
+ import readline from 'readline/promises';
6
+ import { stdin as input, stdout as output } from 'process';
7
+ import figlet from 'figlet';
8
+ import gradient from 'gradient-string';
9
+ import ora from 'ora';
10
+ import Table from 'cli-table3';
11
+
12
+ // --- DATA ---
13
+ const data = {
14
+ name: chalk.white.bold('Om Joshi'),
15
+ handle: chalk.redBright('@omjoshi'),
16
+ work: chalk.white('Software Engineer'),
17
+ github: chalk.gray('https://github.com/') + chalk.red('omjoshi'),
18
+ linkedin: chalk.gray('https://linkedin.com/in/') + chalk.red('omjoshi'),
19
+ web: chalk.redBright('https://omjoshi.com'),
20
+
21
+ labelWork: chalk.white.bold(' Work:'),
22
+ labelGitHub: chalk.white.bold(' GitHub:'),
23
+ labelLinkedIn: chalk.white.bold(' LinkedIn:'),
24
+ labelWeb: chalk.white.bold(' Web:')
25
+ };
26
+
27
+ const projects = [
28
+ { name: 'Bhakti Link', desc: 'Cross-platform mobile application built using Flutter' },
29
+ { name: 'AI Tradesperson Assistant', desc: 'Mobile-first, voice-integrated AI brain for trade businesses' },
30
+ { name: 'ML Trading Bot', desc: 'Local financial trading bot using machine learning and Alpaca API' }
31
+ ];
32
+
33
+ const commands = ['help', 'about', 'projects', 'skills', 'clear', 'exit', 'quit'];
34
+
35
+ // Tab completion feature
36
+ function completer(line) {
37
+ const hits = commands.filter((c) => c.startsWith(line));
38
+ return [hits.length ? hits : commands, line];
39
+ }
40
+
41
+ const rl = readline.createInterface({ input, output, completer });
42
+
43
+ // --- UTILS ---
44
+ const sleep = (ms = 1000) => new Promise((r) => setTimeout(r, ms));
45
+
46
+ // Strip ANSI color codes to accurately measure string width in terminal
47
+ const ansiRegex = /\x1B\[[0-9;]*m/g;
48
+ function getVisibleLength(str) {
49
+ return str.replace(ansiRegex, '').length;
50
+ }
51
+
52
+ // Center text in the terminal horizontally
53
+ function center(text) {
54
+ const termWidth = process.stdout.columns || 80;
55
+ const lines = text.split('\n');
56
+
57
+ return lines.map(line => {
58
+ const visibleLength = getVisibleLength(line);
59
+ if (visibleLength >= termWidth) return line;
60
+ const padding = Math.max(0, Math.floor((termWidth - visibleLength) / 2));
61
+ return ' '.repeat(padding) + line;
62
+ }).join('\n');
63
+ }
64
+
65
+ async function showTitle() {
66
+ return new Promise((resolve) => {
67
+ figlet('Om Joshi', (err, data) => {
68
+ const redGradient = gradient(['#ff4d4d', '#cc0000', '#660000']);
69
+ // Color it first, then center the colored text block
70
+ console.log(center(redGradient.multiline(data)));
71
+ resolve();
72
+ });
73
+ });
74
+ }
75
+
76
+ function printAboutBox() {
77
+ const newline = '\n';
78
+ const heading = `${data.name} / ${data.handle}`;
79
+ const working = `${data.labelWork} ${data.work}`;
80
+ const githubing = `${data.labelGitHub} ${data.github}`;
81
+ const linkedining = `${data.labelLinkedIn} ${data.linkedin}`;
82
+ const webing = `${data.labelWeb} ${data.web}`;
83
+
84
+ const outputStr = heading +
85
+ newline + newline +
86
+ working + newline +
87
+ githubing + newline +
88
+ linkedining + newline +
89
+ webing;
90
+
91
+ const options = {
92
+ padding: 1,
93
+ margin: 1,
94
+ borderStyle: 'double',
95
+ borderColor: 'red'
96
+ };
97
+
98
+ // Create the box, then center the final rendered box string
99
+ const renderedBox = chalk.red(boxen(outputStr, options));
100
+ console.log(center(renderedBox));
101
+ }
102
+
103
+ function printProjects() {
104
+ const table = new Table({
105
+ head: [chalk.redBright('Project Name'), chalk.redBright('Description')],
106
+ colWidths: [30, 60],
107
+ chars: {
108
+ 'top': '═', 'top-mid': '╤', 'top-left': '╔', 'top-right': '╗',
109
+ 'bottom': '═', 'bottom-mid': '╧', 'bottom-left': '╚', 'bottom-right': '╝',
110
+ 'left': '║', 'left-mid': '╟', 'mid': '─', 'mid-mid': '┼',
111
+ 'right': '║', 'right-mid': '╢', 'middle': '│'
112
+ }
113
+ });
114
+
115
+ projects.forEach(p => table.push([chalk.white.bold(p.name), chalk.gray(p.desc)]));
116
+ console.log(center(table.toString()));
117
+ }
118
+
119
+ function printSkills() {
120
+ const table = new Table({
121
+ head: [chalk.redBright('Category'), chalk.redBright('Technologies')],
122
+ colWidths: [20, 70],
123
+ style: { head: [], border: [] }
124
+ });
125
+
126
+ table.push(
127
+ [chalk.white('Languages'), chalk.gray('JavaScript, TypeScript, Python, Dart, HTML, CSS')],
128
+ [chalk.white('Frameworks'), chalk.gray('Node.js, React, Next.js, Flutter')],
129
+ [chalk.white('Tools'), chalk.gray('Git, Docker, Machine Learning, npm')]
130
+ );
131
+
132
+ console.log(center(table.toString()));
133
+ }
134
+
135
+ async function main() {
136
+ console.clear();
137
+ await showTitle();
138
+
139
+ console.log(center(chalk.gray('Welcome to the interactive terminal.')));
140
+ console.log(center(chalk.gray('Hit [TAB] to autocomplete, type "help" for commands, or "exit" to quit.')));
141
+ console.log();
142
+
143
+ while (true) {
144
+ // Generate centered prompt
145
+ const promptChar = '❯ ';
146
+ const termWidth = process.stdout.columns || 80;
147
+ // We add 3 spaces to roughly keep the typed text centered as well
148
+ const padding = Math.max(0, Math.floor((termWidth - promptChar.length) / 2) - 10);
149
+ const centeredPromptStr = ' '.repeat(padding) + chalk.redBright(promptChar);
150
+
151
+ const answer = await rl.question(centeredPromptStr);
152
+ const command = answer.trim().toLowerCase();
153
+
154
+ if (!command) continue;
155
+
156
+ if (command === 'exit' || command === 'quit') {
157
+ console.log(center(chalk.gray('Goodbye!')));
158
+ rl.close();
159
+ break;
160
+ }
161
+
162
+ if (command === 'clear') {
163
+ console.clear();
164
+ continue;
165
+ }
166
+
167
+ // Determine left padding for spinner to keep it roughly centered
168
+ const spinnerPadding = ' '.repeat(padding);
169
+
170
+ // Cool spinner effect
171
+ const spinner = ora({
172
+ text: chalk.red(`Executing ${command}...`),
173
+ spinner: 'dots',
174
+ color: 'red',
175
+ prefixText: spinnerPadding
176
+ }).start();
177
+
178
+ await sleep(400);
179
+
180
+ if (command === 'help') {
181
+ spinner.stop();
182
+ console.log();
183
+ console.log(center(chalk.white.bold('Available Commands:')));
184
+ console.log(center(chalk.redBright('about ') + chalk.gray(' - Read about me and find my links')));
185
+ console.log(center(chalk.redBright('projects') + chalk.gray(' - View my recent work')));
186
+ console.log(center(chalk.redBright('skills ') + chalk.gray(' - See my technical arsenal')));
187
+ console.log(center(chalk.redBright('clear ') + chalk.gray(' - Clear the terminal output')));
188
+ console.log(center(chalk.redBright('exit ') + chalk.gray(' - Leave the terminal')));
189
+ console.log();
190
+ } else if (command === 'about') {
191
+ spinner.succeed(chalk.red('Profile loaded\n'));
192
+ printAboutBox();
193
+ console.log();
194
+ } else if (command === 'projects') {
195
+ spinner.succeed(chalk.red('Projects fetched\n'));
196
+ printProjects();
197
+ console.log();
198
+ } else if (command === 'skills') {
199
+ spinner.succeed(chalk.red('Skills compiled\n'));
200
+ printSkills();
201
+ console.log();
202
+ } else {
203
+ spinner.fail(chalk.white(`Command not found: "${command}"`));
204
+ console.log(center(chalk.gray('Type "help" to see available commands.')));
205
+ console.log();
206
+ }
207
+ }
208
+ }
209
+
210
+ // Handle ctrl+c gracefully
211
+ rl.on('SIGINT', () => {
212
+ console.log(center(chalk.gray('\nGoodbye!')));
213
+ rl.close();
214
+ process.exit(0);
215
+ });
216
+
217
+ main();
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "omjoshi",
3
+ "version": "1.0.0",
4
+ "description": "CLI Portfolio for Om Joshi",
5
+ "main": "bin/index.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "omjoshi": "bin/index.js"
9
+ },
10
+ "scripts": {
11
+ "test": "echo \"Error: no test specified\" && exit 1"
12
+ },
13
+ "keywords": [
14
+ "cli",
15
+ "portfolio"
16
+ ],
17
+ "author": "Om Joshi",
18
+ "license": "ISC",
19
+ "dependencies": {
20
+ "boxen": "^8.0.1",
21
+ "chalk": "^5.6.2",
22
+ "cli-table3": "^0.6.5",
23
+ "figlet": "^1.11.0",
24
+ "gradient-string": "^3.0.0",
25
+ "ora": "^9.4.1"
26
+ }
27
+ }