Skip to content

Commit

Permalink
feat!: simplify CLI usage (#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
Zidious authored Nov 29, 2023
1 parent 8aae650 commit 6a61b55
Show file tree
Hide file tree
Showing 11 changed files with 242 additions and 364 deletions.
87 changes: 17 additions & 70 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,96 +21,43 @@ You can install the crypto-cli tool via npm and yarn:
npm install -g coffee-crypto-cli
```

```sh
yarn add global coffee-crypto-cli
```

## Usage

```sh
$ crypto --price bitcoin --volume --ath
>> Bitcoin: $20,000 - volume: $13,337 - ATH: $68,000
$ crypto bitcoin
>> Bitcoin: $20,000
```

## Flags

Note: `--price, --p` is required for any of the subsequent flags.

```sh
--price, --p - coin name
```

Coin price change (%) in the past 24 hours.

```sh
--price-change, --pc
```

Coin volume in the past 24 hours.

```sh
--volume, --v
```

Highest price sold in the past 24 hours.

```sh
--high
```

Lowest price sold in the past 24 hours.

```sh
--low
```

Coin all time high price.

```sh
--ath
```

Percent price change from the all time high.

```sh
--ath-change, --athc
```

Save coin data via JSON and/or CSV

```sh
--save json
--save json,csv
```

CLI help message.

```sh
--help
```

Current version.

```sh
--version
```
| Name | Description |
| ------------------------ | ------------------------------------------- |
| `--price-change`, `--pc` | Coin price change (%) in the past 24 hours |
| `--volume`, `--v` | Coin volume in the past 24 hours |
| `--ath-change`, `--athc` | Percent price change from the all time high |
| `--high`, `--h` | Highest price sold in the past 24 hours |
| `--low`, `--l` | Lowest price sold in the past 24 hours |
| `--ath` | Coin all time high price |
| `--save json,csv` | Save coin data via JSON and/or CSV |
| `--help` | Flag description and usage examples |
| `--version` | Current version |

## Local Development

First things first, we'll need to clone the repo, install the dependencies, and, build the project.
Clone the repo, install the dependencies, and, build the project.

```sh
git clone https://github.com/Zidious/crypto-cli.git
```

```sh
yarn install && yarn build
yarn install --frozen-lockfile && yarn build
```

To run the CLI locally, use the below command followed by the flag you want to run.
To run the CLI locally:

```sh
node dist/index.js --price bitcoin
node dist/index.js bitcoin
```

## Contributing
Expand Down
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"prebuild": "rimraf dist",
"build": "tsc",
"test": "mocha 'src/*.test.ts'",
"lint": "eslint --fix",
"prepare": "husky install",
"precommit": "lint-staged"
},
Expand All @@ -37,8 +38,8 @@
"@types/json2csv": "^5.0.3",
"@types/mocha": "^10.0.1",
"@types/node": "^20.6.0",
"@typescript-eslint/eslint-plugin": "^6.6.0",
"@typescript-eslint/parser": "^5.54.0",
"@typescript-eslint/eslint-plugin": "^6.13.1",
"@typescript-eslint/parser": "^6.13.1",
"chai": "^4.3.8",
"eslint": "^8.49.0",
"execa": "^8.0.1",
Expand All @@ -51,10 +52,11 @@
"typescript": "^5.2.2"
},
"lint-staged": {
"*.{md,ts}": [
"*.ts": [
"eslint --fix",
"prettier --write"
]
],
"*.md": "prettier --write"
},
"keywords": [
"bitcoin",
Expand Down
113 changes: 49 additions & 64 deletions src/actions/priceStats.ts
Original file line number Diff line number Diff line change
@@ -1,67 +1,52 @@
import { format, logSuccess } from '../utils.js'
import type { Flags } from '../constants.js'

interface PriceStatsParams {
name: string
current_price: number
total_volume: number
high_24h: number
low_24h: number
percent24h: number
athPrice: number
athPercent: number
}

type PriceStatFlags = Omit<Flags, 'save'>

export const priceStats = (
{
name,
current_price,
total_volume,
high_24h,
low_24h,
percent24h,
athPrice,
athPercent
}: PriceStatsParams,
{ price, priceChange, high, low, volume, ath, athChange }: PriceStatFlags
): void => {
const priceRes = `${name}: ${format(current_price)}`
let priceChangeRes
let volumeRes
let highRes
let lowRes
let athRes
let athChangeRes

if (priceChange) {
priceChangeRes = `change (24H): ${percent24h.toFixed(2)}%`
}

if (high) {
highRes = `high (24H): ${format(high_24h)}`
}

if (low) {
lowRes = `low (24H): ${format(low_24h)}`
}

if (volume) {
volumeRes = `volume (24H): ${format(total_volume)}`
}

if (ath) {
athRes = `ATH: ${format(athPrice)}`
}

if (athChange) {
athChangeRes = `ATH (%): ${athPercent.toFixed(2)}%`
import type { PriceStatsParams } from '../types.js'

export const priceStats = ({ results, flags }: PriceStatsParams): void => {
for (const result of results) {
const priceRes = `${result.name}: ${format(result.current_price)}`
let priceChangeRes
let volumeRes
let highRes
let lowRes
let athRes
let athChangeRes

if (flags.priceChange) {
priceChangeRes = `change (24H): ${result.price_change_24h.toFixed(2)}%`
}

if (flags.high) {
highRes = `high (24H): ${format(result.high_24h)}`
}

if (flags.low) {
lowRes = `low (24H): ${format(result.low_24h)}`
}

if (flags.volume) {
volumeRes = `volume (24H): ${format(result.total_volume)}`
}

if (flags.ath) {
athRes = `ATH: ${format(result.ath)}`
}

if (flags.athChange) {
athChangeRes = `ATH (%): ${result.atl_change_percentage.toFixed(2)}%`
}

logSuccess(
[
priceRes,
priceChangeRes,
volumeRes,
highRes,
lowRes,
athRes,
athChangeRes
]
.filter(Boolean)
.join(' - ')
)
}

logSuccess(
[priceRes, priceChangeRes, volumeRes, highRes, lowRes, athRes, athChangeRes]
.filter(Boolean)
.join(' - ')
)
}
42 changes: 25 additions & 17 deletions src/actions/saveCoinData.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import fs from 'fs'
import { parseAsync } from 'json2csv'
import { logError, logSuccess } from '../utils.js'
import { formatFileName, logError, logSuccess } from '../utils.js'
import { CSVEXT, JSONEXT } from '../constants.js'
import type { ExportData } from '../constants.js'
import { CoinMarkets } from '@crypto-coffee/coingecko-api/dist/types.js'
import type { SaveCoinDataParams } from '../types.js'

export const saveCoinData = async ({
options,
results
}: SaveCoinDataParams) => {
if (!options) {
return
}

export const saveCoinData = async (
options: string,
exportData: ExportData[]
) => {
const fileExts = options.toLowerCase().split(',')

if (
Expand All @@ -21,6 +26,12 @@ export const saveCoinData = async (
)
}

const exportData: Partial<CoinMarkets>[] = []

for (const result of results) {
exportData.push(result)
}

logSuccess('Exporting coin data...')
if (fileExts.includes(JSONEXT)) {
writeFile(exportData, JSONEXT)
Expand All @@ -33,10 +44,14 @@ export const saveCoinData = async (
logSuccess('Export complete.')
}

const writeFile = async (exportData: ExportData[], fileExt: string) => {
const writeFile = async (
exportData: Partial<CoinMarkets>[],
fileExt: string
) => {
for (const coin of exportData) {
const data =
fileExt === JSONEXT ? JSON.stringify(coin) : await formatCsvFile(coin)

try {
fs.writeFileSync(formatFileName(coin.name as string, fileExt), data, {
encoding: 'utf8'
Expand All @@ -51,15 +66,8 @@ const writeFile = async (exportData: ExportData[], fileExt: string) => {
}
}

const formatFileName = (coinName: string, fileExt: string): string => {
/* use unix timestamp, resolves conflict of same filenames */
const timestamp = new Date().valueOf()

return `${coinName.toLowerCase()}-${timestamp}.${fileExt}`
}

const formatCsvFile = async (coin: ExportData): Promise<string> => {
return await parseAsync(coin as Readonly<ExportData>, {
const formatCsvFile = async (coin: Partial<CoinMarkets>): Promise<string> => {
return await parseAsync(coin, {
delimiter: ',',
excelStrings: false,
fields: [
Expand Down Expand Up @@ -89,7 +97,7 @@ const formatCsvFile = async (coin: ExportData): Promise<string> => {
},
{
label: 'All Time High',
value: 'all_time_high'
value: 'ath'
},
{
label: 'All Time High Percentage',
Expand Down
Loading

0 comments on commit 6a61b55

Please sign in to comment.