Skip to content

Commit 286d75e

Browse files
authored
feat(ui): Dependencies view (vuejs#1740)
* fix(ui): chrome bug: grid element overflow https://bugs.chromium.org/p/chromium/issues/detail?id=833837 * feat(ui): dependencies view * feat(ui): filter deps
1 parent 6bc5d72 commit 286d75e

27 files changed

+1067
-165
lines changed
Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
const fs = require('fs')
2+
const path = require('path')
3+
const LRU = require('lru-cache')
4+
const semver = require('semver')
5+
// Connectors
6+
const cwd = require('./cwd')
7+
const folders = require('./folders')
8+
const progress = require('./progress')
9+
const logs = require('./logs')
10+
// Context
11+
const getContext = require('../context')
12+
// Utils
13+
const { isPlugin } = require('@vue/cli-shared-utils')
14+
const { resolveModule } = require('@vue/cli/lib/util/module')
15+
const getPackageVersion = require('@vue/cli/lib/util/getPackageVersion')
16+
const {
17+
progress: installProgress,
18+
installPackage,
19+
uninstallPackage,
20+
updatePackage
21+
} = require('@vue/cli/lib/util/installDeps')
22+
const { getCommand } = require('../util/command')
23+
const { resolveModuleRoot } = require('../util/resolve-path')
24+
const { notify } = require('../util/notification')
25+
26+
const PROGRESS_ID = 'dependency-installation'
27+
const CLI_SERVICE = '@vue/cli-service'
28+
29+
// Caches
30+
const metadataCache = new LRU({
31+
max: 200,
32+
maxAge: 1000 * 60 * 30 // 30 min.
33+
})
34+
35+
// Local
36+
let dependencies
37+
38+
function list (file, context) {
39+
const pkg = folders.readPackage(file, context)
40+
dependencies = []
41+
dependencies = dependencies.concat(
42+
findDependencies(pkg.devDependencies || {}, 'devDependencies', context)
43+
)
44+
dependencies = dependencies.concat(
45+
findDependencies(pkg.dependencies || {}, 'dependencies', context)
46+
)
47+
return dependencies
48+
}
49+
50+
function findOne (id, context) {
51+
return dependencies.find(
52+
p => p.id === id
53+
)
54+
}
55+
56+
function findDependencies (deps, type, context) {
57+
return Object.keys(deps).filter(
58+
id => !isPlugin(id) && id !== CLI_SERVICE
59+
).map(
60+
id => ({
61+
id,
62+
versionRange: deps[id],
63+
installed: fs.existsSync(getPath(id)),
64+
website: getLink(id, context),
65+
type
66+
})
67+
)
68+
}
69+
70+
function getPath (id) {
71+
return resolveModuleRoot(resolveModule(path.join(id, 'package.json'), cwd.get()), id)
72+
}
73+
74+
function readPackage (id, context) {
75+
try {
76+
return folders.readPackage(getPath(id), context)
77+
} catch (e) {
78+
console.log(e)
79+
}
80+
return {}
81+
}
82+
83+
function invalidatePackage (id, context) {
84+
return folders.invalidatePackage(getPath(id), context)
85+
}
86+
87+
async function getVersion ({ id, installed, versionRange }, context) {
88+
let current
89+
if (installed) {
90+
const pkg = readPackage(id, context)
91+
current = pkg.version
92+
} else {
93+
current = null
94+
}
95+
let latest, wanted
96+
const metadata = await getMetadata(id, context)
97+
if (metadata) {
98+
latest = metadata['dist-tags'].latest
99+
100+
const versions = Object.keys(metadata.versions)
101+
wanted = semver.maxSatisfying(versions, versionRange)
102+
}
103+
104+
if (!latest) latest = current
105+
if (!wanted) wanted = current
106+
107+
return {
108+
current,
109+
latest,
110+
wanted,
111+
range: versionRange
112+
}
113+
}
114+
115+
async function getDescription ({ id }, context) {
116+
const metadata = await getMetadata(id, context)
117+
if (metadata) {
118+
return metadata.description
119+
}
120+
return null
121+
}
122+
123+
async function getMetadata (id, context) {
124+
let metadata = metadataCache.get(id)
125+
if (metadata) {
126+
return metadata
127+
}
128+
129+
const res = await getPackageVersion(id)
130+
if (res.statusCode === 200) {
131+
metadata = res.body
132+
}
133+
134+
if (metadata) {
135+
metadataCache.set(id, metadata)
136+
return metadata
137+
}
138+
}
139+
140+
function getLink (id, context) {
141+
const pkg = readPackage(id, context)
142+
return pkg.homepage ||
143+
(pkg.repository && pkg.repository.url) ||
144+
`https://www.npmjs.com/package/${id.replace(`/`, `%2F`)}`
145+
}
146+
147+
function install ({ id, type }, context) {
148+
return progress.wrap(PROGRESS_ID, context, async setProgress => {
149+
setProgress({
150+
status: 'dependency-install',
151+
args: [id]
152+
})
153+
await installPackage(cwd.get(), getCommand(), null, id, type === 'devDependencies')
154+
155+
logs.add({
156+
message: `Dependency ${id} installed`,
157+
type: 'info'
158+
}, context)
159+
160+
notify({
161+
title: `Dependency installed`,
162+
message: `Dependency ${id} successfully installed`,
163+
icon: 'done'
164+
})
165+
166+
list(cwd.get(), context)
167+
168+
return findOne(id, context)
169+
})
170+
}
171+
172+
function uninstall ({ id }, context) {
173+
return progress.wrap(PROGRESS_ID, context, async setProgress => {
174+
setProgress({
175+
status: 'dependency-uninstall',
176+
args: [id]
177+
})
178+
179+
const dep = findOne(id, context)
180+
181+
await uninstallPackage(cwd.get(), getCommand(), null, id)
182+
183+
logs.add({
184+
message: `Dependency ${id} uninstalled`,
185+
type: 'info'
186+
}, context)
187+
188+
notify({
189+
title: `Dependency uninstalled`,
190+
message: `Dependency ${id} successfully uninstalled`,
191+
icon: 'done'
192+
})
193+
194+
return dep
195+
})
196+
}
197+
198+
function update ({ id }, context) {
199+
return progress.wrap(PROGRESS_ID, context, async setProgress => {
200+
setProgress({
201+
status: 'dependency-update',
202+
args: [id]
203+
})
204+
205+
const dep = findOne(id, context)
206+
const { current, wanted } = await getVersion(dep, context)
207+
await updatePackage(cwd.get(), getCommand(), null, id)
208+
209+
logs.add({
210+
message: `Dependency ${id} updated from ${current} to ${wanted}`,
211+
type: 'info'
212+
}, context)
213+
214+
notify({
215+
title: `Dependency updated`,
216+
message: `Dependency ${id} was successfully updated`,
217+
icon: 'done'
218+
})
219+
220+
invalidatePackage(id)
221+
222+
return findOne(id)
223+
})
224+
}
225+
226+
function updateAll (context) {
227+
return progress.wrap(PROGRESS_ID, context, async setProgress => {
228+
const deps = list(cwd.get(), context)
229+
let updatedDeps = []
230+
for (const dep of deps) {
231+
const version = await getVersion(dep, context)
232+
if (version.current !== version.wanted) {
233+
updatedDeps.push(dep)
234+
invalidatePackage(dep.id, context)
235+
}
236+
}
237+
238+
if (!updatedDeps.length) {
239+
notify({
240+
title: `No updates available`,
241+
message: `No dependency to update in the version ranges declared in package.json`,
242+
icon: 'done'
243+
})
244+
return []
245+
}
246+
247+
setProgress({
248+
status: 'dependencies-update',
249+
args: [updatedDeps.length]
250+
})
251+
252+
await updatePackage(cwd.get(), getCommand(), null, updatedDeps.map(
253+
p => p.id
254+
).join(' '))
255+
256+
notify({
257+
title: `Dependencies updated`,
258+
message: `${updatedDeps.length} dependencies were successfully updated`,
259+
icon: 'done'
260+
})
261+
262+
return updatedDeps
263+
})
264+
}
265+
266+
function setup (context) {
267+
// Package installation progress events
268+
installProgress.on('progress', value => {
269+
if (progress.get(PROGRESS_ID)) {
270+
progress.set({ id: PROGRESS_ID, progress: value }, context)
271+
}
272+
})
273+
installProgress.on('log', message => {
274+
if (progress.get(PROGRESS_ID)) {
275+
progress.set({ id: PROGRESS_ID, info: message }, context)
276+
}
277+
})
278+
}
279+
280+
setup(getContext())
281+
282+
module.exports = {
283+
list,
284+
findOne,
285+
getPath,
286+
getMetadata,
287+
getLink,
288+
getDescription,
289+
getVersion,
290+
install,
291+
uninstall,
292+
update,
293+
updateAll,
294+
invalidatePackage
295+
}

packages/@vue/cli-ui/apollo-server/connectors/folders.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ function writePackage ({ file, data }, context) {
109109
fs.outputJsonSync(path.join(file, 'package.json'), data, {
110110
spaces: 2
111111
})
112+
invalidatePackage(file)
113+
return true
114+
}
115+
116+
function invalidatePackage (file, context) {
117+
pkgCache.del(file)
112118
return true
113119
}
114120

@@ -165,6 +171,7 @@ module.exports = {
165171
isPackage,
166172
readPackage,
167173
writePackage,
174+
invalidatePackage,
168175
isVueProject,
169176
isFavorite,
170177
listFavorite,

0 commit comments

Comments
 (0)