Skip to content

Commit 9ac8f8d

Browse files
committed
feat: migrated to npx pulkitxm
1 parent 84d1a7f commit 9ac8f8d

File tree

6 files changed

+1845
-52
lines changed

6 files changed

+1845
-52
lines changed

README.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
[![pulkitxm](https://utfs.io/f/fAg0SbN5tYMawKGr0YTf0H1JXoMj5DTdB38FOVscE2yeUhwa)](https://www.holopin.io/@pulkitxm)
22

33
<br/>
4+
5+
<a href="https://www.npmjs.com/package/pulkitxm">
6+
<img src="https://img.shields.io/badge/Terminal-npx%20pulkitxm-%234CAF50?style=for-the-badge&logo=windowsterminal&logoColor=white" alt="npx pulkitxm" />
7+
</a>
48

59
My name is Pulkit. I'm a undergraduate from 🇮🇳 ![wakatime](https://visitor-badge.laobi.icu/badge?page_id=pulkitxm.pulkitxm&)
610

@@ -19,12 +23,12 @@ My name is Pulkit. I'm a undergraduate from 🇮🇳 ![wakatime](https://visitor
1923
### :pencil: [Latest blog posts](https://blogs.pulkitxm.com)
2024

2125
<!--START_SECTION:blog-posts-->
22-
| Title | Date | Image |
23-
| ----- | ---- | ----- |
24-
| [Building a Contact Form in Next.js with Resend Email Integration](https://blogs.pulkitxm.com/emails-with-resend) | Dec 13, 2024 | [<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734081142688/30bd0035-ff2e-4a94-a3f3-5549231565e4.jpeg?w=300&h=157&fit=crop&crop=entropy&auto=compress,format&format=webp" width="200px" />](https://blogs.pulkitxm.com/emails-with-resend)
25-
| [Boost Your Link Previews: Implementing Open Graph Images in Next.js](https://blogs.pulkitxm.com/open-graph-images-in-nextjs) | Nov 15, 2024 | [<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731658433998/70bdbb5d-1123-478d-b35a-316169ce5615.png?w=300&h=157&fit=crop&crop=entropy&auto=compress,format&format=webp" width="200px" />](https://blogs.pulkitxm.com/open-graph-images-in-nextjs)
26-
| [Setting Up Prisma ORM with PostgreSQL](https://blogs.pulkitxm.com/setting-up-prisma-orm-with-postgresql) | Aug 17, 2024 | [<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734016058521/1d653d70-3204-40fa-9272-58298cd8e663.webp?w=300&h=157&fit=crop&crop=entropy&auto=compress,format&format=webp" width="200px" />](https://blogs.pulkitxm.com/setting-up-prisma-orm-with-postgresql)
27-
| [Adding Animated Image Zoom to Your React App with PhotoSwipe](https://blogs.pulkitxm.com/react-image-gallery-with-photoswipe) | Aug 12, 2024 | [<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1723050714944/ecb7f6c0-7151-4ce1-9c57-08c47e2a6625.jpeg?w=300&h=157&fit=crop&crop=entropy&auto=compress,format&format=webp" width="200px" />](https://blogs.pulkitxm.com/react-image-gallery-with-photoswipe)
26+
| Title | Date | Image |
27+
| ------------------------------------------------------------------------------------------------------------------------------ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
28+
| [Building a Contact Form in Next.js with Resend Email Integration](https://blogs.pulkitxm.com/emails-with-resend) | Dec 13, 2024 | [<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734081142688/30bd0035-ff2e-4a94-a3f3-5549231565e4.jpeg?w=300&h=157&fit=crop&crop=entropy&auto=compress,format&format=webp" width="200px" />](https://blogs.pulkitxm.com/emails-with-resend) |
29+
| [Boost Your Link Previews: Implementing Open Graph Images in Next.js](https://blogs.pulkitxm.com/open-graph-images-in-nextjs) | Nov 15, 2024 | [<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731658433998/70bdbb5d-1123-478d-b35a-316169ce5615.png?w=300&h=157&fit=crop&crop=entropy&auto=compress,format&format=webp" width="200px" />](https://blogs.pulkitxm.com/open-graph-images-in-nextjs) |
30+
| [Setting Up Prisma ORM with PostgreSQL](https://blogs.pulkitxm.com/setting-up-prisma-orm-with-postgresql) | Aug 17, 2024 | [<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734016058521/1d653d70-3204-40fa-9272-58298cd8e663.webp?w=300&h=157&fit=crop&crop=entropy&auto=compress,format&format=webp" width="200px" />](https://blogs.pulkitxm.com/setting-up-prisma-orm-with-postgresql) |
31+
| [Adding Animated Image Zoom to Your React App with PhotoSwipe](https://blogs.pulkitxm.com/react-image-gallery-with-photoswipe) | Aug 12, 2024 | [<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1723050714944/ecb7f6c0-7151-4ce1-9c57-08c47e2a6625.jpeg?w=300&h=157&fit=crop&crop=entropy&auto=compress,format&format=webp" width="200px" />](https://blogs.pulkitxm.com/react-image-gallery-with-photoswipe) |
2832
<!--END_SECTION:blog-posts-->
2933

3034
---

cli/Readme.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Simple PulkitXM CLI Setup Guide
2+
3+
This guide explains how to set up and use the simple CLI tool.
4+
5+
## Quick Setup
6+
7+
1. Create a directory for your CLI:
8+
```bash
9+
mkdir pulkitxm-cli
10+
cd pulkitxm-cli
11+
```
12+
13+
2. Create the two required files:
14+
- Save the CLI code as `cli.js`
15+
- Save the package.json content as `package.json`
16+
17+
3. Make the CLI script executable (on Linux/Mac):
18+
```bash
19+
chmod +x cli.js
20+
```
21+
22+
4. Test the CLI locally:
23+
```bash
24+
node cli.js
25+
```
26+
27+
## Testing with npx
28+
29+
To test as if it were installed with npx:
30+
31+
1. Link the package locally:
32+
```bash
33+
npm link
34+
```
35+
36+
2. Run the command:
37+
```bash
38+
pulkitxm
39+
```
40+
41+
3. When you're done testing, unlink:
42+
```bash
43+
npm unlink pulkitxm
44+
```
45+
46+
## Publishing
47+
48+
When you're ready to publish:
49+
50+
```bash
51+
npm login
52+
npm publish
53+
```
54+
55+
After publishing, users can run:
56+
```bash
57+
npx pulkitxm
58+
```
59+
60+
## Notes
61+
62+
- No external dependencies are used in this version
63+
- Only Node.js built-in modules are used:
64+
- `https` for API requests
65+
- `readline` for interactive CLI
66+
- The CLI will display all profile information in plain text
67+
- Simple error handling is included
68+
69+
This minimal approach avoids any potential package compatibility issues and makes the CLI extremely portable.

cli/cli.js

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
#!/usr/bin/env node
2+
3+
const https = require("https");
4+
const readline = require("readline");
5+
6+
const rl = readline.createInterface({
7+
input: process.stdin,
8+
output: process.stdout,
9+
});
10+
11+
const API_URL = "https://pulkitxm.com/api/profile";
12+
13+
console.clear();
14+
15+
console.log("\n=== Pulkit's Profile ===");
16+
console.log("Data source: " + API_URL + "\n");
17+
18+
function formatDate(dateString) {
19+
if (!dateString) return "Present";
20+
const date = new Date(dateString);
21+
return date.toLocaleDateString("en-US", { year: "numeric", month: "short" });
22+
}
23+
24+
function fetchProfileData() {
25+
return new Promise((resolve, reject) => {
26+
console.log("Fetching profile data...");
27+
28+
https
29+
.get(API_URL, (res) => {
30+
let data = "";
31+
32+
res.on("data", (chunk) => {
33+
data += chunk;
34+
});
35+
36+
res.on("end", () => {
37+
try {
38+
const profileData = JSON.parse(data);
39+
console.log("Data loaded successfully!\n");
40+
resolve(profileData);
41+
} catch (error) {
42+
reject(new Error("Error parsing profile data"));
43+
}
44+
});
45+
})
46+
.on("error", (err) => {
47+
reject(new Error(`Error fetching profile data: ${err.message}`));
48+
});
49+
});
50+
}
51+
52+
function displayBasicInfo(profile) {
53+
console.clear();
54+
console.log("\n=== Basic Information ===\n");
55+
console.log(`Name: ${profile.name}`);
56+
console.log(`Title: ${profile.caption}`);
57+
console.log(`Email: ${profile.email}`);
58+
console.log(`\nLinks:`);
59+
console.log(`Resume: ${profile.resumeLink}`);
60+
console.log(`GitHub: ${profile.links.github}`);
61+
console.log(`LinkedIn: ${profile.links.linkedin}`);
62+
console.log(`Twitter: ${profile.links.twitter}`);
63+
if (profile.links.blogs) {
64+
console.log(`Blog: ${profile.links.blogs}`);
65+
}
66+
return showMainMenu(profile);
67+
}
68+
69+
function displayExperience(profile) {
70+
console.clear();
71+
console.log("\n=== Experience ===\n");
72+
73+
profile.experience.forEach((exp, index) => {
74+
console.log(`${index + 1}. ${exp.position} at ${exp.companyName}`);
75+
console.log(
76+
` ${formatDate(exp.startDate)} - ${formatDate(exp.endDate)} | ${
77+
exp.type
78+
} | ${exp.location}`
79+
);
80+
if (exp.desc) {
81+
console.log(` ${exp.desc}`);
82+
}
83+
console.log("");
84+
});
85+
86+
return showMainMenu(profile);
87+
}
88+
89+
function displayProjects(profile) {
90+
console.clear();
91+
console.log("\n=== Projects ===\n");
92+
93+
profile.projects.forEach((project, index) => {
94+
console.log(`${index + 1}. ${project.name}`);
95+
console.log(` Description: ${project.tagline || "No description"}`);
96+
console.log(` URL: ${project.url}`);
97+
console.log("");
98+
});
99+
100+
return showMainMenu(profile);
101+
}
102+
103+
function displaySkills(profile) {
104+
console.clear();
105+
console.log("\n=== Skills ===\n");
106+
107+
Object.entries(profile.skills).forEach(([category, skillList]) => {
108+
console.log(`${category}:`);
109+
console.log(` ${skillList.join(", ")}`);
110+
console.log("");
111+
});
112+
113+
return showMainMenu(profile);
114+
}
115+
116+
function displayCertifications(profile) {
117+
console.clear();
118+
console.log("\n=== Certifications ===\n");
119+
120+
profile.certifications.forEach((cert, index) => {
121+
console.log(`${index + 1}. ${cert.name}`);
122+
console.log(
123+
` Issued by: ${cert.issuedBy.name} (${formatDate(cert.issuedAt)})`
124+
);
125+
console.log(` Verify: ${cert.verifyLink}`);
126+
console.log("");
127+
});
128+
129+
return showMainMenu(profile);
130+
}
131+
132+
function displayContributions(profile) {
133+
console.clear();
134+
console.log("\n=== GitHub Contributions ===\n");
135+
136+
const recentYears = profile.contributions.slice(-2);
137+
138+
recentYears.forEach((yearData) => {
139+
console.log(
140+
`${yearData.year}: ${yearData.contributions.totalContributions} contributions`
141+
);
142+
143+
const months = yearData.contributions.months;
144+
months.forEach((month) => {
145+
const totalInMonth = month.days.reduce(
146+
(sum, day) => sum + day.contributionCount,
147+
0
148+
);
149+
if (totalInMonth > 0) {
150+
const barLength = Math.min(Math.floor(totalInMonth / 5), 30);
151+
console.log(
152+
` ${month.month}: ${"#".repeat(barLength)} (${totalInMonth})`
153+
);
154+
}
155+
});
156+
console.log("");
157+
});
158+
159+
return showMainMenu(profile);
160+
}
161+
162+
function showMainMenu(profile) {
163+
console.log("\nWhat would you like to see?");
164+
console.log("1. Basic Information");
165+
console.log("2. Experience");
166+
console.log("3. Projects");
167+
console.log("4. Skills");
168+
console.log("5. Certifications");
169+
console.log("6. GitHub Contributions");
170+
console.log("7. Exit");
171+
172+
rl.question("\nEnter your choice (1-7): ", (choice) => {
173+
switch (choice) {
174+
case "1":
175+
return displayBasicInfo(profile);
176+
case "2":
177+
return displayExperience(profile);
178+
case "3":
179+
return displayProjects(profile);
180+
case "4":
181+
return displaySkills(profile);
182+
case "5":
183+
return displayCertifications(profile);
184+
case "6":
185+
return displayContributions(profile);
186+
case "7":
187+
console.log("\nThanks for checking out my profile! Goodbye!");
188+
rl.close();
189+
return;
190+
default:
191+
console.log("\nInvalid choice. Please enter a number between 1 and 7.");
192+
return showMainMenu(profile);
193+
}
194+
});
195+
}
196+
197+
async function main() {
198+
try {
199+
const profile = await fetchProfileData();
200+
showMainMenu(profile);
201+
} catch (error) {
202+
console.error(`\nError: ${error.message}`);
203+
rl.close();
204+
}
205+
}
206+
207+
main();

0 commit comments

Comments
 (0)