pkg-stats 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -1,3 +1,16 @@
1
1
  ## PKG Stats
2
2
 
3
- Beautiful package download stats.
3
+ Beautiful NPM package download stats.
4
+
5
+ ```
6
+ npx pkg-stats react
7
+ ```
8
+
9
+ <div align='center'>
10
+ <img src="https://raw.githubusercontent.com/mdjastrzebski/pkg-stats/main/docs/public/example-react.png" alt="pkg-stats" height="210" width="538" />
11
+ </div>
12
+
13
+ ### Options:
14
+
15
+ - version grouping: `--group major|minor|patch` (alias `-g`, `--major`, `--minor`, `--patch`)
16
+ - top version: `--top <number>` (alias `-t`)
package/dist/bin.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import chalk from 'chalk';
2
2
  import minimist from 'minimist';
3
3
  import { renderChart } from './chart.js';
4
- import { gradients } from './colors.js';
4
+ import { getColors } from './colors.js';
5
5
  import { parseVersion, versionCompare } from './version.js';
6
+ import { groupByType, pickTopStats } from './stats.js';
6
7
  export async function pkgStats(argv) {
7
8
  const options = parseCliOptions(argv);
8
9
  if (options.help) {
@@ -31,27 +32,20 @@ export async function pkgStats(argv) {
31
32
  };
32
33
  })
33
34
  .sort(versionCompare);
34
- let groupedStats;
35
- if (options.group === 'patch') {
36
- groupedStats = sumByPatch(rawStats);
37
- }
38
- else if (options.group === 'minor') {
39
- groupedStats = sumByMinor(rawStats);
40
- }
41
- else {
42
- groupedStats = sumByMajor(rawStats);
43
- }
35
+ let groupedStats = groupByType(options.group, rawStats);
44
36
  const totalDownloads = Object.values(groupedStats).reduce((sum, version) => sum + version.downloads, 0);
45
37
  const groupedStatsToDisplay = options.top
46
38
  ? pickTopStats(groupedStats, options.top)
47
39
  : groupedStats;
48
- console.log(chalk.bold(`\nNPM weekly downloads for ${chalk.cyan(options.name)}\n`));
49
- console.log(`Total: ${chalk.cyan(totalDownloads.toLocaleString())}\n`);
40
+ const colors = getColors(groupedStatsToDisplay.length);
41
+ const primaryColor = chalk.hex(colors[0]);
42
+ console.log(chalk.bold(`\nNPM weekly downloads for ${primaryColor(options.name)}\n`));
43
+ console.log(`Total: ${primaryColor(totalDownloads.toLocaleString())} last week\n`);
50
44
  console.log(options.top ? `Top ${options.top} versions:\n` : 'By version:\n');
51
- const colors = gradients.passion(groupedStatsToDisplay.length);
52
45
  const maxDownloads = Math.max(...groupedStats.map((v) => v.downloads));
