brignano 0.0.39 → 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.
@@ -0,0 +1,29 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ paths:
6
+ - '**/*.ts'
7
+ - '*.json'
8
+ - '.github/workflows/ci.yml'
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ matrix:
15
+ node-version: [18.x, 20.x]
16
+ steps:
17
+ - uses: actions/checkout@v6
18
+ - name: Use Node.js ${{ matrix.node-version }}
19
+ uses: actions/setup-node@v6
20
+ with:
21
+ node-version: ${{ matrix.node-version }}
22
+ - name: Install dependencies
23
+ run: npm ci
24
+ - name: Build
25
+ run: npm run build
26
+ - name: Test (non-interactive)
27
+ run: npm test
28
+ env:
29
+ CI: true
@@ -0,0 +1,32 @@
1
+ # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2
+ # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
3
+
4
+ name: Publish Package
5
+
6
+ on:
7
+ workflow_dispatch:
8
+ release:
9
+ types: [created]
10
+
11
+ jobs:
12
+ publish:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v6
16
+ - name: Use Node.js
17
+ uses: actions/setup-node@v6
18
+ with:
19
+ node-version: '20.x'
20
+ registry-url: 'https://registry.npmjs.org'
21
+ - name: Install & Build
22
+ run: |
23
+ npm ci
24
+ npm run build
25
+ - name: Test (non-interactive)
26
+ run: npm test
27
+ env:
28
+ CI: true
29
+ - name: Publish to npm
30
+ env:
31
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
32
+ run: npm publish --access public
package/dist/card.js ADDED
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env node
2
+ import boxen from 'boxen';
3
+ import chalk from 'chalk';
4
+ import inquirer from 'inquirer';
5
+ import open from 'open';
6
+ function clearConsole() {
7
+ if (typeof process.stdout.clear === 'function') {
8
+ try {
9
+ process.stdout.clear();
10
+ }
11
+ catch (e) { /* ignore */ }
12
+ }
13
+ if (process.stdout.isTTY) {
14
+ process.stdout.write('\u001b[2J\u001b[0f');
15
+ }
16
+ }
17
+ clearConsole();
18
+ const prompt = inquirer.createPromptModule();
19
+ const questions = [
20
+ {
21
+ type: 'list',
22
+ name: 'action',
23
+ message: 'What you want to do?',
24
+ choices: [
25
+ {
26
+ name: `Send me an ${chalk.green.bold('Email')}.`,
27
+ value: () => sendEmail(),
28
+ },
29
+ {
30
+ name: `View my ${chalk.magentaBright.bold('Resume')}.`,
31
+ value: () => viewResume(),
32
+ },
33
+ {
34
+ name: 'Just quit.',
35
+ value: () => {
36
+ console.log('Have a good day!\n');
37
+ },
38
+ },
39
+ ],
40
+ },
41
+ ];
42
+ function sendEmail() {
43
+ open('mailto:hi@brignano.io')
44
+ .then(() => {
45
+ console.log('\nDone, see you soon at inbox.\n');
46
+ })
47
+ .catch((err) => {
48
+ console.error('Failed to open mail client:', err && err.message ? err.message : err);
49
+ });
50
+ }
51
+ function viewResume() {
52
+ const resumeUrl = 'https://brignano.io/resume';
53
+ open(resumeUrl)
54
+ .then(() => {
55
+ console.log(`\nOpened resume: ${resumeUrl}\n`);
56
+ })
57
+ .catch((err) => {
58
+ console.error('Failed to open resume URL:', err && err.message ? err.message : err);
59
+ });
60
+ }
61
+ const data = {
62
+ name: chalk.bold.green(' Anthony Brignano'),
63
+ handle: chalk.white('@brignano'),
64
+ work: `Senior Staff Software Engineer ${chalk.white('at')} ${chalk.hex('#3A5A78').bold('The Hartford')}`,
65
+ github: chalk.gray('https://github.com/') + chalk.green('brignano'),
66
+ linkedin: chalk.gray('https://linkedin.com/in/') + chalk.blue('brignano'),
67
+ web: chalk.cyan('https://brignano.io'),
68
+ npx: chalk.red('npx') + ' ' + chalk.white('brignano'),
69
+ labelWork: chalk.white.bold(' Work:'),
70
+ labelGitHub: chalk.white.bold(' GitHub:'),
71
+ labelLinkedIn: chalk.white.bold(' LinkedIn:'),
72
+ labelWeb: chalk.white.bold(' Website:'),
73
+ labelCard: chalk.white.bold(' Card:'),
74
+ };
75
+ const me = boxen([
76
+ `${data.name}`,
77
+ '',
78
+ `${data.labelWork} ${data.work}`,
79
+ '',
80
+ `${data.labelGitHub} ${data.github}`,
81
+ `${data.labelLinkedIn} ${data.linkedin}`,
82
+ `${data.labelWeb} ${data.web}`,
83
+ '',
84
+ `${data.labelCard} ${data.npx}`,
85
+ '',
86
+ `${chalk.italic("My inbox is always open. Whether you have a")}`,
87
+ `${chalk.italic("question or just want to say hi, I will try")}`,
88
+ `${chalk.italic("my best to get back to you! :)")}`,
89
+ ].join('\n'), {
90
+ margin: 1,
91
+ float: 'center',
92
+ padding: 1,
93
+ borderStyle: 'single',
94
+ borderColor: 'green',
95
+ });
96
+ console.log(me);
97
+ const tip = [`Tip: Try ${chalk.cyanBright.bold('cmd/ctrl + click')} on the links above`, ''].join('\n');
98
+ console.log(tip);
99
+ // Simple argument parsing
100
+ const argv = process.argv.slice(2);
101
+ if (argv.includes('--help') || argv.includes('-h')) {
102
+ console.log('\nUsage: npx brignano [options]\n');
103
+ console.log('Options:');
104
+ console.log(' -h, --help Show this help');
105
+ console.log(' -v, --view Open resume in browser (https://brignano.io/resume)');
106
+ console.log(' -d, --download Deprecated: previously downloaded resume — now opens resume in browser');
107
+ console.log(' -e, --email Open mail client to email me');
108
+ console.log(' --no-prompt Show card only (non-interactive)\n');
109
+ }
110
+ else if (argv.includes('--view') || argv.includes('-v')) {
111
+ viewResume();
112
+ }
113
+ else if (argv.includes('--download') || argv.includes('-d')) {
114
+ console.warn('Warning: `--download` is deprecated and now opens the resume in your browser.');
115
+ viewResume();
116
+ }
117
+ else if (argv.includes('--email') || argv.includes('-e')) {
118
+ sendEmail();
119
+ }
120
+ else if (argv.includes('--no-prompt') || argv.includes('--quiet')) {
121
+ console.log('\nExiting in non-interactive mode (--no-prompt).');
122
+ }
123
+ else {
124
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
125
+ prompt(questions).then((answer) => answer.action());
126
+ }
package/package.json CHANGED
@@ -1,33 +1,43 @@
1
1
  {
2
2
  "name": "brignano",
3
- "version": "0.0.39",
4
- "main": "card.js",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "main": "dist/card.js",
6
+ "engines": {
7
+ "node": ">=18"
8
+ },
5
9
  "bin": {
6
- "anthony": "card.js"
10
+ "brignano": "dist/card.js"
7
11
  },
8
12
  "scripts": {
9
- "test": "node card.js"
13
+ "build": "tsc",
14
+ "dev": "ts-node --esm src/card.ts",
15
+ "start": "node dist/card.js",
16
+ "test": "node dist/card.js --no-prompt",
17
+ "prepare": "npm run build"
10
18
  },
11
19
  "repository": {
12
20
  "type": "git",
13
- "url": "git+https://github.com/brignano/npx_card.git"
21
+ "url": "git+https://github.com/brignano/npx-brignano.git"
14
22
  },
15
23
  "author": "Anthony Brignano <anthonybrignano@gmail.com> (https://brignano.io/)",
16
24
  "license": "ISC",
17
25
  "bugs": {
18
- "url": "https://github.com/brignano/npx_card/issues"
26
+ "url": "https://github.com/brignano/npx-brignano/issues"
19
27
  },
20
- "homepage": "https://github.com/brignano/npx_card#readme",
28
+ "homepage": "https://github.com/brignano/npx-brignano#readme",
21
29
  "keywords": [],
22
30
  "description": "A personal card for Anthony Brignano (@brignano)",
23
31
  "dependencies": {
24
- "boxen": "^4.2.0",
25
- "chalk": "^4.1.0",
26
- "clear": "^0.1.0",
27
- "cli-spinners": "^2.5.0",
28
- "inquirer": "^7.3.3",
29
- "open": "^7.3.0",
30
- "ora": "^5.1.0",
31
- "request": "^2.88.2"
32
+ "boxen": "^6.0.0",
33
+ "chalk": "^5.2.0",
34
+ "inquirer": "^9.2.7",
35
+ "open": "^8.4.0"
36
+ },
37
+ "devDependencies": {
38
+ "ts-node": "^10.9.1",
39
+ "typescript": "^5.1.6",
40
+ "@types/node": "^20.5.1",
41
+ "@types/inquirer": "^9.0.3"
32
42
  }
33
43
  }
