forked from comunica/comunica
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lerna.js
139 lines (115 loc) · 5.16 KB
/
lerna.js
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
const {loadPackages, exec, iter} = require('lerna-script')
const checkDeps = require('depcheck')
const path = require('path');
const { readFileSync, writeFileSync, readdirSync, readdir } = require('fs');
async function depInfo({ location, name }, log) {
const folders = readdirSync(location, { withFileTypes: true });
const { files } = JSON.parse(readFileSync(path.join(location, 'package.json'), 'utf8'));
let ignore = files ? folders.filter(elem => files.every(file => !file.startsWith(elem.name))) : folders;
ignore = ignore.map(x => x.isDirectory() ? `${x.name}/**` : x.name)
const {dependencies, devDependencies, missing, using} = await checkDeps(location, { ignorePatterns: ignore }, val => val);
return {
unusedDeps: [...dependencies, ...devDependencies].filter(elem => !Object.keys(using).includes(elem)),
missingDeps: Object.keys(missing),
allDeps: Object.keys(using),
}
}
async function depfixTask(log) {
const packages = (await (log.packages || loadPackages())).filter(package => package.location.startsWith(path.join(__dirname, '/packages')));
const resolutions = Object.keys(JSON.parse(readFileSync(path.join(__dirname, 'package.json'), 'utf8')).resolutions ?? {});
await iter.forEach(packages, { log })(async package => {
log.info(package.name)
const { missingDeps, unusedDeps, allDeps } = await depInfo(package);
if (allDeps.includes(package.name))
log.error(' package is a dependency of itself')
if (missingDeps.length > 0) {
try {
log.info(' add:', missingDeps.join(', '))
await exec.command(package)(`yarn add ${missingDeps.join(' ')}`);
} catch (e) {
for (const dep of missingDeps) {
try {
await exec.command(package)(`yarn add ${dep}`);
} catch (e) {
log.error(' CANNOT ADD:', dep);
}
}
}
}
if (unusedDeps.length > 0) {
try {
log.info(' remove:', unusedDeps.join(', '))
await exec.command(package)(`yarn remove ${unusedDeps.join(' ')}`);
} catch (e) {
for (const dep of unusedDeps) {
try {
await exec.command(package)(`yarn remove ${dep}`);
} catch (e) {
log.error(' CANNOT REMOVE:', dep);
}
}
}
}
// Now fix up any resolutions to use a star ("*") import
const packageJson = JSON.parse(readFileSync(path.join(package.location, 'package.json'), 'utf8'));
for (const dep of Object.keys(packageJson.dependencies ?? {})) {
if (resolutions.includes(dep) && packageJson.dependencies[dep] !== '*') {
log.info(' converting to \'*\' import for', dep)
packageJson.dependencies[dep] = '*';
}
}
writeFileSync(path.join(package.location, 'package.json'), JSON.stringify(packageJson, null, 2) + '\n');
})
}
async function depcheckTask(log) {
const packages = (await (log.packages || loadPackages())).filter(package => package.location.startsWith(path.join(__dirname, '/packages')));
const resolutions = Object.keys(JSON.parse(readFileSync(path.join(__dirname, 'package.json'), 'utf8')).resolutions ?? {});
return iter.forEach(packages, { log })(async package => {
const { missingDeps, unusedDeps, allDeps } = await depInfo(package)
if (missingDeps.length > 0) {
throw new Error(`Missing dependencies: ${missingDeps.join(', ')} from ${package.name}`);
}
if (unusedDeps.length > 0) {
throw new Error(`Extra dependencies: ${unusedDeps.join(', ')} in ${package.name}`);
}
if (allDeps.includes(package.name))
throw new Error(`${package.name} is a dependency of itself`);
// Now check all resolutions use a star ("*") import
const packageJson = JSON.parse(readFileSync(path.join(package.location, 'package.json'), 'utf8'));
for (const dep of Object.keys(packageJson.dependencies ?? {})) {
if (resolutions.includes(dep) && packageJson.dependencies[dep] !== '*') {
throw new Error(`Resolution not using \'*\' import for ${dep} in ${package.name}`);
}
}
})
}
module.exports.depfixTask = depfixTask
module.exports.depcheckTask = depcheckTask
const ncu = require('npm-check-updates');
async function updateTask(log) {
const packages = (await (log.packages || loadPackages())).filter(
package => package.location.startsWith(path.join(__dirname, '/packages')) ||
package.location.startsWith(path.join(__dirname, '/engines'))
);
await iter.forEach(packages, { log })(async package => {
const upgraded = await ncu.run({
// Pass any cli option
packageFile: path.join(package.location, 'package.json'),
upgrade: true,
target: 'minor'
});
log.info(package.name, upgraded);
})
}
async function updateTaskMajor(log) {
const packages = (await (log.packages || loadPackages())).filter(package => package.location.startsWith(path.join(__dirname, '/packages')));
await iter.forEach(packages, { log })(async package => {
const upgraded = await ncu.run({
// Pass any cli option
packageFile: path.join(package.location, 'package.json'),
});
log.info(package.name, upgraded);
})
}
module.exports.updateTask = updateTask
module.exports.updateTaskMajor = updateTaskMajor