diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..23f8942
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+# folders
+node_modules
+.vscode
+
+# files
+yarn.lock
+package-lock.json
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..31ba22d
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,5 @@
+{
+ "semi": false,
+ "singleQuote": true,
+ "printWidth": 120
+}
diff --git a/README.md b/README.md
index 85e6ff1..6fef557 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,70 @@
-# WIP
+
+
pkg-details
+
+
CLI tool to get pkg details
+
+![npm bundle size](https://img.shields.io/bundlephobia/minzip/pkg-details?label=size&style=flat-square)
+![npm version](https://img.shields.io/npm/v/pkg-details?style=flat-square)
+![npm downloads](https://img.shields.io/npm/dm/pkg-details?style=flat-square)
+![gitHub tests](https://img.shields.io/github/workflow/status/sagar-gavhane/pkg-details/tests?label=tests&style=flat-square)
+
+
+
+### Installing
+
+This module is distributed via `npm` which is bundled with `node` and should be installed as one of your project's dependence.
+
+```bash
+npm install -g pkg-details
+# or
+yarn global add pkg-details
+```
+
+### Usage
+
+
+
+```bash
+npx pkg-details react
+>
+react@v16.13.1 | MIT | deps: 3 | versions: 275 | minified: 6.30 KB | gzip: 2.56 KB
+React is a JavaScript library for building user interfaces.
+
+versions:
+latest: 16.13.1
+next: 0.0.0-7f28234f8
+experimental: 0.0.0-experimental-4c8c98ab9
+canary: 0.0.0-57333ca33
+unstable: 0.0.0-da834083c
+
+downloads:
+weekly: 7687396
+monthly: 29955078
+
+links:
+README: https://reactjs.org/
+npm: https://www.npmjs.com/package/react
+repository: https://github.com/facebook/react.git
+
+dates:
+last published: 4 months
+created at: over 8 years
+
+maintainers:
+- acdlite [npm@andrewclark.io]
+- brianvaughn [briandavidvaughn@gmail.com]
+- fb [opensource+npm@fb.com]
+- gaearon [dan.abramov@gmail.com]
+- lunaruan [lunaris.ruan@gmail.com]
+- sebmarkbage [sebastian@calyptus.eu]
+- sophiebits [npm@sophiebits.com]
+- trueadm [dg@domgan.com]
+```
+
+### Contributing
+
+Pull requests are always welcome! :)
+
+### License
+
+MIT
diff --git a/index.js b/index.js
new file mode 100755
index 0000000..e4a993c
--- /dev/null
+++ b/index.js
@@ -0,0 +1,98 @@
+#!/usr/bin/env node
+
+const chalk = require('chalk')
+const argv = require('minimist')(process.argv.slice(2))
+const terminalLink = require('terminal-link')
+const ora = require('ora')
+const { subDays, format, parseISO, formatDistance } = require('date-fns')
+
+const { getPackage, getPackageStats, getDownloadStats } = require('./services/api')
+const clear = require('./utils/clear')
+const br = require('./utils/br')
+const downloadSum = require('./utils/downloadSum')
+const readablizeBytes = require('./utils/readablizeBytes')
+
+const spinner = ora('Loading package details...')
+
+// handle unhandled rejections
+process.on('unhandledRejection', (err) => {
+ // clear()
+ spinner.clear()
+ console.log(chalk.red(`Failed while fetching package details :(`))
+ process.exit()
+})
+
+const log = console.log
+
+const tl = (...args) => chalk.blueBright(terminalLink(...args))
+
+if (!Array.isArray(argv._) || !argv._.length) {
+ log(chalk.bold.red('Please provide package name.'))
+ return
+}
+
+const pkgName = argv._[0]
+
+const init = async () => {
+ // fetch package stats
+ spinner.start()
+ const [package, packageStats, weeklyDownloadStats, monthlyDownloadStats] = await Promise.all([
+ await getPackage(pkgName),
+ await getPackageStats(pkgName),
+ await getDownloadStats(pkgName, format(subDays(new Date(), 7), 'yyyy-MM-dd'), format(new Date(), 'yyyy-MM-dd')),
+ await getDownloadStats(pkgName, format(subDays(new Date(), 28), 'yyyy-MM-dd'), format(new Date(), 'yyyy-MM-dd')),
+ ])
+ spinner.stop()
+
+ const npmhome = `https://www.npmjs.com/package/${pkgName}`
+ const homepage = package.homepage || npmhome
+ const tlConfig = { fallback: false }
+ const latestVersion = `${package['dist-tags'].latest}`
+ const numberOfDeps = Object.keys(package.versions[latestVersion].dependencies).length
+ const numberOfVersions = Object.keys(package.versions).length
+ const repositoryUrl = package.repository.url.replace('git+', '')
+ const lastPublished = package.time[latestVersion]
+
+ // printout
+ clear()
+ br()
+ log(
+ chalk.green.underline.bold(`${pkgName}@v${latestVersion}`),
+ `| ${package.license} | deps: ${chalk.cyan(numberOfDeps)} | versions: ${chalk.cyan(numberOfVersions)}`,
+ `| minified: ${chalk.cyan(readablizeBytes(packageStats.size))} | gzip: ${chalk.cyan(
+ readablizeBytes(packageStats.gzip)
+ )}`
+ )
+ console.log(`${package.description}`)
+ br()
+
+ console.log(chalk.yellow.bold('versions:'))
+ for (const key in package['dist-tags']) {
+ console.log(`${key}: ${chalk.cyan(package['dist-tags'][key])}`)
+ }
+ br()
+
+ console.log(chalk.yellow.bold('downloads:'))
+ console.log(`weekly: ${chalk.cyan(downloadSum(weeklyDownloadStats.downloads))}`)
+ console.log(`monthly: ${chalk.cyan(downloadSum(monthlyDownloadStats.downloads))}`)
+
+ br()
+ console.log(chalk.yellow.bold('links:'))
+ console.log(`README: ${tl(homepage, homepage, tlConfig)}`)
+ console.log(`npm: ${tl(npmhome, npmhome, tlConfig)}`)
+ console.log(`repository: ${tl(repositoryUrl, repositoryUrl, tlConfig)}`)
+
+ br()
+ console.log(chalk.yellow.bold('dates:'))
+ // 2020-03-19T19:53:13.309Z
+ console.log(`last published: ${formatDistance(parseISO(lastPublished), new Date())}`)
+ console.log(`created at: ${formatDistance(parseISO(package.time.created), new Date())}`)
+
+ br()
+ console.log(chalk.yellow.bold('maintainers:'))
+ package.maintainers.forEach((maintainer) => {
+ console.log(`- ${maintainer.name} [${tl(maintainer.email, `mailto:${maintainer.email}`)}]`)
+ })
+}
+
+init()
diff --git a/package.json b/package.json
index b40e573..f151db3 100644
--- a/package.json
+++ b/package.json
@@ -3,8 +3,31 @@
"version": "1.0.0",
"description": "get npm package details",
"main": "index.js",
+ "bin": {
+ "pkg-details": "index.js"
+ },
"repository": "git@github.com:sagar-gavhane/pkg-details.git",
"author": "sagar",
"license": "MIT",
- "private": false
+ "private": false,
+ "keywords": [
+ "pkg details",
+ "details",
+ "pkg-info",
+ "npm-info"
+ ],
+ "scripts": {
+ "release": "np"
+ },
+ "devDependencies": {
+ "np": "^6.3.2"
+ },
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "date-fns": "^2.15.0",
+ "got": "^11.5.1",
+ "minimist": "^1.2.5",
+ "ora": "^4.0.5",
+ "terminal-link": "^2.1.1"
+ }
}
diff --git a/services/api.js b/services/api.js
new file mode 100644
index 0000000..c85bdb0
--- /dev/null
+++ b/services/api.js
@@ -0,0 +1,25 @@
+const got = require('got')
+
+const getPackage = async (packageName) => {
+ return await got(`https://registry.npmjs.org/${packageName}`, {
+ responseType: 'json',
+ }).then((r) => r.body)
+}
+
+const getPackageStats = async (packageName) => {
+ return await got(`https://bundlephobia.com/api/size?package=${packageName}`, {
+ responseType: 'json',
+ }).then((r) => r.body)
+}
+
+const getDownloadStats = async (packageName, startDate, endDate) => {
+ return await got(`https://api.npmjs.org/downloads/range/${startDate}:${endDate}/${packageName}`, {
+ responseType: 'json',
+ }).then((r) => r.body)
+}
+
+module.exports = {
+ getPackage,
+ getPackageStats,
+ getDownloadStats,
+}
diff --git a/utils/br.js b/utils/br.js
new file mode 100644
index 0000000..fc386ab
--- /dev/null
+++ b/utils/br.js
@@ -0,0 +1,5 @@
+const clear = () => {
+ console.log('')
+}
+
+module.exports = clear
diff --git a/utils/clear.js b/utils/clear.js
new file mode 100644
index 0000000..02ab514
--- /dev/null
+++ b/utils/clear.js
@@ -0,0 +1,9 @@
+const clear = () => {
+ const readline = require('readline')
+ const blank = '\n'.repeat(process.stdout.rows)
+ console.log(blank)
+ readline.cursorTo(process.stdout, 0, 0)
+ readline.clearScreenDown(process.stdout)
+}
+
+module.exports = clear
diff --git a/utils/downloadSum.js b/utils/downloadSum.js
new file mode 100644
index 0000000..0e97b42
--- /dev/null
+++ b/utils/downloadSum.js
@@ -0,0 +1,5 @@
+const downloadSum = (downloads) => {
+ return downloads.reduce((prev, currentValue) => prev + currentValue.downloads, 0)
+}
+
+module.exports = downloadSum
diff --git a/utils/readablizeBytes.js b/utils/readablizeBytes.js
new file mode 100644
index 0000000..1f8115d
--- /dev/null
+++ b/utils/readablizeBytes.js
@@ -0,0 +1,7 @@
+const readablizeBytes = (bytes) => {
+ var s = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB']
+ var e = Math.floor(Math.log(bytes) / Math.log(1024))
+ return (bytes / Math.pow(1024, e)).toFixed(2) + ' ' + s[e]
+}
+
+module.exports = readablizeBytes