Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/kohheepeace/hello-ts-cli


https://github.com/kohheepeace/hello-ts-cli

chalk node-cli typescript yarn

Last synced: about 1 month ago
JSON representation

Awesome Lists containing this project

README

        

# hello-ts-cli tutorial
This github repository explains how to create a node cli tool with typescript and publish it as a npm (yarn) package.

## đź“ŚCreate yarn package

```sh
mkdir hello-ts-cli
cd hello-ts-cli
yarn init -y
```

## đź“ŚInstall Typescript in your project
To use typescript, let's install `typescript`.

```sh
yarn add typescript --dev
```
https://www.typescriptlang.org/download

## đź“ŚMake first ts file
Make `src` folder and `cli.ts` inside it.

`src/cli.ts`
```ts
#!/usr/bin/env node

console.log("Hello World");
```

- [`#!/usr/bin/env node` is needed for making node.js cli tool.](https://stackoverflow.com/questions/33509816/what-exactly-does-usr-bin-env-node-do-at-the-beginning-of-node-files)
- [filename convention: `cli.ts`](https://docs.npmjs.com/cli/v7/configuring-npm/package-json#bin)

## đź“ŚTypescript compile command
Let's check basic typescript command.

https://www.typescriptlang.org/docs/handbook/compiler-options.html
### âś…`tsc`

`tsc` is the command to compile the Typescript code.

```sh
yarn tsc src/cli.ts
```
This command creates `src/cli.js`.
### âś…`tsc --watch`
Automatically compile `ts` files when you make a change.
```sh
tsc src/index.ts --watch
```

## đź“Ś`tsconfig.json`
https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
### âś…What is `tsconfig.json` ?
- Specify compile options
- Indicates that the directory is the root of a TypeScript project
- You can specify which files to compile and which files to exclude (**you don't need to specify each files to compile**).

### âś…Make `tsconfig.json`
```
yarn tsc --init
```
to create the `tsconfig.json` file.
### âś…Use Recommended `tsconfig.json` settings
đź“ťIn the beginning, you may not know what settings to use, so let's extend the recommended settings.

This time, we will use the recommended settings for `node14`.

https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#tsconfig-bases

`terminal`
```sh
yarn add -D @tsconfig/node14
```

Then,

`tsconfig.json`
```json
{
"extends": "@tsconfig/node14/tsconfig.json",
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
```

### âś… Add `rootDir`
Set the `rootDir` to `src` since `ts` files are only stored under the `src` directory.

`tsconfig.json`
```json
{
"extends": "@tsconfig/node14/tsconfig.json",
"compilerOptions": {
"rootDir": "src",
},
"include": ["src/**/*"],
"exclude": ["node_modules"],
}
```

Ref: https://www.typescriptlang.org/tsconfig#rootDir

### âś… Change output dir
- Change the output destination of the compiled `.ts` file to `lib`.
- Also, add exclude `lib` in `tsconfig.json`.
```json
{
"extends": "@tsconfig/node14/tsconfig.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "lib",
},
"include": ["src/**/*"],
"exclude": ["node_modules", "lib"],
}
```

[Ref: Naming Conventions of `lib`](https://stackoverflow.com/questions/39553079/difference-between-lib-and-dist-folders-when-packaging-library-using-webpack#:~:text=3%20Answers&text=Usually%20the%20dist%20folder%20is,npm%20will%20consume%20that%20directly)

## đź“ŚAdd `@types/node`
If you compile the file in this state, you will get the following error.

`terminal`
```sh
$ yarn tsc # thanks to `tsconfig.json`, you don't need to specify target ts files now.
Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.

1 console.log("Hello World");
~~~~~~~
```

This is caused by the lack of `node` types. So, you can add
```sh
yarn add -D @types/node
```

Ref: https://github.com/microsoft/TypeScript/issues/9545

## đź“ŚAdd `main` and `bin` to `package.json`

`package.json`
```json
{
"name": "hello-ts-cli",
"version": "1.0.0",
"main": "lib/cli.js",
"bin": {
"hello-ts-cli": "lib/cli.js"
},
"license": "MIT",
"devDependencies": {
"@tsconfig/node14": "^1.0.0",
"@types/node": "^15.6.1",
"typescript": "^4.3.2"
},
"dependencies": {
"chalk": "^4.1.1",
"commander": "^7.2.0"
}
}
```
`main`: https://docs.npmjs.com/cli/v7/configuring-npm/package-json#main

`bin`: https://docs.npmjs.com/cli/v7/configuring-npm/package-json#bin

## đź“ŚRun cli scripts
Now we are ready to run the cli command. Let's install the current folder into `npm` global.

`terminal`
```sh
npm i -g .
```

Now you can use the `hello-ts-cli` command specified in `package.json`.

`terminal`
```sh
$ hello-ts-cli
Hello World
```

âť—Don't forget to uninstall after finishing this tutorial.
```
npm uninstall -g .
```

## đź“ŚTerminal Text Coloring
https://github.com/chalk/chalk

```sh
yarn add chalk
```

`src/cli.ts`
```ts
#!/usr/bin/env node
import chalk from "chalk";
console.log(chalk.blue("Hello World"));
```

```sh
yarn tsc
hello-ts-cli
```

![2021-06-01_08h25_51](https://user-images.githubusercontent.com/29557494/120248657-114b1580-c2b3-11eb-93c8-4741b29aee5f.png)

## đź“ŚAccept Args
https://github.com/tj/commander.js/

```
yarn add commander
```

I will use this example

https://github.com/tj/commander.js/#action-handler

```ts
#!/usr/bin/env node
import { Command } from "commander";
import chalk from "chalk";

const program = new Command();

program
.arguments("")
.option("-t, --title ", "title to use before name")
.option("-d, --debug", "display some debugging")
.action((name, options, command) => {
if (options.debug) {
console.error("Called %s with options %o", command.name(), options);
}
const title = options.title ? `${options.title} ` : "";
console.log(chalk.blue(`Hello ${title}${name}`));
});

program.parse();
```

Then compile and run command with options

```sh
$ yarn tsc
$ hello-ts-cli World --title="Super"
Hello Super World
```

## đź“ŚPublish Yarn Package
1. [Create an npm account](https://www.npmjs.com/signup)

Then,

```sh
# git tagging before publish
$ git tag v1.0.0
$ git tag -l
v1.0.0
$ git push origin v1.0.0

# publish package
$ yarn publish
```

### âś…If package name is already taken

Change name in `package.json`
```json
{
"name": "@username/hello-ts-cli",
...
}
```

Then

```sh
yarn publish --access public
```

Ref: https://docs.npmjs.com/creating-and-publishing-scoped-public-packages

### âś…Files included in package by `yarn publish`
You can check what files will be included in your package, by running `npx npm-packlist`.

```sh
$npx npm-packlist
lib/cli.js
package.json
tsconfig.json
README.md
src/cli.ts
```

Ref: https://docs.npmjs.com/cli/v7/commands/npm-publish#files-included-in-package

### âś…Prevent the possibility of forgetting to build before publish.

If you put the following in `package.json`, it will automatically build the typescript file when you type `yarn publish`.

In `package.json`
```
...
"scripts": {
"prepare": "tsc"
},
...
```

Ref: https://docs.npmjs.com/cli/v7/using-npm/scripts#life-cycle-scripts

## đź“ŚUpdate and publish yarn package
```sh
$ yarn version
...
# Type new version here
question New version: 1.0.1
```
`yarn version` automatically creates new git tag.

```sh
$ git tag -l
v1.0.0
v1.0.1

# So, just push new version to remote
git push origin v1.0.1

# publish updated version
yarn publish
```

## Refs
- https://developer.okta.com/blog/2019/06/18/command-line-app-with-nodejs
- https://medium.com/netscape/a-guide-to-create-a-nodejs-command-line-package-c2166ad0452e
- https://www.digitalocean.com/community/tutorials/typescript-new-project
- https://itnext.io/how-to-create-your-own-typescript-cli-with-node-js-1faf7095ef89