Skip to content

Commit

Permalink
feat: add example for Commander (nodejs#32)
Browse files Browse the repository at this point in the history
* feat(examples): 🎉 Example commander cli to generate fake names using faker.js

* test(examples): 🚧 Test Case for logNames

* chore: 🔧 Added VSCode workspace to gitignore

* test(examples): ✅ Tests for utils

* test(examples): ✅ Cleanup after save file tests

Cleanup by deleting the files which are generated by tests

* ci(examples): 🔧 Actions for cli-commander-fake-names-generator

Github actions for commander example project fake-names-generator

* docs(examples): 📝 Usage Instruction & README Updates

* docs(examples): 📝 Added Test information

* ci(examples): 🔧 Update CI Config with correct path

* ci(examples): ✏️ Typo Fix of the path name

* Update cli/commander/fake-names-generator/README.md

Co-authored-by: Rodion Abdurakhimov <[email protected]>

* fix(examples): 🐛 Replace time delimiter`:` in Filename with `-`

Windows CI build was failing because of `:` in file name. Hence replacing it with `-`

* feat(examples): 📦 Replacing faker with chanceJS

* Update cli/commander/fake-names-generator/README.md

Co-authored-by: Tierney Cyren <[email protected]>

* Update cli/commander/fake-names-generator/README.md

Co-authored-by: Tierney Cyren <[email protected]>

* fix(examples): 🔥 Remove gender related changes

* chore(examples): 🙈 Moved the new line to end of file

* Update .gitignore

Co-authored-by: Tierney Cyren <[email protected]>

* Update cli/commander/fake-names-generator/README.md

Co-authored-by: Tierney Cyren <[email protected]>

* Update cli/commander/fake-names-generator/package.json

Co-authored-by: Tierney Cyren <[email protected]>

* Update cli/commander/fake-names-generator/README.md

Co-authored-by: Tierney Cyren <[email protected]>

* fix(examples): ✏️ Fixing auto-commit typo issue.

Co-authored-by: Rodion Abdurakhimov <[email protected]>
Co-authored-by: Tierney Cyren <[email protected]>
  • Loading branch information
3 people authored Dec 9, 2020
1 parent 867350f commit 2e89b65
Show file tree
Hide file tree
Showing 9 changed files with 323 additions and 1 deletion.
34 changes: 34 additions & 0 deletions .github/workflows/cli-commander-fake-names-generator.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: cli-commander-fake-names-generator

on:
push:
paths:
- 'cli/commander/fake-names-generator/**'
pull_request:
paths:
- 'cli/commander/fake-names-generator/**'
schedule:
# Every day at 1am
- cron: '0 1 * * *'

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
node-version: [10.x, 12.x]
env:
CI: true
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }} on ${{ matrix.os }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install
run: npm install
working-directory: './cli/commander/fake-names-generator'
- name: npm run test
run: npm run test
working-directory: './cli/commander/fake-names-generator'
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,7 @@ dist

# ignore lockfiles
package-lock.json
yarn.lock
yarn.lock

# VSCode workspaces
*.code-workspace
76 changes: 76 additions & 0 deletions cli/commander/fake-names-generator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# fake-names-generator

CLI built with [commander](https://www.npmjs.com/package/commander) to generate fake names using [Chance](https://www.npmjs.com/package/chance)

## Usage

Here is the output of running `node bin/cli.js -h` from the `fake-names-generator` directory:

```bash
Usage: fake-names-generator <option>

CLI built with [commander](https://www.npmjs.com/package/commander) to generate fake names using [Chance](https://www.npmjs.com/package/chance)

Options:
-V, --version output the version number
-n, --nameType <option> name (default: "fullName")
-t, --times <option> number of times (default: 1)
-i --info info (default: false)
-s --save save as json (default: false)
-h, --help display help for command

Example usages:
$ fake-names-generator -n firstName # generates a first name
$ fake-names-generator -n lastName # generates a last name
$ fake-names-generator -t 5 # generates 5 full names
$ fake-names-generator -s # generates a full name also saves the result as json file
$ fake-names-generator -i # gives extra log info during name generation
```

### As a Local Project

You'll want to start by installing dependencies:

```bash
npm install
```

Since this is a CLI, you'll probably want to get it available on your PATH. There's two ways you can do this:

**Via global installation:**

```bash
npm i -g # this will install the current working directory as a global module.
fake-names-generator # run the CLI
```

You may want to run `npm uninstall -g` from the project directory to uninstall it.

**Via symlink:**

```bash
npm link # this will create a symlink that makes the module act as a global module.
fake-names-generator # run the CLI
```

`npm unlink` to remove this.

### As a Module Published to npm

If you were to pulbish this CLI to npm, there'd be two ways you'd use it from the registry with npm (let's assume you published as `fake-names-generator`):

```bash
npm i -g fake-names-generator # Install the module from the registry & make it globally available

fake-names-generator # run the CLI
```

```bash
npx fake-names-generator # this would temporarily download the module, run the first entry in `bin` of package.json and pass along any additional arguments like `--save`
```

## Tests

```bash
npm test
```
41 changes: 41 additions & 0 deletions cli/commander/fake-names-generator/bin/cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env node
const { program } = require('commander')

const { logNames, saveNames } = require('../lib/fake-names') // name generating lib
const { log } = require('../lib/utils') // helper utilities
const packageJSON = require('../package.json')

program
.version(packageJSON.version)
.description(packageJSON.description)
.usage('<option>')
.option('-n, --nameType <option>', 'name', 'fullName')
.option('-t, --times <option>', 'number of times', 1)
.option('-i --info', 'info', false)
.option('-s --save', 'save as json', false)

// custom help must be defined before .parse()
program.on('--help', () => {
const examples = [
'-n firstName \t# generates a first name',
'-n lastName \t# generates a last name',
'-t 5 \t\t# generates 5 full names',
'-s \t\t# generates a full name also saves the result as json file',
'-i \t\t# gives extra log info during name generation']
console.log('\nExample usages:\n')
examples.forEach(example => console.log(`\t$ fake-names-generator ${example}`))
})

program.parse(process.argv)

if (program.info) {
log.dim(`\nGenerating ${program.times} names \n`)
}

// always logs the generated names
logNames(program.times, program.nameType)

// Saves the generated names as JSON file.
if (program.save) {
saveNames(program.times, program.nameType)
}
35 changes: 35 additions & 0 deletions cli/commander/fake-names-generator/lib/fake-names.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const Chance = require('chance') // Load Chance
const chance = new Chance() // Instantiate Chance so it can be used
const fs = require('fs')
const { log, getFileName } = require('../lib/utils')

// Get First name
exports.firstName = () => chance.first()

// Get Last name
exports.lastName = () => chance.last()

// Get Full name
exports.fullName = () => chance.name()

// Generates names based on cli inputs
exports.generateNames = (times = 1, nameType = 'fullName') => {
const names = []
for (let i = 1; i <= times; i++) {
names.push(this[nameType]())
}
return names
}

// Logs the generated names
exports.logNames = (times, nameType) => {
this.generateNames(times, nameType).forEach(name => console.log(name))
}

// Saves the generated names in a JSON File
exports.saveNames = (times, nameType) => {
const names = this.generateNames(times, nameType)
const data = JSON.stringify({ names })
fs.writeFileSync(getFileName(), data)
log.success(`\n✅ Saved ${times} names to ${getFileName()}\n`)
}
66 changes: 66 additions & 0 deletions cli/commander/fake-names-generator/lib/fake-names.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
const fakeNames = require('./fake-names')
const utils = require('../lib/utils')
const fs = require('fs')

describe('fake names tests', () => {
test('should generate a first name', () => {
const spy = jest.spyOn(fakeNames, 'firstName').mockImplementation(() => 'Jane')
fakeNames.firstName()
expect(spy).toHaveBeenCalled()
expect(spy()).toBe('Jane')
})

test('should generate a last name', () => {
const spy = jest.spyOn(fakeNames, 'lastName').mockImplementation(() => 'Doe')
fakeNames.lastName()
expect(spy).toHaveBeenCalled()
expect(spy()).toBe('Doe')
})

test('should generate a full name', () => {
const spy = jest.spyOn(fakeNames, 'fullName').mockImplementation(() => 'Jane Doe')

fakeNames.fullName()
expect(spy).toHaveBeenCalled()
expect(spy()).toBe('Jane Doe')
})

test('should generate names only 1 time by default', () => {
const names = fakeNames.generateNames()
expect(names).toHaveLength(1)
})

test('should generate names n times', () => {
const names = fakeNames.generateNames(5)
expect(names).toHaveLength(5)
})

test('should log names', () => {
jest.spyOn(fakeNames, 'logNames')
jest.spyOn(fakeNames, 'generateNames')
jest.spyOn(console, 'log')
fakeNames.logNames()
expect(fakeNames.logNames).toHaveBeenCalled()
expect(fakeNames.generateNames).toHaveBeenCalled()
expect(console.log).toHaveBeenCalled()
})

test('should save names in a file', () => {
jest.spyOn(fakeNames, 'saveNames')
jest.spyOn(fakeNames, 'generateNames')
jest.spyOn(fs, 'writeFileSync')
jest.spyOn(utils.log, 'success')
jest.spyOn(utils, 'getFileName')

fakeNames.saveNames(5)
expect(fakeNames.saveNames).toHaveBeenCalled()
expect(fakeNames.generateNames).toHaveBeenCalled()
expect(fs.writeFileSync).toHaveBeenCalled()
expect(utils.log.success).toHaveBeenCalled()

// Cleanup by Deleting the generated file
fs.readdirSync('./')
.filter(f => f.startsWith('fake-names-') && f.endsWith('.json'))
.map(f => fs.unlinkSync(f))
})
})
11 changes: 11 additions & 0 deletions cli/commander/fake-names-generator/lib/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const chalk = require('chalk')
const currentTime = (new Date().toLocaleTimeString([], { hour12: false })).split(':').join('-')

// Pretty print console logs with Chalk
exports.log = {
dim: (text) => console.log(chalk.dim(text)),
success: (text) => console.log(chalk.green(text))
}

// Generates a fileName with current time. e.g. fake-names-19:29:17.json
exports.getFileName = () => `fake-names-${currentTime}.json`
18 changes: 18 additions & 0 deletions cli/commander/fake-names-generator/lib/utils.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

const utils = require('./utils')

describe('utils tests', () => {
test('should call log.dim', () => {
jest.spyOn(utils.log, 'dim')
utils.log.dim()
expect(utils.log.dim).toHaveBeenCalled()
})

test('should return a name with current timestamp', () => {
jest.spyOn(utils, 'getFileName')
const currentTime = new Date().toLocaleTimeString([], { hour12: false }).split(':').join('-')
utils.getFileName()
expect(utils.getFileName).toHaveBeenCalled()
expect(utils.getFileName()).toBe(`fake-names-${currentTime}.json`)
})
})
38 changes: 38 additions & 0 deletions cli/commander/fake-names-generator/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "fake-names-generator",
"version": "1.0.0",
"description": "CLI built with [commander](https://www.npmjs.com/package/commander) to generate fake names using [Chance](https://www.npmjs.com/package/chance)",
"main": "index.js",
"bin": {
"fake-names-generator": "./bin/cli.js"
},
"scripts": {
"test:unit": "jest --coverage",
"test:onlychanged": "jest --onlyChanged --coverage",
"lint": "standard",
"test": "npm run lint && npm run test:unit"
},
"keywords": [
"commander",
"chance",
"cli"
],
"author": "Thiruppathi Muthukumar",
"license": "MIT",
"dependencies": {
"commander": "^6.2.0",
"chance": "^1.1.7"
},
"devDependencies": {
"jest": "^25.2.6",
"standard": "^14.3.3"
},
"standard": {
"globals": [
"describe",
"test",
"expect",
"jest"
]
}
}

0 comments on commit 2e89b65

Please sign in to comment.