UNPKG

2.83 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2013-present, Facebook, Inc.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8'use strict';
9
10var PluginError = require('plugin-error');
11var colors = require('ansi-colors');
12var fancyLog = require('fancy-log');
13var path = require('path');
14var semver = require('semver');
15var spawn = require('cross-spawn');
16var through = require('through2');
17
18var PLUGIN_NAME = 'check-dependencies';
19
20module.exports = function(opts) {
21 function read(file, enc, cb) {
22 var cwd = path.dirname(file.path);
23 var pkgData = JSON.parse(file.contents.toString());
24 var outdated = spawn(
25 'yarn',
26 ['outdated', '--json'],
27 { cwd: cwd }
28 );
29 var data = '';
30
31 outdated.stdout.on('data', function(chunk) {
32 data += chunk.toString();
33 });
34
35 outdated.on('exit', function(code) {
36 try {
37 // Parse the yarn outdated format (http://jsonlines.org/)
38 var outdatedData = data
39 .split('\n')
40 .filter(Boolean)
41 .map(d => JSON.parse(d))
42 .filter(j => j.type === 'table')[0].data;
43 } catch (e) {
44 console.log('error', e)
45 cb(new PluginError(PLUGIN_NAME, 'npm broke'));
46 }
47
48 // Convert ["Package", "Current",...] to {"Package": 0, ...}
49 const name2idx = {};
50 outdatedData.head.forEach((key, idx) => name2idx[key] = idx);
51 const {
52 Package: NAME,
53 Current: CURRENT,
54 "Package Type": TYPE
55 } = name2idx;
56
57 var failures = [];
58 outdatedData.body.forEach(function(row) {
59 var name = row[NAME];
60 var current = row[CURRENT];
61 var type = row[TYPE];
62 var pkgDeps = pkgData[type];
63
64 if (!pkgDeps) {
65 fancyLog(`Found missing dependency category ${type}.`);
66 return;
67 }
68
69 var requested = pkgDeps[name];
70
71 if (!requested) {
72 fancyLog('Found extraneous outdated dependency. Consider running `npm prune`');
73 return;
74 }
75
76 if (!requested.startsWith('file:') && !semver.satisfies(current, requested)) {
77 // Definitely wrong, so we should error
78 failures.push({name, current, requested});
79 }
80 });
81
82 if (failures.length) {
83 failures.forEach((failure) => {
84 fancyLog(
85 `${colors.bold(failure.name)} is outdated ` +
86 `(${colors.red(failure.current)} does not satisfy ` +
87 `${colors.yellow(failure.requested)})`
88 );
89 });
90 var msg =
91 'Some of your dependencies are outdated. Please run ' +
92 `${colors.bold('npm update')} to ensure you are up to date.`;
93 cb(new PluginError(PLUGIN_NAME, msg));
94 return;
95 }
96
97 cb();
98 });
99 }
100
101 return through.obj(read);
102};