Skip to content

Commit

Permalink
add release age, fixes #40
Browse files Browse the repository at this point in the history
  • Loading branch information
silverwind committed Mar 8, 2020
1 parent d3aa357 commit 08dbbae
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 8 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@
`updates` is a CLI tool which checks for npm dependency updates of the current project and optionally updates `package.json`. It is highly configurable and is typically able to complete in less than a second.

<p align="center">
<img src="https://i.imgur.com/tI7rp0g.png"/>
</p>
```
$ updates
NAME OLD NEW AGE INFO
p-map 3.0.0 4.0.0 3 days https://github.com/sindresorhus/p-map
rrdir 4.0.0 5.0.0 11 days https://github.com/silverwind/rrdir
eslint 6.7.2 6.8.0 3 months https://github.com/eslint/eslint
eslint-config-silverwind 5.1.1 10.0.0 2 days https://github.com/silverwind/eslint-config-silverwind
rimraf 3.0.0 3.0.2 28 days https://github.com/isaacs/rimraf
versions 7.0.5 8.2.3 1 day https://github.com/silverwind/versions
iltorb 2.4.4 2.4.5 1 month https://github.com/nstepien/iltorb
```

## Usage

Expand Down
Binary file removed screenshot.png
Binary file not shown.
16 changes: 15 additions & 1 deletion test.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,21 @@ function makeTest(args, expected) {
args.split(/\s+/),
{cwd: testDir},
);
return expect(JSON.parse(stdout)).toEqual({results: expected});

const {results} = JSON.parse(stdout);
for (const dependencyType of dependencyTypes) {
for (const [dependencyName, data] of Object.entries(expected[dependencyType] || {})) {
for (const [key, value] of Object.entries(data || {})) {
const resultValue = results[dependencyType][dependencyName][key];
if (key === "age") {
expect(resultValue).toBeInstanceOf(String);
expect(resultValue.length > 0).toBeTruthy();
} else {
expect(resultValue).toEqual(value);
}
}
}
}
};
}

Expand Down
55 changes: 51 additions & 4 deletions updates.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,40 @@ if (!Object.keys(deps).length) {
}
}

const timeData = [
[1e3, 1, "ns", false],
[1e6, 1e3, "µs", false],
[1e9, 1e6, "ms", false],
[60e9, 1e9, "sec", true],
[3600e9, 60e9, "min", true],
[86400e9, 3600e9, "hour", true],
[2592e12, 86400e9, "day", true],
[31536e12, 2592e12, "month", true],
[Infinity, 31536e12, "year", true],
];

function reltime(str) {
if (!str) return "";
const unix = new Date(str).getTime() * 1e6;
if (Number.isNaN(unix)) return "";
const diff = (Date.now() * 1e6) - unix;
if (diff <= 10e9) return "now";

let value, suffix;
for (let i = 0; i <= timeData.length; i++) {
const entry = timeData[i];
const [end, start, unit, addS] = entry || [];
if (entry && end && diff < end) {
value = Math.round(diff / start);
const s = addS ? (value > 1 ? "s" : "") : "";
suffix = `${unit}${s}`;
break;
}
}

return `${value} ${suffix}`;
}

function findSync(filename, dir, stopDir) {
const path = join(dir, filename);

Expand Down Expand Up @@ -398,14 +432,15 @@ function highlightDiff(a, b, added) {
}

function formatDeps() {
const arr = [["NAME", "OLD", "NEW", "INFO"]];
const arr = [["NAME", "OLD", "NEW", "AGE", "INFO"]];

for (const [key, data] of Object.entries(deps)) {
const [_type, name] = key.split(sep);
arr.push([
name,
highlightDiff(data.oldPrint || data.old, data.newPrint || data.new, false),
highlightDiff(data.newPrint || data.new, data.oldPrint || data.old, true),
data.age || "",
data.info,
]);
}
Expand Down Expand Up @@ -549,6 +584,7 @@ function findNewVersion(data, opts) {
}
}

// TODO: refactor this mess
async function checkUrlDep([key, dep], {useGreatest} = {}) {
const stripped = dep.old.replace(stripRe, "");
const [_, user, repo, oldRef] = partsRe.exec(stripped) || [];
Expand All @@ -558,12 +594,20 @@ async function checkUrlDep([key, dep], {useGreatest} = {}) {
const res = await fetch(`https://api.github.com/repos/${user}/${repo}/commits`);
if (!res || !res.ok) return;
const data = await res.json();
let newRef = data.map(entry => entry.sha)[0];
let {sha: newRef, commit} = data[0];
if (!newRef || !newRef.length) return;

let newDate;
if (commit && commit.committer && commit.committer.date) {
newDate = commit.committer.date;
} else if (commit && commit.auhor && commit.author.date) {
newDate = commit.author.date;
}

newRef = newRef.substring(0, oldRef.length);
if (oldRef !== newRef) {
const newRange = dep.old.replace(oldRef, newRef);
return {key, newRange, user, repo, oldRef, newRef};
return {key, newRange, user, repo, oldRef, newRef, newDate};
}
} else {
const res = await fetch(`https://api.github.com/repos/${user}/${repo}/git/refs/tags`);
Expand Down Expand Up @@ -650,6 +694,7 @@ async function main() {
} else {
deps[key].new = newRange;
deps[key].info = getInfoUrl(data.versions[newVersion] || data, registry, data.name);
if (data.time && data.time[newVersion]) deps[key].age = reltime(data.time[newVersion]);
}
}

Expand All @@ -661,14 +706,16 @@ async function main() {
}));
results = results.filter(r => !!r);
for (const res of results || []) {
const {key, newRange, user, repo, oldRef, newRef} = res;
const {key, newRange, user, repo, oldRef, newRef, newDate} = res;
deps[key] = {
old: maybeUrlDeps[key].old,
new: newRange,
oldPrint: hashRe.test(oldRef) ? oldRef.substring(0, 7) : oldRef,
newPrint: hashRe.test(newRef) ? newRef.substring(0, 7) : newRef,
info: `https://github.com/${user}/${repo}`,
};

if (newDate) deps[key].age = reltime(newDate);
}
}

Expand Down

0 comments on commit 08dbbae

Please sign in to comment.