-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
94 lines (87 loc) · 3.38 KB
/
index.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
'use strict'
const fs = require('fs')
const path = require('path')
const latestVersion = require('latest-version')
const semver = require('semver')
function readPackageJson (dir, ignoreNotFound) {
const file = path.join(dir, 'package.json')
return new Promise((resolve, reject) => {
fs.readFile(file, 'utf8', (err, data) => {
if (err) {
if (err.code === 'ENOENT') {
if (ignoreNotFound) return resolve()
err = `File ${file} does not exist :(`
}
return reject(err)
}
try {
resolve(JSON.parse(data))
} catch (e) {
reject(e)
}
})
})
}
function addArray (deps, array, type) {
let dep
for (let i = 0, len = array.length; i < len; i++) {
dep = deps.find(d => d.name === array[i])
if (dep) dep.types.push(type)
else deps.push({ types: [type], name: array[i], semver: 'unknown' })
}
}
function addObject (deps, obj, type) {
let dep
for (const [name, semver] of Object.entries(obj)) {
dep = deps.find(d => d.name === name)
if (dep) dep.types.push(type)
else deps.push({ types: [type], name, semver })
}
}
module.exports = function cies (opts) {
opts = opts || {}
const baseDir = opts.dir || process.cwd()
return readPackageJson(baseDir).then(pkg => {
const deps = []
if (pkg.dependencies && (opts.all || !opts.exclusive)) addObject(deps, pkg.dependencies, 'prod')
if (pkg.devDependencies && (opts.all || opts.dev)) addObject(deps, pkg.devDependencies, 'dev')
if (pkg.peerDependencies && (opts.all || opts.peer)) addObject(deps, pkg.peerDependencies, 'peer')
if ((pkg.bundledDependencies || pkg.bundleDependencies) && (opts.all || opts.bundled)) addArray(deps, pkg.bundledDependencies || pkg.bundleDependencies, 'bundled')
if (pkg.optionalDependencies && (opts.all || opts.optional)) addObject(deps, pkg.optionalDependencies, 'optional')
if (opts.sort) deps.sort((a, b) => a.name.localeCompare(b.name))
return deps
}).then(deps => {
if ((!opts.versions || (opts.terse && !opts.command)) && !opts.major && !opts.minor && !opts.patch) return deps
const promises = []
let scopeName
deps.forEach(d => {
scopeName = d.name.split('/')
promises.push(Promise.all([
readPackageJson(path.join(baseDir, 'node_modules', scopeName[0], scopeName[1] || ''), true),
latestVersion(d.name)
]))
})
return Promise.all(promises).then(pkgs => {
let pkgJson, latest
for (let i = 0, len = pkgs.length; i < len; i++) {
[pkgJson, latest] = pkgs[i]
deps[i].version = (pkgJson && pkgJson.version) || 'not installed'
deps[i].latest = latest || 'no latest'
if ((deps[i].version !== 'not installed' || deps[i].semver !== 'unknown') && deps[i].latest !== 'no latest') {
if (deps[i].version !== 'not installed') deps[i].diff = semver.diff(deps[i].version, deps[i].latest)
else deps[i].diff = semver.satisfies(deps[i].latest, deps[i].semver) ? 'in-range' : 'out-of-range'
} else {
deps[i].diff = '¯\\_(ツ)_/¯'
}
}
if (opts.major || opts.minor || opts.patch) {
const matches = [/out/, /ツ/]
if (opts.major) matches.push(/major/)
if (opts.minor) matches.push(/minor/)
if (opts.patch) matches.push(/patch/)
return deps.filter(d => matches.some(regex => regex.test(d.diff)))
}
return deps
})
})
}