init
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
dist
|
||||
15
Readme.md
Normal file
15
Readme.md
Normal file
@@ -0,0 +1,15 @@
|
||||
## CLI Example
|
||||
|
||||
A simple example of making gorgeous CLI's with Typescript, Commander.js, and ora.
|
||||
|
||||
Read this blog post for more information.
|
||||
|
||||

|
||||
|
||||
## How to run this
|
||||
|
||||
`npm install`
|
||||
`npm build`
|
||||
`npm link`
|
||||
|
||||
You should now have `terribledev` as a command on your path
|
||||
27
index.ts
Normal file
27
index.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { Command } from 'commander'
|
||||
import { spinnerError, stopSpinner } from './spinner';
|
||||
import { widgets } from './widgets';
|
||||
const program = new Command('Our New CLI');
|
||||
program.option('-v, --verbose', 'verbose logging');
|
||||
program.version('0.0.1');
|
||||
program.addHelpCommand()
|
||||
program.addCommand(widgets);
|
||||
|
||||
async function main() {
|
||||
await program.parseAsync();
|
||||
|
||||
}
|
||||
console.log() // log a new line so there is a nice space
|
||||
main();
|
||||
|
||||
process.on('unhandledRejection', function (err: Error) {
|
||||
const debug = program.opts().verbose;
|
||||
if(debug) {
|
||||
console.error(err.stack);
|
||||
}
|
||||
spinnerError()
|
||||
stopSpinner()
|
||||
program.error('', { exitCode: 1 });
|
||||
})
|
||||
1011
package-lock.json
generated
Normal file
1011
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
22
package.json
Normal file
22
package.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "terribledev",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc --noEmit ./index.ts && esbuild index.ts --bundle --platform=node --format=cjs --outfile=dist/index.js",
|
||||
"build:notype": "esbuild index.ts --bundle --platform=node --format=cjs --outfile=dist/index.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@types/node": "^18.0.3",
|
||||
"commander": "^9.3.0",
|
||||
"esbuild": "^0.14.48",
|
||||
"ora": "^6.1.2"
|
||||
},
|
||||
"bin": {
|
||||
"terribledev": "./dist/index.js"
|
||||
}
|
||||
}
|
||||
32
spinner.ts
Normal file
32
spinner.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import ora from 'ora';
|
||||
|
||||
const spinner = ora({
|
||||
spinner: 'dots',
|
||||
})
|
||||
|
||||
export const updateSpinnerText = (message: string) => {
|
||||
if(spinner.isSpinning) {
|
||||
spinner.text = message
|
||||
return;
|
||||
}
|
||||
spinner.start(message)
|
||||
}
|
||||
|
||||
export const stopSpinner = () => {
|
||||
if(spinner.isSpinning) {
|
||||
spinner.stop()
|
||||
}
|
||||
}
|
||||
export const spinnerError = (message?: string) => {
|
||||
if(spinner.isSpinning) {
|
||||
spinner.fail(message)
|
||||
}
|
||||
}
|
||||
export const spinnerSuccess = (message?: string) => {
|
||||
if(spinner.isSpinning) {
|
||||
spinner.succeed(message)
|
||||
}
|
||||
}
|
||||
export const spinnerInfo = (message: string) => {
|
||||
spinner.info(message)
|
||||
}
|
||||
34
widgets.ts
Normal file
34
widgets.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { Command } from "commander";
|
||||
import { spinnerError, spinnerInfo, spinnerSuccess, updateSpinnerText } from "./spinner";
|
||||
|
||||
export const widgets = new Command("widgets");
|
||||
|
||||
widgets.command("list").action(async () => {
|
||||
updateSpinnerText("Processing ");
|
||||
// do work
|
||||
await new Promise(resolve => setTimeout(resolve, 1000)); // emulate work
|
||||
spinnerSuccess()
|
||||
console.table([{ id: 1, name: "Tommy" }, { id: 2, name: "Bob" }]);
|
||||
})
|
||||
|
||||
widgets.command("get")
|
||||
.argument("widget id <id>", "the id of the widget")
|
||||
.option("-f, --format <format>", "the format of the widget")
|
||||
.action(async (id, options) => {
|
||||
updateSpinnerText("Getting widget " + id);
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
spinnerSuccess()
|
||||
console.table({ id: 1, name: "Tommy" })
|
||||
})
|
||||
|
||||
widgets.command("fail").action(async () => {
|
||||
updateSpinnerText("Processing a handled failure ");
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
spinnerError()
|
||||
})
|
||||
|
||||
widgets.command("unhandled-error").action(async () => {
|
||||
updateSpinnerText("Processing an unhandled failure ");
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
throw new Error("Unhandled error");
|
||||
})
|
||||
Reference in New Issue
Block a user