53
46
  groupedStatsToDisplay.forEach((item, i) => {
54
- const version = options.group != 'patch' ? `${item.versionString}.x` : item.versionString;
47
+ const versionParts = item.versionString.split('.');
48
+ const version = versionParts.length < 3 ? `${item.versionString}.x` : item.versionString;
55
49
  const chart = renderChart(item.downloads / maxDownloads);
56
50
  const downloads = formatDownloads(item.downloads, maxDownloads);
57
51
  const color = chalk.hex(colors[i]);
@@ -65,8 +59,11 @@ function parseCliOptions(argv) {
65
59
  boolean: ['help'],
66
60
  alias: { g: 'group', h: 'help', t: 'top' },
67
61
  });
68
- let group = 'major';
69
- if (options.group === 'minor' || options.minor) {
62
+ let group;
63
+ if (options.group === 'major' || options.major) {
64
+ group = 'major';
65
+ }
66
+ else if (options.group === 'minor' || options.minor) {
70
67
  group = 'minor';
71
68
  }
72
69
  else if (options.group === 'patch' || options.patch) {
@@ -93,52 +90,6 @@ function printHelp() {
93
90
  --top <number> Show top <number> versions
94
91
  `);
95
92
  }
96
- function sumByMajor(stats) {
97
- const result = {};
98
- for (const versionStats of stats) {
99
- const key = `${versionStats.major}`;
100
- const entry = result[key] ?? {
101
- version: { major: versionStats.major },
102
- versionString: key,
103
- downloads: 0,
104
- };
105
- result[key] = entry;
106
- entry.downloads += versionStats.downloads;
107
- }
108
- return Object.values(result).sort((a, b) => versionCompare(a.version, b.version));
109
- }
110
- function sumByMinor(stats) {
111
- const result = {};
112
- for (const versionStats of stats) {
113
- const key = `${versionStats.major}.${versionStats.minor}`;
114
- const entry = result[key] ?? {
115
- version: { major: versionStats.major, minor: versionStats.minor },
116
- versionString: key,
117
- downloads: 0,
118
- };
119
- result[key] = entry;
120
- entry.downloads += versionStats.downloads;
121
- }
122
- return Object.values(result).sort((a, b) => versionCompare(a.version, b.version));
123
- }
124
- function sumByPatch(stats) {
125
- const result = {};
126
- for (const versionStats of stats) {
127
- const key = `${versionStats.major}.${versionStats.minor}.${versionStats.patch}`;
128
- const entry = result[key] ?? {
129
- version: {
130
- major: versionStats.major,
131
- minor: versionStats.minor,
132
- patch: versionStats.patch,
133
- },
134
- versionString: key,
135
- downloads: 0,
136
- };
137
- result[key] = entry;
138
- entry.downloads += versionStats.downloads;
139
- }
140
- return Object.values(result).sort((a, b) => versionCompare(a.version, b.version));
141
- }
142
93
  function formatDownloads(downloads, maxDownloads) {
143
94
  if (maxDownloads > 1000000) {
144
95
  return `${(downloads / 1000000).toFixed(1)}M`;
@@ -148,8 +99,3 @@ function formatDownloads(downloads, maxDownloads) {
148
99
  }
149
100
  return downloads.toString();
150
101
  }
151
- function pickTopStats(stats, top) {
152
- const sortedStats = stats.sort((a, b) => b.downloads - a.downloads);
153
- const topStats = sortedStats.slice(0, top);
154
- return topStats.sort((a, b) => versionCompare(a.version, b.version));
155
- }
package/dist/colors.js CHANGED
@@ -1,11 +1,44 @@
1
1
  import tinygradient from 'tinygradient';
2
2
  // See: https://github.com/bokub/gradient-string/blob/465e86c8499a7f427c45afb1861f1444a2db74b9/src/index.ts#L166
3
- export const gradients = {
4
- mind: (count) => toColors(tinygradient(['#473b7b', '#3584a7', '#30d2be']).rgb(count)),
5
- pastel: (count) => toColors(tinygradient(['#74ebd5', '#74ecd5']).hsv(count, 'long')),
6
- passion: (count) => toColors(tinygradient(['#f43b47', '#453a94']).rgb(count)),
7
- retro: (count) => toColors(tinygradient(['#4150AB', '#AE6F97', '#EFCB84']).rgb(count)),
3
+ const gradients = {
4
+ atlas: { colors: ['#feac5e', '#c779d0', '#4bc0c8'], options: {} },
5
+ cristal: { colors: ['#bdfff3', '#4ac29a'], options: {} },
6
+ teen: { colors: ['#77a1d3', '#79cbca', '#e684ae'], options: {} },
7
+ mind: { colors: ['#473b7b', '#3584a7', '#30d2be'], options: {} },
8
+ morning: { colors: ['#ff5f6d', '#ffc371'], options: { interpolation: 'hsv' } },
9
+ vice: { colors: ['#5ee7df', '#b490ca'], options: { interpolation: 'hsv' } },
10
+ passion: { colors: ['#f43b47', '#453a94'], options: {} },
11
+ fruit: { colors: ['#ff4e50', '#f9d423'], options: {} },
12
+ instagram: { colors: ['#833ab4', '#fd1d1d', '#fcb045'], options: {} },
13
+ retro: {
14
+ colors: [
15
+ '#3f51b1',
16
+ '#5a55ae',
17
+ '#7b5fac',
18
+ '#8f6aae',
19
+ '#a86aa4',
20
+ '#cc6b8e',
21
+ '#f18271',
22
+ '#f3a469',
23
+ '#f7c978',
24
+ ],
25
+ options: {},
26
+ },
27
+ summer: { colors: ['#fdbb2d', '#22c1c3'], options: {} },
28
+ rainbow: { colors: ['#ff0000', '#ff0100'], options: { interpolation: 'hsv', hsvSpin: 'long' } },
29
+ pastel: { colors: ['#74ebd5', '#74ecd5'], options: { interpolation: 'hsv', hsvSpin: 'long' } },
8
30
  };
9
- function toColors(colors) {
10
- return colors.map((c) => c.toHexString());
31
+ export function getColors(count, colorScheme) {
32
+ const { colors, options } = gradients[colorScheme ?? getRandomScheme()];
33
+ if (count < colors.length) {
34
+ return colors;
35
+ }
36
+ const gradient = tinygradient(colors);
37
+ const tinyColors = options.interpolation === 'hsv'
38
+ ? gradient.hsv(count, options.hsvSpin ?? false)
39
+ : gradient.rgb(count);
40
+ return tinyColors.map((c) => c.toHexString());
41
+ }
42
+ function getRandomScheme() {
43
+ return Object.keys(gradients)[Math.floor(Math.random() * Object.keys(gradients).length)];
11
44
  }
package/dist/stats.js ADDED
@@ -0,0 +1,72 @@
1
+ import { versionCompare } from './version.js';
2
+ export function groupByType(type, stats) {
3
+ if (type === 'major') {
4
+ return groupByMajor(stats);
5
+ }
6
+ if (type === 'minor') {
7
+ return groupByMinor(stats);
8
+ }
9
+ if (type === 'patch') {
10
+ return groupByPatch(stats);
11
+ }
12
+ const groupedByMajor = groupByMajor(stats);
13
+ if (groupedByMajor.length > 1) {
14
+ return groupedByMajor;
15
+ }
16
+ const groupedByMinor = groupByMinor(stats);
17
+ if (groupedByMinor.length > 1) {
18
+ return groupedByMinor;
19
+ }
20
+ return groupByPatch(stats);
21
+ }
22
+ function groupByMajor(stats) {
23
+ const result = {};
24
+ for (const versionStats of stats) {
25
+ const key = `${versionStats.major}`;
26
+ const entry = result[key] ?? {
27
+ version: { major: versionStats.major },
28
+ versionString: key,
29
+ downloads: 0,
30
+ };
31
+ result[key] = entry;
32
+ entry.downloads += versionStats.downloads;
33
+ }
34
+ return Object.values(result).sort((a, b) => versionCompare(a.version, b.version));
35
+ }
36
+ function groupByMinor(stats) {
37
+ const result = {};
38
+ for (const versionStats of stats) {
39
+ const key = `${versionStats.major}.${versionStats.minor}`;
40
+ const entry = result[key] ?? {
41
+ version: { major: versionStats.major, minor: versionStats.minor },
42
+ versionString: key,
43
+ downloads: 0,
44
+ };
45
+ result[key] = entry;
46
+ entry.downloads += versionStats.downloads;
47
+ }
48
+ return Object.values(result).sort((a, b) => versionCompare(a.version, b.version));
49
+ }
50
+ function groupByPatch(stats) {
51
+ const result = {};
52
+ for (const versionStats of stats) {
53
+ const key = `${versionStats.major}.${versionStats.minor}.${versionStats.patch}`;
54
+ const entry = result[key] ?? {
55
+ version: {
56
+ major: versionStats.major,
57
+ minor: versionStats.minor,
58
+ patch: versionStats.patch,
59
+ },
60
+ versionString: key,
61
+ downloads: 0,
62
+ };
63
+ result[key] = entry;
64
+ entry.downloads += versionStats.downloads;
65
+ }
66
+ return Object.values(result).sort((a, b) => versionCompare(a.version, b.version));
67
+ }
68
+ export function pickTopStats(stats, top) {
69
+ const sortedStats = stats.sort((a, b) => b.downloads - a.downloads);
70
+ const topStats = sortedStats.slice(0, top);
71
+ return topStats.sort((a, b) => versionCompare(a.version, b.version));
72
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pkg-stats",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Beautiful NPM package download stats",
5
5
  "author": "Maciej Jastrzębski <mdjastrzebski@gmail.com> (https://github.com/mdjastrzebski)",
6
6
  "license": "MIT",