himanshuchandola 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.
- package/LICENSE +21 -0
- package/README.md +175 -0
- package/dist/index.js +291 -0
- package/package.json +80 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Himanshu Chandola
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# himanshuchandola-cli
|
|
2
|
+
|
|
3
|
+
Interactive CLI portfolio for Himanshu Chandola - A modern terminal experience built with TypeScript.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/himanshuchandola)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
A TypeScript-based interactive CLI tool that serves as a terminal portfolio. Features animated ASCII banner, terminal card display, and interactive menu navigation to explore my digital presence.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
### Run without installing
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx himanshuchandola
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Install globally
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install -g himanshuchandola
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Then run:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
himanshuchandola
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
himanshuchandola [options]
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Options
|
|
40
|
+
|
|
41
|
+
- `--open=<destination>` - Open a destination directly (portfolio, github, linkedin, peerlist, twitter)
|
|
42
|
+
- `--no-anim` - Skip the animated banner
|
|
43
|
+
- `-h, --help` - Show help message
|
|
44
|
+
|
|
45
|
+
### Examples
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Open GitHub directly
|
|
49
|
+
himanshuchandola --open=github
|
|
50
|
+
|
|
51
|
+
# Skip animation
|
|
52
|
+
himanshuchandola --no-anim
|
|
53
|
+
|
|
54
|
+
# Show help
|
|
55
|
+
himanshuchandola --help
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Features
|
|
59
|
+
|
|
60
|
+
- Animated ASCII banner with color cycling
|
|
61
|
+
- Beautiful terminal card with personal information
|
|
62
|
+
- Interactive numbered menu for navigation
|
|
63
|
+
- CLI flags for direct navigation and animation control
|
|
64
|
+
- Graceful fallbacks for non-TTY environments
|
|
65
|
+
- TypeScript with strict mode
|
|
66
|
+
- Comprehensive test coverage
|
|
67
|
+
- Automated versioning and publishing with semantic-release
|
|
68
|
+
|
|
69
|
+
## Tech Stack
|
|
70
|
+
|
|
71
|
+
- **TypeScript** - Type-safe development with strict mode
|
|
72
|
+
- **tsup** - Fast TypeScript bundler
|
|
73
|
+
- **Biome** - Fast linter and formatter
|
|
74
|
+
- **Vitest** - Unit testing framework
|
|
75
|
+
- **Inquirer** - Interactive command-line prompts
|
|
76
|
+
- **Chalk** - Terminal string styling
|
|
77
|
+
- **Boxen** - Terminal boxes
|
|
78
|
+
- **Figlet** - ASCII art text
|
|
79
|
+
- **Ora** - Elegant terminal spinners
|
|
80
|
+
- **Semantic Release** - Automated versioning and npm publishing
|
|
81
|
+
|
|
82
|
+
## Development
|
|
83
|
+
|
|
84
|
+
### Prerequisites
|
|
85
|
+
|
|
86
|
+
- [Bun](https://bun.sh/) (recommended) or Node.js 18+
|
|
87
|
+
|
|
88
|
+
### Setup
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# Clone the repository
|
|
92
|
+
git clone https://github.com/himanshuchandola/himanshuchandola-cli.git
|
|
93
|
+
cd himanshuchandola-cli
|
|
94
|
+
|
|
95
|
+
# Install dependencies
|
|
96
|
+
bun install
|
|
97
|
+
|
|
98
|
+
# Run in development mode
|
|
99
|
+
bun run dev
|
|
100
|
+
|
|
101
|
+
# Build
|
|
102
|
+
bun run build
|
|
103
|
+
|
|
104
|
+
# Test
|
|
105
|
+
bun test
|
|
106
|
+
|
|
107
|
+
# Lint
|
|
108
|
+
bun run lint
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Scripts
|
|
112
|
+
|
|
113
|
+
- `bun run dev` - Watch mode with auto-rebuild
|
|
114
|
+
- `bun run build` - Build for production
|
|
115
|
+
- `bun test` - Run tests
|
|
116
|
+
- `bun run type-check` - TypeScript type checking
|
|
117
|
+
- `bun run lint` - Lint code with Biome
|
|
118
|
+
- `bun run format` - Format code with Biome
|
|
119
|
+
|
|
120
|
+
## Project Structure
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
himanshuchandola-cli/
|
|
124
|
+
├── src/
|
|
125
|
+
│ ├── index.ts # CLI entry point
|
|
126
|
+
│ ├── config/
|
|
127
|
+
│ │ └── personal.ts # Personal data configuration
|
|
128
|
+
│ ├── modules/
|
|
129
|
+
│ │ ├── banner.ts # Animated ASCII banner
|
|
130
|
+
│ │ ├── menu.ts # Interactive menu system
|
|
131
|
+
│ │ └── card.ts # Terminal card display
|
|
132
|
+
│ ├── utils/
|
|
133
|
+
│ │ ├── flags.ts # CLI flag parsing
|
|
134
|
+
│ │ ├── loader.ts # Dynamic module loading
|
|
135
|
+
│ │ └── open.ts # Safe URL opening
|
|
136
|
+
│ └── types/
|
|
137
|
+
│ └── index.ts # TypeScript type definitions
|
|
138
|
+
├── tests/ # Test files
|
|
139
|
+
├── docs/ # Documentation
|
|
140
|
+
├── .github/workflows/ # CI/CD workflows
|
|
141
|
+
└── package.json
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Documentation
|
|
145
|
+
|
|
146
|
+
- [Development Guide](./docs/DEVELOPMENT.md)
|
|
147
|
+
- [Testing Guide](./docs/TESTING.md)
|
|
148
|
+
- [Contributing Guidelines](./docs/CONTRIBUTING.md)
|
|
149
|
+
|
|
150
|
+
## Automated Publishing
|
|
151
|
+
|
|
152
|
+
This project uses semantic-release for automated versioning and npm publishing. Commits following the [Conventional Commits](https://www.conventionalcommits.org/) specification will trigger automated releases.
|
|
153
|
+
|
|
154
|
+
### Commit Message Format
|
|
155
|
+
|
|
156
|
+
- `feat(scope): message` - Minor version bump
|
|
157
|
+
- `fix(scope): message` - Patch version bump
|
|
158
|
+
- `feat(scope)!: message` - Major version bump (breaking change)
|
|
159
|
+
- `docs(scope): message` - No version bump
|
|
160
|
+
- `chore(scope): message` - No version bump
|
|
161
|
+
|
|
162
|
+
Valid scopes: cli, config, deps, ci, types, utils, banner, menu, card, release
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
This project is [MIT](./LICENSE) licensed.
|
|
167
|
+
|
|
168
|
+
## Author
|
|
169
|
+
|
|
170
|
+
**Himanshu Chandola**
|
|
171
|
+
|
|
172
|
+
- Portfolio: [himanshuchandola.dev](https://himanshuchandola.dev)
|
|
173
|
+
- GitHub: [@himanshuchandola](https://github.com/himanshuchandola)
|
|
174
|
+
- LinkedIn: [himanshuchandola](https://www.linkedin.com/in/himanshuchandola/)
|
|
175
|
+
- Twitter: [@himanshuistaken](https://x.com/himanshuistaken)
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/config/personal.ts
|
|
4
|
+
var personalConfig = {
|
|
5
|
+
name: "Himanshu Chandola",
|
|
6
|
+
role: "Software Engineer",
|
|
7
|
+
company: "Exiliensoft Consulting Services",
|
|
8
|
+
portfolio: "https://himanshuchandola.dev",
|
|
9
|
+
links: {
|
|
10
|
+
github: "https://github.com/himanshuchandola",
|
|
11
|
+
linkedin: "https://www.linkedin.com/in/himanshuchandola/",
|
|
12
|
+
peerlist: "https://peerlist.io/himanshuhere",
|
|
13
|
+
twitter: "https://x.com/himanshuistaken"
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// src/modules/banner.ts
|
|
18
|
+
import chalk from "chalk";
|
|
19
|
+
|
|
20
|
+
// src/utils/loader.ts
|
|
21
|
+
async function loadModule(moduleName) {
|
|
22
|
+
try {
|
|
23
|
+
const module = await import(moduleName);
|
|
24
|
+
return module.default || module;
|
|
25
|
+
} catch (_error) {
|
|
26
|
+
throw new Error(`Failed to load module: ${moduleName}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/modules/banner.ts
|
|
31
|
+
var bannerColors = [
|
|
32
|
+
chalk.hex("#667eea"),
|
|
33
|
+
// Purple
|
|
34
|
+
chalk.hex("#764ba2"),
|
|
35
|
+
// Deep purple
|
|
36
|
+
chalk.hex("#5b86e5"),
|
|
37
|
+
// Blue
|
|
38
|
+
chalk.hex("#36d1dc"),
|
|
39
|
+
// Cyan
|
|
40
|
+
chalk.hex("#667eea")
|
|
41
|
+
// Back to purple
|
|
42
|
+
];
|
|
43
|
+
async function animateBanner(text, cycles = 2, delay = 100) {
|
|
44
|
+
for (let i = 0; i < cycles * bannerColors.length; i++) {
|
|
45
|
+
console.clear();
|
|
46
|
+
const colorFn = bannerColors[i % bannerColors.length];
|
|
47
|
+
if (colorFn) {
|
|
48
|
+
console.log(colorFn(text));
|
|
49
|
+
}
|
|
50
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function showBanner(skipAnimation) {
|
|
54
|
+
if (skipAnimation) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const figletModule = await loadModule("figlet");
|
|
59
|
+
const bannerText = figletModule.textSync("Hello There!", {
|
|
60
|
+
font: "Slant",
|
|
61
|
+
horizontalLayout: "default",
|
|
62
|
+
verticalLayout: "default"
|
|
63
|
+
});
|
|
64
|
+
await animateBanner(bannerText, 2, 100);
|
|
65
|
+
} catch (_error) {
|
|
66
|
+
console.log(chalk.bold.hex("#667eea")("\n=== Hello There! ===\n"));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/modules/card.ts
|
|
71
|
+
import boxen from "boxen";
|
|
72
|
+
import chalk2 from "chalk";
|
|
73
|
+
function createCard() {
|
|
74
|
+
const name = chalk2.bold.hex("#667eea")(personalConfig.name);
|
|
75
|
+
const role = chalk2.hex("#a8b2d1")(`${personalConfig.role} @ ${personalConfig.company}`);
|
|
76
|
+
const tagline = chalk2.hex("#8892b0")("Building elegant solutions, one line at a time");
|
|
77
|
+
const portfolio = chalk2.hex("#64ffda")(personalConfig.portfolio);
|
|
78
|
+
const github = chalk2.hex("#64ffda")(personalConfig.links.github);
|
|
79
|
+
const linkedin = chalk2.hex("#64ffda")(personalConfig.links.linkedin);
|
|
80
|
+
const peerlist = chalk2.hex("#64ffda")(personalConfig.links.peerlist);
|
|
81
|
+
const twitter = chalk2.hex("#64ffda")(personalConfig.links.twitter);
|
|
82
|
+
const width = Math.min(80, Math.max(40, (process.stdout.columns || 80) - 10));
|
|
83
|
+
const card = boxen(
|
|
84
|
+
[
|
|
85
|
+
`${name}`,
|
|
86
|
+
`${tagline}`,
|
|
87
|
+
"",
|
|
88
|
+
`${role}`,
|
|
89
|
+
"",
|
|
90
|
+
`${chalk2.hex("#a8b2d1")("Portfolio")} ${portfolio}`,
|
|
91
|
+
`${chalk2.hex("#a8b2d1")("GitHub")} ${github}`,
|
|
92
|
+
`${chalk2.hex("#a8b2d1")("LinkedIn")} ${linkedin}`,
|
|
93
|
+
`${chalk2.hex("#a8b2d1")("Peerlist")} ${peerlist}`,
|
|
94
|
+
`${chalk2.hex("#a8b2d1")("Twitter")} ${twitter}`
|
|
95
|
+
].join("\n"),
|
|
96
|
+
{
|
|
97
|
+
padding: 1,
|
|
98
|
+
margin: 1,
|
|
99
|
+
borderStyle: "double",
|
|
100
|
+
borderColor: "#667eea",
|
|
101
|
+
width
|
|
102
|
+
}
|
|
103
|
+
);
|
|
104
|
+
return card;
|
|
105
|
+
}
|
|
106
|
+
function showCard() {
|
|
107
|
+
console.log(chalk2.hex("#8892b0")("\n Welcome to my interactive cli digital space\n"));
|
|
108
|
+
console.log(createCard());
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/utils/open.ts
|
|
112
|
+
import open from "open";
|
|
113
|
+
async function safeOpen(url) {
|
|
114
|
+
try {
|
|
115
|
+
await open(url);
|
|
116
|
+
} catch (_error) {
|
|
117
|
+
console.log(`
|
|
118
|
+
Couldn't open automatically. Here's the link:
|
|
119
|
+
${url}
|
|
120
|
+
`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// src/modules/menu.ts
|
|
125
|
+
var menuChoices = [
|
|
126
|
+
{ name: "\u2192 Visit Portfolio - Check out my work and projects", value: "portfolio" },
|
|
127
|
+
{ name: "\u2192 GitHub Profile - Explore my open source contributions", value: "github" },
|
|
128
|
+
{ name: "\u2192 LinkedIn - Let's connect professionally", value: "linkedin" },
|
|
129
|
+
{ name: "\u2192 Peerlist - View my professional timeline", value: "peerlist" },
|
|
130
|
+
{ name: "\u2192 Twitter/X - Follow for tech insights", value: "twitter" },
|
|
131
|
+
{ name: "\u2190 Exit", value: "exit" }
|
|
132
|
+
];
|
|
133
|
+
var destinationUrls = {
|
|
134
|
+
portfolio: personalConfig.portfolio,
|
|
135
|
+
github: personalConfig.links.github,
|
|
136
|
+
linkedin: personalConfig.links.linkedin,
|
|
137
|
+
peerlist: personalConfig.links.peerlist,
|
|
138
|
+
twitter: personalConfig.links.twitter
|
|
139
|
+
};
|
|
140
|
+
var loadingMessages = {
|
|
141
|
+
portfolio: "Loading portfolio...",
|
|
142
|
+
github: "Opening GitHub profile...",
|
|
143
|
+
linkedin: "Connecting to LinkedIn...",
|
|
144
|
+
peerlist: "Loading Peerlist profile...",
|
|
145
|
+
twitter: "Opening Twitter/X..."
|
|
146
|
+
};
|
|
147
|
+
async function showRedirectLoader(message, url) {
|
|
148
|
+
const ora = await loadModule("ora");
|
|
149
|
+
const cliSpinners = await loadModule("cli-spinners");
|
|
150
|
+
const loader = ora({
|
|
151
|
+
text: message,
|
|
152
|
+
spinner: cliSpinners.dots,
|
|
153
|
+
color: "magenta"
|
|
154
|
+
}).start();
|
|
155
|
+
setTimeout(async () => {
|
|
156
|
+
loader.succeed(message);
|
|
157
|
+
await safeOpen(url);
|
|
158
|
+
}, 1200);
|
|
159
|
+
}
|
|
160
|
+
async function showMenu() {
|
|
161
|
+
const inquirer = await loadModule("inquirer");
|
|
162
|
+
const ora = await loadModule("ora");
|
|
163
|
+
const cliSpinners = await loadModule("cli-spinners");
|
|
164
|
+
const menuLoader = ora({
|
|
165
|
+
text: "Initializing menu...",
|
|
166
|
+
spinner: cliSpinners.dots,
|
|
167
|
+
color: "magenta"
|
|
168
|
+
}).start();
|
|
169
|
+
setTimeout(() => {
|
|
170
|
+
menuLoader.stop();
|
|
171
|
+
const questions = [
|
|
172
|
+
{
|
|
173
|
+
type: "rawlist",
|
|
174
|
+
name: "action",
|
|
175
|
+
message: "What would you like to explore?",
|
|
176
|
+
choices: menuChoices
|
|
177
|
+
}
|
|
178
|
+
];
|
|
179
|
+
inquirer.prompt(questions).then(async (answers) => {
|
|
180
|
+
const action = answers.action;
|
|
181
|
+
if (action === "exit") {
|
|
182
|
+
console.log("\u{1F44B} Thanks for stopping by\u2014see you around!");
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const url = destinationUrls[action];
|
|
186
|
+
const message = loadingMessages[action];
|
|
187
|
+
if (url && message) {
|
|
188
|
+
await showRedirectLoader(message, url);
|
|
189
|
+
}
|
|
190
|
+
}).catch((error) => {
|
|
191
|
+
if (error.message?.includes("SIGINT")) {
|
|
192
|
+
console.log("\u270B Caught Ctrl+C. Take care and have a great day!");
|
|
193
|
+
} else {
|
|
194
|
+
console.log("Prompt closed. Until next time! \u{1F44B}");
|
|
195
|
+
}
|
|
196
|
+
process.exitCode = 0;
|
|
197
|
+
});
|
|
198
|
+
}, 900);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// src/utils/flags.ts
|
|
202
|
+
function parseFlags(argv2) {
|
|
203
|
+
const flags2 = {
|
|
204
|
+
help: false,
|
|
205
|
+
noAnim: false
|
|
206
|
+
};
|
|
207
|
+
for (const arg of argv2) {
|
|
208
|
+
if (arg === "--help" || arg === "-h") {
|
|
209
|
+
flags2.help = true;
|
|
210
|
+
} else if (arg === "--no-anim") {
|
|
211
|
+
flags2.noAnim = true;
|
|
212
|
+
} else if (arg.startsWith("--open=")) {
|
|
213
|
+
const value = arg.slice(7);
|
|
214
|
+
if (value === "portfolio" || value === "github" || value === "linkedin" || value === "peerlist" || value === "twitter") {
|
|
215
|
+
flags2.open = value;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return flags2;
|
|
220
|
+
}
|
|
221
|
+
function showHelp() {
|
|
222
|
+
console.log(`
|
|
223
|
+
Usage: himanshuchandola [options]
|
|
224
|
+
|
|
225
|
+
Options:
|
|
226
|
+
--open=portfolio|github|linkedin|peerlist|twitter Open a link directly and exit
|
|
227
|
+
--no-anim Skip banner animation
|
|
228
|
+
-h, --help Show this help
|
|
229
|
+
`);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// src/index.ts
|
|
233
|
+
var isCI = process.env.CI === "true" || process.env.CI === "1";
|
|
234
|
+
var isInteractive = process.stdin.isTTY && process.stdout.isTTY;
|
|
235
|
+
var argv = process.argv.slice(2);
|
|
236
|
+
var flags = parseFlags(argv);
|
|
237
|
+
var destinationUrls2 = {
|
|
238
|
+
portfolio: personalConfig.portfolio,
|
|
239
|
+
github: personalConfig.links.github,
|
|
240
|
+
linkedin: personalConfig.links.linkedin,
|
|
241
|
+
peerlist: personalConfig.links.peerlist,
|
|
242
|
+
twitter: personalConfig.links.twitter
|
|
243
|
+
};
|
|
244
|
+
async function main() {
|
|
245
|
+
if (flags.help) {
|
|
246
|
+
showHelp();
|
|
247
|
+
process.exit(0);
|
|
248
|
+
}
|
|
249
|
+
if (flags.open && flags.open !== "exit") {
|
|
250
|
+
const url = destinationUrls2[flags.open];
|
|
251
|
+
if (url) {
|
|
252
|
+
await safeOpen(url);
|
|
253
|
+
process.exit(0);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (!isInteractive) {
|
|
257
|
+
console.log("\nQuick links:");
|
|
258
|
+
console.log(`- Portfolio: ${personalConfig.portfolio}`);
|
|
259
|
+
console.log(`- GitHub: ${personalConfig.links.github}`);
|
|
260
|
+
console.log(`- LinkedIn: ${personalConfig.links.linkedin}`);
|
|
261
|
+
console.log(`- Peerlist: ${personalConfig.links.peerlist}`);
|
|
262
|
+
console.log(`- Twitter: ${personalConfig.links.twitter}
|
|
263
|
+
`);
|
|
264
|
+
process.exit(0);
|
|
265
|
+
}
|
|
266
|
+
process.on("SIGTERM", () => {
|
|
267
|
+
console.log("\u270B Received SIGTERM. Bye!");
|
|
268
|
+
process.exit(0);
|
|
269
|
+
});
|
|
270
|
+
process.on("SIGINT", () => {
|
|
271
|
+
console.log("\n\u270B Caught Ctrl+C. Take care and have a great day!");
|
|
272
|
+
process.exit(0);
|
|
273
|
+
});
|
|
274
|
+
try {
|
|
275
|
+
await showBanner(flags.noAnim || isCI);
|
|
276
|
+
showCard();
|
|
277
|
+
await showMenu();
|
|
278
|
+
} catch (error) {
|
|
279
|
+
if (error instanceof Error && error.message?.includes("SIGINT")) {
|
|
280
|
+
console.log("\u270B Caught Ctrl+C. Take care and have a great day!");
|
|
281
|
+
process.exitCode = 0;
|
|
282
|
+
} else {
|
|
283
|
+
console.log("Prompt closed. Until next time! \u{1F44B}");
|
|
284
|
+
process.exitCode = 0;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
main().catch((error) => {
|
|
289
|
+
console.error("An error occurred:", error);
|
|
290
|
+
process.exit(1);
|
|
291
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "himanshuchandola",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Interactive CLI portfolio for Himanshu Chandola - A delightful terminal experience",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"himanshuchandola": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"dev": "tsup --watch",
|
|
17
|
+
"build": "tsup",
|
|
18
|
+
"start": "node dist/index.js",
|
|
19
|
+
"test": "vitest run",
|
|
20
|
+
"test:watch": "vitest",
|
|
21
|
+
"test:coverage": "vitest run --coverage",
|
|
22
|
+
"type-check": "tsc --noEmit",
|
|
23
|
+
"lint": "biome check .",
|
|
24
|
+
"lint:fix": "biome check --write .",
|
|
25
|
+
"format": "biome format --write .",
|
|
26
|
+
"prepare": "husky",
|
|
27
|
+
"prepublishOnly": "npm run build"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"cli",
|
|
31
|
+
"terminal",
|
|
32
|
+
"interactive",
|
|
33
|
+
"portfolio",
|
|
34
|
+
"developer-portfolio",
|
|
35
|
+
"himanshuchandola",
|
|
36
|
+
"cli-app"
|
|
37
|
+
],
|
|
38
|
+
"author": {
|
|
39
|
+
"name": "Himanshu Chandola",
|
|
40
|
+
"url": "https://himanshuchandola.dev"
|
|
41
|
+
},
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://github.com/himanshuchandola/himanshuchandola-cli.git"
|
|
46
|
+
},
|
|
47
|
+
"bugs": {
|
|
48
|
+
"url": "https://github.com/himanshuchandola/himanshuchandola-cli/issues"
|
|
49
|
+
},
|
|
50
|
+
"homepage": "https://github.com/himanshuchandola/himanshuchandola-cli#readme",
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=18"
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"boxen": "^8.0.1",
|
|
56
|
+
"chalk": "^5.6.2",
|
|
57
|
+
"cli-spinners": "^3.3.0",
|
|
58
|
+
"figlet": "^1.9.4",
|
|
59
|
+
"inquirer": "^13.1.0",
|
|
60
|
+
"open": "^11.0.0",
|
|
61
|
+
"ora": "^9.0.0"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@biomejs/biome": "^2.3.11",
|
|
65
|
+
"@commitlint/cli": "^20.3.0",
|
|
66
|
+
"@commitlint/config-conventional": "^20.3.0",
|
|
67
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
68
|
+
"@semantic-release/git": "^10.0.1",
|
|
69
|
+
"@semantic-release/github": "^12.0.2",
|
|
70
|
+
"@types/figlet": "^1.7.0",
|
|
71
|
+
"@types/inquirer": "^9.0.9",
|
|
72
|
+
"@types/node": "^25.0.3",
|
|
73
|
+
"@vitest/coverage-v8": "^4.0.16",
|
|
74
|
+
"husky": "^9.1.7",
|
|
75
|
+
"semantic-release": "^25.0.2",
|
|
76
|
+
"tsup": "^8.5.1",
|
|
77
|
+
"typescript": "^5.9.3",
|
|
78
|
+
"vitest": "^4.0.16"
|
|
79
|
+
}
|
|
80
|
+
}
|