Skip to content

About

TypeScript Commands

Resources

Stars

1 star

Watchers

1 watching

Forks

Repository files navigation

ts-commands - Readme

Installation

  1. npm i ts-commands

Usage

Creating Commands

Create a command file:

src/bin/greet-command.ts

import { Command, OptionType, ParsedArguments } from 'ts-commands';

interface Args extends ParsedArguments {
	fname: string;
	lname: string;
	informal?: boolean;
}

export class GreetCommand extends Command {
	override key = 'greet';
	override description = 'say hello';

	override positional = [
		{
			key: 'fname',
			type: OptionType.string,
			description: 'first name',
			default: 'Tom',
		},
		{
			key: 'lname',
			type: OptionType.string,
			description: 'last name',
			default: 'Tester',
		},
	];

	override options = [
		{
			key: 'informal',
			type: OptionType.boolean,
			default: false,
			description: 'Informal?',
		},
	];

	override async handle(args: Args) {
		const greeting = args.informal ? 'yo' : 'hello';

		console.log(`${greeting} ${args.fname} ${args.lname}`);
	}
}

Registering Commands

Option 1 - Singular Command

If your app only needs one command (e.g. it only does one thing), you can use a singular style CLI:

src/bin/index.ts

import { CommandRunner } from 'ts-commands';
import { GreetCommand } from '../commands/greet';

new CommandRunner(new GreetCommand()).run();

Option 2 - Dispatched Commands

Dispatched commands are useful for when you have multiple sub-commands in your CLI, such as migration:run, migration:generate, etc.

Create an index file to register your command(s):

src/bin/index.ts

import { CommandDispatcher } from 'ts-commands';
import { FarewellCommand } from './farewell';
import { GreetCommand } from './greet';

new CommandDispatcher({
	commands: [FarewellCommand, GreetCommand],
}).run();

Option 3 - Automatically Register all Commands in a Folder

Use ts-import-ts to load all Commands in a directory. Note, you will need to change each Command to the default export of the module, e.g. export default class MyCommand.... Please read the readme of that package for proper usage.

First, install with npm i ts-import-ts

Create your dispatcher:

src/bin/index.ts

import { tsimportDirectory } from 'ts-import-ts';
import { Command, CommandDispatcher } from 'ts-commands';

new CommandDispatcher({
	commands: tsimportDirectory<typeof Command>('scripts'),
}).run();

Prompting the User

You can use the this.ask() method to prompt the user for input and await their response:

export class AskCommand extends Command {
	override key = 'ask';
	override description = 'ask a question and get an answer';

	override async handle(args: ParsedArguments) {
		const answer = await this.ask('What is your name? ');
		console.log(`Your name is ${answer}`);
	}
}

Loading Indicator

Use LoadingIndicator from ts-commands/loading-indicator to show a spinner while an asynchronous operation runs:

import { LoadingIndicator } from 'ts-commands/loading-indicator';

const indicator = new LoadingIndicator();
await indicator.runWithIndicator(
	'Loading...',
	async () => {
		await new Promise(resolve => setTimeout(resolve, 1000));
	}
);

The message is required and must be provided as the first argument.

The spinner redraws on the current terminal line and stops automatically on success or failure. Redirected (non-TTY) output prints messages on separate lines without animation. updateMessage() changes the message for subsequent frames.

Set clearOnStop: false to keep the final frame followed by a newline, or pass an explicit boolean to stop() to override that option.

Create Additional Commands

  1. Repeat "Creating Commands" section for each command
  2. Add each command in the commands of CommandDispatcher

About

TypeScript Commands

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages