-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcheck-versions.ts
116 lines (104 loc) · 3 KB
/
check-versions.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
* This script checks if new versions of node modules are available.
* It uses naming conventions to transform constants to matching node module name.
*
* Usage:
* yarn checkversions [file]
*
* Positional arg:
* - [file]: relative or absolute file path to the versions file.
*
* Example:
* yarn checkversions packages/react/src/utils/versions
*/
import { join } from 'path';
import { gt } from 'semver';
import chalk from 'chalk';
import { dasherize } from '../packages/workspace/src/utils/strings';
import * as shell from 'shelljs';
import * as glob from 'glob';
const excluded = ['nxVersion'];
const scoped = [
'babel',
'emotion',
'reduxjs',
'testing-library',
'types',
'zeit',
];
try {
const files = process.argv[2]
? [process.argv[2]]
: glob.sync('packages/**/*/versions.ts');
checkFiles(files);
} catch (e) {
console.log(chalk.red(e.message));
process.exitCode = 1;
}
// -----------------------------------------------------------------------------
function checkFiles(files: string[]) {
console.log(chalk.blue(`Checking versions in the following files...\n`));
console.log(` - ${files.join('\n - ')}\n`);
const maxFileNameLength = Math.max(...files.map((f) => f.length));
files.forEach((f) => {
const versions = getVersions(f);
const npmPackages = getPackages(versions);
const results = npmPackages.map(([p, v]) => getVersionData(p, v));
const logContext = `${f.padEnd(maxFileNameLength)}`;
results.forEach((r) => {
if (r.outdated) {
console.log(
`${logContext} ❗ ${chalk.bold(
r.package
)} has new version ${chalk.bold(r.latest)} (current: ${r.prev})`
);
}
});
});
}
function getVersions(path: string) {
const versionsPath =
path.startsWith('.') || path.startsWith('packages')
? join(__dirname, '..', path)
: path;
try {
return require(versionsPath);
} catch {
throw new Error(`Could not load ${path}. Please make sure it is valid.`);
}
}
function getPackages(versions: Record<string, string>): string[][] {
return Object.entries(versions).reduce((acc, [name, version]) => {
if (!excluded.includes(name)) {
const npmName = getNpmName(name);
acc.push([npmName, version]);
}
return acc;
}, [] as string[][]);
}
function getNpmName(name: string): string {
const dashedName = dasherize(name.replace(/Version$/, ''));
const scope = scoped.find((s) => dashedName.startsWith(`${s}-`));
if (scope) {
const rest = dashedName.split(`${scope}-`)[1];
return `@${scope}/${rest}`;
} else {
return dashedName;
}
}
function getVersionData(
p: string,
v: string
): { package: string; outdated: boolean; latest: string; prev?: string } {
try {
const latest = JSON.parse(
shell.exec(`npm view ${p} version --json --silent`, { silent: true })
);
if (gt(latest, v)) {
return { package: p, outdated: true, latest, prev: v };
}
} catch {
// ignored
}
return { package: p, outdated: false, latest: v };
}