package/readme.md CHANGED
@@ -9,6 +9,58 @@ npx brignano
9
9
 
10
10
  ### DEMO
11
11
 
12
+ # npx-brignano <a href="#"><img src="https://img.shields.io/badge/-npx%20brignano-white?style=flat-square&logo=npm&logoColor=grey" align="right" alt="npm Badge"></img></a>
13
+
14
+ An interactive terminal business card for Anthony Brignano. Run it with `npx` to view a styled card in your terminal and choose quick actions like emailing or downloading a resume.
15
+
16
+ Quick start
17
+
18
+ ```bash
19
+ npx brignano
20
+ ```
21
+
22
+ Demo
23
+
12
24
  ![](https://raw.githubusercontent.com/brignano/npx_brignano/main/demo.gif)
13
25
 
14
- > _100% credit to [anmol098/npx_card](https://github.com/anmol098/npx_card)_
26
+ What it does
27
+
28
+ - Renders a boxed, colored business card in the terminal using `boxen` and `chalk`.
29
+ - Presents a small interactive menu (via `inquirer`) with actions:
30
+ - Send an email (opens your mail client with `mailto:`)
31
+ - Download the resume (fetches a resume HTML and opens it locally)
32
+ - Quit
33
+
34
+ Files
35
+
36
+ - `card.js` — main CLI script: prints the card and runs the interactive menu.
37
+ - `package.json` — project metadata and `bin` entry used by `npx`.
38
+
39
+ Usage
40
+
41
+ - Run directly with `npx brignano` (no install required).
42
+ - Or clone and run locally:
43
+
44
+ ```bash
45
+ git clone https://github.com/brignano/npx_brignano.git
46
+ cd npx-brignano
47
+ npm install
48
+ node card.js
49
+ ```
50
+
51
+ Prerequisites
52
+
53
+ - Node.js (tested with Node 14+). `npx` is included with npm.
54
+
55
+ Notes
56
+
57
+ - When you choose "Download my Resume" the script requests the resume URL and writes `anthony-brignano.html` into the current working directory, then opens it.
58
+ - Links printed in the card may be cmd/ctrl+clickable in supported terminals.
59
+
60
+ Credits
61
+
62
+ This project is inspired by and credited to [anmol098/npx_card](https://github.com/anmol098/npx_card).
63
+
64
+ License
65
+
66
+ See `package.json` for license information.
package/src/card.ts ADDED
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env node
2
+
3
+ import boxen from 'boxen';
4
+ import chalk from 'chalk';
5
+ import inquirer from 'inquirer';
6
+ import open from 'open';
7
+
8
+ function clearConsole(): void {
9
+ if (typeof (process.stdout as any).clear === 'function') {
10
+ try { (process.stdout as any).clear(); } catch (e) { /* ignore */ }
11
+ }
12
+ if (process.stdout.isTTY) {
13
+ process.stdout.write('\u001b[2J\u001b[0f');
14
+ }
15
+ }
16
+
17
+ clearConsole();
18
+
19
+ const prompt = inquirer.createPromptModule();
20
+
21
+ const questions = [
22
+ {
23
+ type: 'list',
24
+ name: 'action',
25
+ message: 'What you want to do?',
26
+ choices: [
27
+ {
28
+ name: `Send me an ${chalk.green.bold('Email')}.`,
29
+ value: () => sendEmail(),
30
+ },
31
+ {
32
+ name: `View my ${chalk.magentaBright.bold('Resume')}.`,
33
+ value: () => viewResume(),
34
+ },
35
+ {
36
+ name: 'Just quit.',
37
+ value: () => {
38
+ console.log('Have a good day!\n');
39
+ },
40
+ },
41
+ ],
42
+ },
43
+ ];
44
+
45
+ function sendEmail(): void {
46
+ open('mailto:hi@brignano.io')
47
+ .then(() => {
48
+ console.log('\nDone, see you soon at inbox.\n');
49
+ })
50
+ .catch((err: any) => {
51
+ console.error('Failed to open mail client:', err && err.message ? err.message : err);
52
+ });
53
+ }
54
+
55
+ function viewResume(): void {
56
+ const resumeUrl = 'https://brignano.io/resume';
57
+ open(resumeUrl)
58
+ .then(() => {
59
+ console.log(`\nOpened resume: ${resumeUrl}\n`);
60
+ })
61
+ .catch((err: any) => {
62
+ console.error('Failed to open resume URL:', err && err.message ? err.message : err);
63
+ });
64
+ }
65
+
66
+ const data = {
67
+ name: chalk.bold.green(' Anthony Brignano'),
68
+ handle: chalk.white('@brignano'),
69
+ work: `Senior Staff Software Engineer ${chalk.white('at')} ${chalk.hex('#3A5A78').bold('The Hartford')}`,
70
+ github: chalk.gray('https://github.com/') + chalk.green('brignano'),
71
+ linkedin: chalk.gray('https://linkedin.com/in/') + chalk.blue('brignano'),
72
+ web: chalk.cyan('https://brignano.io'),
73
+ npx: chalk.red('npx') + ' ' + chalk.white('brignano'),
74
+
75
+ labelWork: chalk.white.bold(' Work:'),
76
+ labelGitHub: chalk.white.bold(' GitHub:'),
77
+ labelLinkedIn: chalk.white.bold(' LinkedIn:'),
78
+ labelWeb: chalk.white.bold(' Website:'),
79
+ labelCard: chalk.white.bold(' Card:'),
80
+ };
81
+
82
+ const me = boxen(
83
+ [
84
+ `${data.name}`,
85
+ '',
86
+ `${data.labelWork} ${data.work}`,
87
+ '',
88
+ `${data.labelGitHub} ${data.github}`,
89
+ `${data.labelLinkedIn} ${data.linkedin}`,
90
+ `${data.labelWeb} ${data.web}`,
91
+ '',
92
+ `${data.labelCard} ${data.npx}`,
93
+ '',
94
+ `${chalk.italic("My inbox is always open. Whether you have a")}`,
95
+ `${chalk.italic("question or just want to say hi, I will try")}`,
96
+ `${chalk.italic("my best to get back to you! :)")}`,
97
+ ].join('\n'),
98
+ {
99
+ margin: 1,
100
+ float: 'center' as const,
101
+ padding: 1,
102
+ borderStyle: 'single',
103
+ borderColor: 'green',
104
+ }
105
+ );
106
+
107
+ console.log(me);
108
+ const tip = [`Tip: Try ${chalk.cyanBright.bold('cmd/ctrl + click')} on the links above`, ''].join('\n');
109
+ console.log(tip);
110
+
111
+ // Simple argument parsing
112
+ const argv = process.argv.slice(2);
113
+ if (argv.includes('--help') || argv.includes('-h')) {
114
+ console.log('\nUsage: npx brignano [options]\n');
115
+ console.log('Options:');
116
+ console.log(' -h, --help Show this help');
117
+ console.log(' -v, --view Open resume in browser (https://brignano.io/resume)');
118
+ console.log(' -d, --download Deprecated: previously downloaded resume — now opens resume in browser');
119
+ console.log(' -e, --email Open mail client to email me');
120
+ console.log(' --no-prompt Show card only (non-interactive)\n');
121
+ } else if (argv.includes('--view') || argv.includes('-v')) {
122
+ viewResume();
123
+ } else if (argv.includes('--download') || argv.includes('-d')) {
124
+ console.warn('Warning: `--download` is deprecated and now opens the resume in your browser.');
125
+ viewResume();
126
+ } else if (argv.includes('--email') || argv.includes('-e')) {
127
+ sendEmail();
128
+ } else if (argv.includes('--no-prompt') || argv.includes('--quiet')) {
129
+ console.log('\nExiting in non-interactive mode (--no-prompt).');
130
+ } else {
131
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
132
+ prompt(questions as any).then((answer: any) => answer.action());
133
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ES2020",
5
+ "declaration": false,
6
+ "outDir": "dist",
7
+ "rootDir": "src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "moduleResolution": "node",
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true
13
+ },
14
+ "include": ["src/**/*"]
15
+ }
package/card.js DELETED
@@ -1,118 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- 'use strict'
4
-
5
- const boxen = require("boxen");
6
- const chalk = require("chalk");
7
- const inquirer = require("inquirer");
8
- const clear = require("clear");
9
- const open = require("open");
10
- const fs = require('fs');
11
- const request = require('request');
12
- const path = require('path');
13
- const ora = require('ora');
14
- const cliSpinners = require('cli-spinners');
15
- clear();
16
-
17
- const prompt = inquirer.createPromptModule();
18
-
19
- const questions = [
20
- {
21
- type: "list",
22
- name: "action",
23
- message: "What you want to do?",
24
- choices: [
25
- {
26
- name: `Send me an ${chalk.green.bold("Email")}.`,
27
- value: () => {
28
- open("mailto:hi@brignano.io");
29
- console.log("\nDone, see you soon at inbox.\n");
30
- }
31
- },
32
- {
33
- name: `Download my ${chalk.magentaBright.bold("Resume")}.`,
34
- value: () => {
35
- // cliSpinners.dots;
36
- const loader = ora({
37
- text: ' Downloading Resume',
38
- spinner: cliSpinners.material,
39
- }).start();
40
- let pipe = request('https://brignano-io.vercel.app/api/resume').pipe(fs.createWriteStream('./anthony-brignano.html'));
41
- pipe.on("finish", function () {
42
- let downloadPath = path.join(process.cwd(), 'anthony-brignano.html')
43
- console.log(`\nResume Downloaded at ${downloadPath} \n`);
44
- open(downloadPath)
45
- loader.stop();
46
- });
47
- }
48
- },
49
- {
50
- name: "Just quit.",
51
- value: () => {
52
- console.log("Have a good day!\n");
53
- }
54
- }
55
- ]
56
- }
57
- ];
58
-
59
- const data = {
60
- name: chalk.bold.green(" Anthony Brignano"),
61
- handle: chalk.white("@brignano"),
62
- work: `${chalk.white("Sr. Software Engineer at")} ${chalk
63
- .hex("#3A5A78")
64
- .bold("The Hartford")}`,
65
- github: chalk.gray("https://github.com/") + chalk.green("brignano"),
66
- linkedin: chalk.gray("https://linkedin.com/in/") + chalk.blue("brignano"),
67
- twitter: chalk.gray("https://twitter.com/") + chalk.cyan("brignano_"),
68
- web: chalk.cyan("https://brignano.io"),
69
- npx: chalk.red("npx") + " " + chalk.white("brignano"),
70
-
71
- labelWork: chalk.white.bold(" Work:"),
72
- labelGitHub: chalk.white.bold(" GitHub:"),
73
- labelLinkedIn: chalk.white.bold(" LinkedIn:"),
74
- labelTwitter: chalk.white.bold(" Twitter:"),
75
- labelWeb: chalk.white.bold(" Web:"),
76
- labelCard: chalk.white.bold(" Card:")
77
- };
78
-
79
- const me = boxen(
80
- [
81
- `${data.name}`,
82
- ``,
83
- `${data.labelWork} ${data.work}`,
84
- ``,
85
- `${data.labelGitHub} ${data.github}`,
86
- `${data.labelLinkedIn} ${data.linkedin}`,
87
- `${data.labelTwitter} ${data.twitter}`,
88
- `${data.labelWeb} ${data.web}`,
89
- ``,
90
- `${data.labelCard} ${data.npx}`,
91
- ``,
92
- `${chalk.italic("My inbox is always open. Whether you have a")}`,
93
- `${chalk.italic(
94
- "question or just want to say hi, I will try"
95
- )}`,
96
- `${chalk.italic(
97
- "my best to get back to you! :)"
98
- )}`
99
- ].join("\n"),
100
- {
101
- margin: 1,
102
- float: 'center',
103
- padding: 1,
104
- borderStyle: "single",
105
- borderColor: "green"
106
- }
107
- );
108
-
109
- console.log(me);
110
- const tip = [
111
- `Tip: Try ${chalk.cyanBright.bold(
112
- "cmd/ctrl + click"
113
- )} on the links above`,
114
- '',
115
- ].join("\n");
116
- console.log(tip);
117
-
118
- prompt(questions).then(answer => answer.action());