Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@progfay/github-streaks

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@progfay/github-streaks - npm Package Compare versions

Comparing version 1.0.2 to 2.0.0

dist/getCurrentStreak.js

57

dist/getLongestStreak.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const dayPeriodGenerator_1 = require("./lib/dayPeriodGenerator");
exports.getLongestStreak = (since, until) => (contributions) => {
const longestStreak = {
from: null,
to: null,
count: 0
};
const streak = {
from: null,
to: null,
count: 0
};
for (const day of dayPeriodGenerator_1.dayPeriodGenerator(until, since)) {
const key = day.toString();
if (!contributions.has(key))
break;
const contribution = contributions.get(key);
if (contribution === 0) {
if (streak.count > longestStreak.count) {
longestStreak.from = streak.from;
longestStreak.to = streak.to;
longestStreak.count = streak.count;
exports.getLongestStreak = void 0;
const Streak_1 = require("./lib/Streak");
exports.getLongestStreak = contributions => {
let longestStartIndex = -1;
let longestEndIndex = -1;
let startIndex = -1;
let endIndex = -1;
for (let i = 0; i < contributions.length; i++) {
if (contributions[i].count !== 0) {
if (startIndex === -1)
startIndex = i;
endIndex = i;
}
else {
if (startIndex === -1)
continue;
if (longestEndIndex - longestStartIndex <= endIndex - startIndex) {
longestStartIndex = startIndex;
longestEndIndex = endIndex;
}
streak.from = null;
streak.to = null;
streak.count = 0;
continue;
startIndex = -1;
endIndex = -1;
}
streak[streak.to ? 'from' : 'to'] = day;
streak.count++;
}
return streak.count < longestStreak.count ? longestStreak : streak;
if (longestEndIndex - longestStartIndex <= endIndex - startIndex) {
longestStartIndex = startIndex;
longestEndIndex = endIndex;
}
if (longestStartIndex === -1)
return new Streak_1.Streak([]);
return new Streak_1.Streak(contributions.slice(longestStartIndex, longestEndIndex + 1));
};
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const arg_1 = __importDefault(require("arg"));
const chalk_1 = __importDefault(require("chalk"));
const range_1 = require("./lib/range");
const GitHubUser_1 = require("./lib/GitHubUser");
const mergeMap_1 = require("./lib/mergeMap");
const getLongestStreak_1 = require("./getLongestStreak");
const getOngoingStreak_1 = require("./getOngoingStreak");
const Day_1 = require("./lib/Day");
const showStreak_1 = require("./showStreak");
const ARG_OPTIONS = {
'--longest': Boolean,
'--since': String,
'--until': String
};
const getCurrentStreak_1 = require("./getCurrentStreak");
const convertToTable_1 = require("./lib/convertToTable");
const calcContributionsStatistics_1 = require("./lib/calcContributionsStatistics");
const convertStatisticsToRow = (category, statistics) => ({
Category: category,
' From ~ To ': statistics.days > 0 ? `${statistics.from} ~ ${statistics.to}` : '',
'Day Count': statistics.days.toString() + (statistics.days > 1 ? ' days' : ' day '),
Sum: statistics.sum.toString(),
Max: statistics.max.toString(),
Min: statistics.min.toString(),
Median: statistics.median.toFixed(2),
'Std dev': statistics.stddev.toFixed(2)
});
const main = async () => {
const { '--longest': longestFlag = false, '--since': since = '', '--until': until = Day_1.Day.today().toString(), _: [username = ''] } = arg_1.default(ARG_OPTIONS);
const username = process.argv[2];
const user = new GitHubUser_1.GitHubUser(username);
const { created_at: createdAt } = await user.getUserInfo();
const joinedDay = new Day_1.Day(createdAt);
const today = Day_1.Day.today();
const annualDailyContributionsMaps = await Promise.all(range_1.range(joinedDay.getFullYear(), today.getFullYear() + 1)
.map(year => user.getDailyContributions(year)));
const allDailyContributions = mergeMap_1.mergeMap(...annualDailyContributionsMaps);
showStreak_1.showStreak(allDailyContributions, longestFlag
? getLongestStreak_1.getLongestStreak(new Day_1.Day(since || createdAt), new Day_1.Day(until))
: getOngoingStreak_1.getOngoingStreak);
const joinedYear = parseInt(createdAt.substring(0, 4), 10);
const thisYear = new Date().getFullYear();
const annualDailyContributionsMaps = await Promise.all(range_1.range(joinedYear, thisYear + 1)
.map(year => user.getAnnualDailyContributions(year)));
const allDailyContributions = annualDailyContributionsMaps.flat();
const currentStreak = getCurrentStreak_1.getCurrentStreak(allDailyContributions);
const longestStreak = getLongestStreak_1.getLongestStreak(allDailyContributions);
const rows = [
convertStatisticsToRow('All Contributions', calcContributionsStatistics_1.calcContributionsStatistics(allDailyContributions)),
convertStatisticsToRow('Current Streak', currentStreak.statistics),
convertStatisticsToRow('Longest Streak', longestStreak.statistics)
];
const table = convertToTable_1.convertToTable(rows, ['Category', ' From ~ To ', 'Day Count', 'Sum', 'Max', 'Min', 'Median', 'Std dev']);
console.log(table);
};
main()
.catch(({ message }) => {
console.error(chalk_1.default.red(message));
console.error(message);
});

@@ -6,4 +6,5 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const node_fetch_1 = __importDefault(require("node-fetch"));
const fetchElements_1 = require("./fetchElements");
exports.GitHubUser = void 0;
const https_1 = __importDefault(require("https"));
const fast_html_parser_1 = __importDefault(require("fast-html-parser"));
const GITHUB_USERNAME_REGEXP = /^@?[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/i;

@@ -21,24 +22,61 @@ class GitHubUser {

async getUserInfo() {
const response = await node_fetch_1.default(`https://api.github.com/users/${this.username}`);
const information = await response.json();
if (!information.id)
throw Error(information.message || JSON.stringify(information));
return information;
const text = await new Promise((resolve, reject) => {
let text = '';
https_1.default.get({
protocol: 'https:',
hostname: 'api.github.com',
path: `/users/${this.username}`,
headers: { 'User-Agent': '@progfay/github-streaks' }
}, res => {
res.setEncoding('utf-8');
res.on('data', (chunk) => { text += chunk.toString(); });
res.on('end', () => resolve(text));
res.on('error', reject);
});
});
try {
const information = JSON.parse(text);
if (!information.id)
throw Error();
return information;
}
catch {
throw new Error(text);
}
}
async getDailyContributions(year) {
async getAnnualDailyContributions(year) {
if (year <= 0 || !Number.isInteger(year)) {
throw Error('Second argument must be positive integer.');
}
const url = `https://github.com/users/${this.username}/contributions?from=${year}-12-01&to=${year}-12-31`;
const elements = await fetchElements_1.fetchElements(url, 'rect.day');
const html = await new Promise((resolve, reject) => {
let text = '';
https_1.default.get(`https://github.com/users/${this.username}/contributions?from=${year}-12-01&to=${year}-12-31`, res => {
res.setEncoding('utf-8');
res.on('data', (chunk) => { text += chunk.toString(); });
res.on('end', () => resolve(text));
res.on('error', reject);
});
});
const root = fast_html_parser_1.default.parse(html, {
lowerCaseTagName: false,
script: false,
style: false,
pre: false
});
const elements = root.querySelectorAll('rect.day');
if (elements.length === 0)
throw new Error('No contributions found.');
const map = new Map();
const contributions = [];
for (const { attributes } of elements) {
const { 'data-date': date, 'data-count': count } = attributes;
map.set(date, parseInt(count, 10));
if (!date.startsWith(`${year}-`))
continue;
contributions.push({
day: date,
count: parseInt(count, 10)
});
}
return map;
return contributions;
}
}
exports.GitHubUser = GitHubUser;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.range = void 0;
exports.range = (start, end) => {

@@ -4,0 +5,0 @@ if (!Number.isInteger(start) || !Number.isInteger(end)) {

{
"name": "@progfay/github-streaks",
"version": "1.0.2",
"version": "2.0.0",
"description": "Check GitHub streaks from CLI",

@@ -33,24 +33,21 @@ "main": "src/index.ts",

"dependencies": {
"arg": "^4.1.3",
"chalk": "^4.0.0",
"fast-html-parser": "^1.0.1",
"node-fetch": "^2.6.0"
"fast-html-parser": "^1.0.1"
},
"devDependencies": {
"@types/fast-html-parser": "^1.0.0",
"@types/jest": "^25.2.1",
"@types/jest": "^26.0.14",
"@types/node-fetch": "^2.5.7",
"@typescript-eslint/eslint-plugin": "^2.30.0",
"@typescript-eslint/parser": "^2.30.0",
"eslint": "^6.8.0",
"@typescript-eslint/eslint-plugin": "^4.1.1",
"@typescript-eslint/parser": "^4.1.1",
"eslint": "^7.9.0",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-jest": "^23.8.2",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-jest": "^24.0.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"jest": "^25.5.0",
"jest": "^26.4.2",
"jest-fetch-mock": "^3.0.3",
"ts-jest": "^25.4.0",
"typescript": "^3.8.3"
"ts-jest": "^26.3.0",
"typescript": "^4.0.3"
},

@@ -57,0 +54,0 @@ "publishConfig": {

@@ -1,42 +0,53 @@

import arg from 'arg'
import chalk from 'chalk'
import { range } from './lib/range'
import { GitHubUser } from './lib/GitHubUser'
import { mergeMap } from './lib/mergeMap'
import { getLongestStreak } from './getLongestStreak'
import { getOngoingStreak } from './getOngoingStreak'
import { Day } from './lib/Day'
import { showStreak } from './showStreak'
import { getCurrentStreak } from './getCurrentStreak'
import { convertToTable } from './lib/convertToTable'
import { Statistics } from './type'
import { calcContributionsStatistics } from './lib/calcContributionsStatistics'
const ARG_OPTIONS = {
'--longest': Boolean,
'--since': String,
'--until': String
interface Row {
'Category': string
' From ~ To ': string
'Day Count': string
'Sum': string
'Max': string
'Min': string
'Median': string
'Std dev': string
}
const convertStatisticsToRow = (category: string, statistics: Statistics): Row => ({
Category: category,
' From ~ To ': statistics.days > 0 ? `${statistics.from} ~ ${statistics.to}` : '',
'Day Count': statistics.days.toString() + (statistics.days > 1 ? ' days' : ' day '),
Sum: statistics.sum.toString(),
Max: statistics.max.toString(),
Min: statistics.min.toString(),
Median: statistics.median.toFixed(2),
'Std dev': statistics.stddev.toFixed(2)
})
const main = async () => {
const {
'--longest': longestFlag = false,
'--since': since = '',
'--until': until = Day.today().toString(),
_: [username = '']
} = arg(ARG_OPTIONS)
const username = process.argv[2]
const user = new GitHubUser(username)
const { created_at: createdAt } = await user.getUserInfo()
const joinedDay = new Day(createdAt)
const today = Day.today()
const joinedYear = parseInt(createdAt.substring(0, 4), 10)
const thisYear = new Date().getFullYear()
const annualDailyContributionsMaps = await Promise.all(
range(joinedDay.getFullYear(), today.getFullYear() + 1)
.map(year => user.getDailyContributions(year))
range(joinedYear, thisYear + 1)
.map(year => user.getAnnualDailyContributions(year))
)
const allDailyContributions = mergeMap(...annualDailyContributionsMaps)
showStreak(
allDailyContributions,
longestFlag
? getLongestStreak(new Day(since || createdAt), new Day(until))
: getOngoingStreak
)
const allDailyContributions = annualDailyContributionsMaps.flat()
const currentStreak = getCurrentStreak(allDailyContributions)
const longestStreak = getLongestStreak(allDailyContributions)
const rows = [
convertStatisticsToRow('All Contributions', calcContributionsStatistics(allDailyContributions)),
convertStatisticsToRow('Current Streak', currentStreak.statistics),
convertStatisticsToRow('Longest Streak', longestStreak.statistics)
]
const table = convertToTable(rows, ['Category', ' From ~ To ', 'Day Count', 'Sum', 'Max', 'Min', 'Median', 'Std dev'])
console.log(table)
}

@@ -46,3 +57,3 @@

.catch(({ message }) => {
console.error(chalk.red(message))
console.error(message)
})
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc