UNPKG

3.98 kBJavaScriptView Raw
1'use strict';
2const util = require('util');
3const fs = require('fs');
4const path = require('path');
5const chalk = require('chalk');
6const os = require('os');
7const spawn = require('cross-spawn');
8const PEERS = /UNMET PEER DEPENDENCY ([a-z\-0-9\.]+)@(.+)/gm;
9
10exports.requireModule = (name, modules) => {
11 if (typeof name === 'object') {
12 return name;
13 }
14 if (path.isAbsolute(name)) {
15 return require(name);
16 }
17
18 const module = modules.find(m => {
19 const modulepath = path.join(m, name);
20 return fs.existsSync(modulepath);
21 });
22 return module ? require(path.join(module, name)) : null;
23};
24
25exports.isInstalled = (name, modules) => {
26 return !!exports.requireModule(name, modules);
27};
28
29exports.install = (deps, modules, options, type) => {
30
31 if (!deps || !deps.length) {
32 return;
33 }
34
35 console.log(chalk.green(`easywebpack: install webpack dynamic ${type} npm module:\r\n`), deps);
36
37 options = Object.assign({}, { save: true, dev: true, quiet: false, npm: 'npm' }, options);
38
39 const args = ['install'].concat(deps).filter(Boolean);
40
41 if (options.save) {
42 args.push(options.dev ? '--save-dev' : '--save');
43 }
44
45 if (options.quiet) {
46 args.push('--silent', '--no-progress');
47 }
48
49 // Ignore input, capture output, show errors
50 const output = spawn.sync(options.npm, args, {
51 stdio: ['ignore', 'pipe', 'inherit']
52 });
53
54 let matches;
55 const peersDeps = [];
56 if (os.platform() === 'regex_test') { // windows not match PEERS
57 // RegExps track return a single result each time
58 while (matches = PEERS.exec(output.stdout)) {
59 const dep = matches[1];
60 const version = matches[2];
61 if (!exports.isInstalled(dep, modules)) {
62 if (version.match(' ')) {
63 peersDeps.push(dep);
64 } else {
65 peersDeps.push(util.format('%s@%s', dep, version));
66 }
67 }
68 }
69 } else {
70 deps.forEach(dep => {
71 const name = dep.split('@')[0];
72 const module = modules.find(m => {
73 const modulepath = path.join(m, name);
74 return fs.existsSync(modulepath);
75 });
76 if (module) {
77 const pkgpath = path.join(module, name, 'package.json');
78 const pkg = require(pkgpath);
79 const peerDependencies = pkg.peerDependencies;
80 if (peerDependencies) {
81 Object.keys(peerDependencies).forEach(pkgName => {
82 if (!exports.isInstalled(pkgName, modules)) {
83 peersDeps.push(`${pkgName}@${peerDependencies[pkgName]}`);
84 }
85 });
86 }
87 }
88 });
89 }
90
91 if (peersDeps.length) {
92 return this.install(peersDeps, modules, options, 'peer');
93 }
94
95 return deps.length;
96};
97
98exports.getDeps = (configDeps, defaultDeps) => {
99 const deps = Object.assign({}, defaultDeps);
100 if (configDeps) {
101 Object.keys(configDeps).forEach(name => {
102 deps[name] = configDeps[name];
103 });
104 }
105 return deps;
106};
107
108exports.installLoader = (rules, deps, modules, options = {}) => {
109 if (options.check === false) {
110 return;
111 }
112 const pkgs = [];
113 rules.forEach(rule => {
114 if (Array.isArray(rule.use)) {
115 rule.use.forEach(loader => {
116 const name = typeof loader === 'object' ? loader.loader : loader;
117 if (!exports.isInstalled(name, modules)) {
118 const pkg = deps[name] ? `${name}@${deps[name]}` : name;
119 if (!pkgs.includes(pkg)) {
120 pkgs.push(pkg);
121 }
122 }
123 });
124 }
125 });
126 return exports.install(pkgs, modules, options, 'loader');
127};
128
129exports.installPlugin = (plugins, deps, modules, options = {}) => {
130 if (options.check === false) {
131 return;
132 }
133 const pkgs = [];
134 Object.keys(plugins).forEach(key => {
135 const name = plugins[key].name;
136 if (typeof name === 'string') {
137 if (!exports.isInstalled(name, modules)) {
138 const pkg = deps[name] ? `${name}@${deps[name]}` : name;
139 if (!pkgs.includes(pkg)) {
140 pkgs.push(pkg);
141 }
142 }
143 }
144 });
145 return exports.install(pkgs, modules, options, 'plugin');
146};
\No newline at end of file