react-zutils 1.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of react-zutils might be problematic. Click here for more details.

@@ -0,0 +1,156 @@
1
+ /**
2
+ * Copyright (c) 2015-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
+
10
+ var fs = require('fs');
11
+ var path = require('path');
12
+ var chalk = require('chalk');
13
+ var filesize = require('filesize');
14
+ var recursive = require('recursive-readdir');
15
+ var stripAnsi = require('strip-ansi');
16
+ var gzipSize = require('gzip-size').sync;
17
+
18
+ function canReadAsset(asset) {
19
+ return (
20
+ /\.(js|css)$/.test(asset) &&
21
+ !/service-worker\.js/.test(asset) &&
22
+ !/precache-manifest\.[0-9a-f]+\.js/.test(asset)
23
+ );
24
+ }
25
+
26
+ // Prints a detailed summary of build files.
27
+ function printFileSizesAfterBuild(
28
+ webpackStats,
29
+ previousSizeMap,
30
+ buildFolder,
31
+ maxBundleGzipSize,
32
+ maxChunkGzipSize
33
+ ) {
34
+ var root = previousSizeMap.root;
35
+ var sizes = previousSizeMap.sizes;
36
+ var assets = (webpackStats.stats || [webpackStats])
37
+ .map(stats =>
38
+ stats
39
+ .toJson({ all: false, assets: true })
40
+ .assets.filter(asset => canReadAsset(asset.name))
41
+ .map(asset => {
42
+ var fileContents = fs.readFileSync(path.join(root, asset.name));
43
+ var size = gzipSize(fileContents);
44
+ var previousSize = sizes[removeFileNameHash(root, asset.name)];
45
+ var difference = getDifferenceLabel(size, previousSize);
46
+ return {
47
+ folder: path.join(
48
+ path.basename(buildFolder),
49
+ path.dirname(asset.name)
50
+ ),
51
+ name: path.basename(asset.name),
52
+ size: size,
53
+ sizeLabel:
54
+ filesize(size) + (difference ? ' (' + difference + ')' : ''),
55
+ };
56
+ })
57
+ )
58
+ .reduce((single, all) => all.concat(single), []);
59
+ assets.sort((a, b) => b.size - a.size);
60
+ var longestSizeLabelLength = Math.max.apply(
61
+ null,
62
+ assets.map(a => stripAnsi(a.sizeLabel).length)
63
+ );
64
+ var suggestBundleSplitting = false;
65
+ assets.forEach(asset => {
66
+ var sizeLabel = asset.sizeLabel;
67
+ var sizeLength = stripAnsi(sizeLabel).length;
68
+ if (sizeLength < longestSizeLabelLength) {
69
+ var rightPadding = ' '.repeat(longestSizeLabelLength - sizeLength);
70
+ sizeLabel += rightPadding;
71
+ }
72
+ var isMainBundle = asset.name.indexOf('main.') === 0;
73
+ var maxRecommendedSize = isMainBundle
74
+ ? maxBundleGzipSize
75
+ : maxChunkGzipSize;
76
+ var isLarge = maxRecommendedSize && asset.size > maxRecommendedSize;
77
+ if (isLarge && path.extname(asset.name) === '.js') {
78
+ suggestBundleSplitting = true;
79
+ }
80
+ console.log(
81
+ ' ' +
82
+ (isLarge ? chalk.yellow(sizeLabel) : sizeLabel) +
83
+ ' ' +
84
+ chalk.dim(asset.folder + path.sep) +
85
+ chalk.cyan(asset.name)
86
+ );
87
+ });
88
+ if (suggestBundleSplitting) {
89
+ console.log();
90
+ console.log(
91
+ chalk.yellow('The bundle size is significantly larger than recommended.')
92
+ );
93
+ console.log(
94
+ chalk.yellow(
95
+ 'Consider reducing it with code splitting: https://goo.gl/9VhYWB'
96
+ )
97
+ );
98
+ console.log(
99
+ chalk.yellow(
100
+ 'You can also analyze the project dependencies: https://goo.gl/LeUzfb'
101
+ )
102
+ );
103
+ }
104
+ }
105
+
106
+ function removeFileNameHash(buildFolder, fileName) {
107
+ return fileName
108
+ .replace(buildFolder, '')
109
+ .replace(/\\/g, '/')
110
+ .replace(
111
+ /\/?(.*)(\.[0-9a-f]+)(\.chunk)?(\.js|\.css)/,
112
+ (match, p1, p2, p3, p4) => p1 + p4
113
+ );
114
+ }
115
+
116
+ // Input: 1024, 2048
117
+ // Output: "(+1 KB)"
118
+ function getDifferenceLabel(currentSize, previousSize) {
119
+ var FIFTY_KILOBYTES = 1024 * 50;
120
+ var difference = currentSize - previousSize;
121
+ var fileSize = !Number.isNaN(difference) ? filesize(difference) : 0;
122
+ if (difference >= FIFTY_KILOBYTES) {
123
+ return chalk.red('+' + fileSize);
124
+ } else if (difference < FIFTY_KILOBYTES && difference > 0) {
125
+ return chalk.yellow('+' + fileSize);
126
+ } else if (difference < 0) {
127
+ return chalk.green(fileSize);
128
+ } else {
129
+ return '';
130
+ }
131
+ }
132
+
133
+ function measureFileSizesBeforeBuild(buildFolder) {
134
+ return new Promise(resolve => {
135
+ recursive(buildFolder, (err, fileNames) => {
136
+ var sizes;
137
+ if (!err && fileNames) {
138
+ sizes = fileNames.filter(canReadAsset).reduce((memo, fileName) => {
139
+ var contents = fs.readFileSync(fileName);
140
+ var key = removeFileNameHash(buildFolder, fileName);
141
+ memo[key] = gzipSize(contents);
142
+ return memo;
143
+ }, {});
144
+ }
145
+ resolve({
146
+ root: buildFolder,
147
+ sizes: sizes || {},
148
+ });
149
+ });
150
+ });
151
+ }
152
+
153
+ module.exports = {
154
+ measureFileSizesBeforeBuild: measureFileSizesBeforeBuild,
155
+ printFileSizesAfterBuild: printFileSizesAfterBuild,
156
+ };
package/README.md ADDED
@@ -0,0 +1,8 @@
1
+ # My Node Library
2
+
3
+ A simple Node.js library.
4
+
5
+ ## Installation
6
+
7
+ ```sh
8
+ npm install react-zutils
@@ -0,0 +1,500 @@
1
+ /**
2
+ * Copyright (c) 2015-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
+ 'use strict';
8
+
9
+ const address = require('address');
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+ const url = require('url');
13
+ const chalk = require('chalk');
14
+ const detect = require('detect-port-alt');
15
+ const isRoot = require('is-root');
16
+ const prompts = require('prompts');
17
+ const clearConsole = require('./clearConsole');
18
+ const formatWebpackMessages = require('./formatWebpackMessages');
19
+ const getProcessForPort = require('./getProcessForPort');
20
+ const typescriptFormatter = require('./typescriptFormatter');
21
+ const forkTsCheckerWebpackPlugin = require('./ForkTsCheckerWebpackPlugin');
22
+
23
+ const isInteractive = process.stdout.isTTY;
24
+
25
+ function prepareUrls(protocol, host, port, pathname = '/') {
26
+ const formatUrl = hostname =>
27
+ url.format({
28
+ protocol,
29
+ hostname,
30
+ port,
31
+ pathname,
32
+ });
33
+ const prettyPrintUrl = hostname =>
34
+ url.format({
35
+ protocol,
36
+ hostname,
37
+ port: chalk.bold(port),
38
+ pathname,
39
+ });
40
+
41
+ const isUnspecifiedHost = host === '0.0.0.0' || host === '::';
42
+ let prettyHost, lanUrlForConfig, lanUrlForTerminal;
43
+ if (isUnspecifiedHost) {
44
+ prettyHost = 'localhost';
45
+ try {
46
+ // This can only return an IPv4 address
47
+ lanUrlForConfig = address.ip();
48
+ if (lanUrlForConfig) {
49
+ // Check if the address is a private ip
50
+ // https://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces
51
+ if (
52
+ /^10[.]|^172[.](1[6-9]|2[0-9]|3[0-1])[.]|^192[.]168[.]/.test(
53
+ lanUrlForConfig
54
+ )
55
+ ) {
56
+ // Address is private, format it for later use
57
+ lanUrlForTerminal = prettyPrintUrl(lanUrlForConfig);
58
+ } else {
59
+ // Address is not private, so we will discard it
60
+ lanUrlForConfig = undefined;
61
+ }
62
+ }
63
+ } catch (_e) {
64
+ // ignored
65
+ }
66
+ } else {
67
+ prettyHost = host;
68
+ }
69
+ const localUrlForTerminal = prettyPrintUrl(prettyHost);
70
+ const localUrlForBrowser = formatUrl(prettyHost);
71
+ return {
72
+ lanUrlForConfig,
73
+ lanUrlForTerminal,
74
+ localUrlForTerminal,
75
+ localUrlForBrowser,
76
+ };
77
+ }
78
+
79
+ function printInstructions(appName, urls, useYarn) {
80
+ console.log();
81
+ console.log(`You can now view ${chalk.bold(appName)} in the browser.`);
82
+ console.log();
83
+
84
+ if (urls.lanUrlForTerminal) {
85
+ console.log(
86
+ ` ${chalk.bold('Local:')} ${urls.localUrlForTerminal}`
87
+ );
88
+ console.log(
89
+ ` ${chalk.bold('On Your Network:')} ${urls.lanUrlForTerminal}`
90
+ );
91
+ } else {
92
+ console.log(` ${urls.localUrlForTerminal}`);
93
+ }
94
+
95
+ console.log();
96
+ console.log('Note that the development build is not optimized.');
97
+ console.log(
98
+ `To create a production build, use ` +
99
+ `${chalk.cyan(`${useYarn ? 'yarn' : 'npm run'} build`)}.`
100
+ );
101
+ console.log();
102
+ }
103
+
104
+ function createCompiler({
105
+ appName,
106
+ config,
107
+ devSocket,
108
+ urls,
109
+ useYarn,
110
+ useTypeScript,
111
+ tscCompileOnError,
112
+ webpack,
113
+ }) {
114
+ // "Compiler" is a low-level interface to webpack.
115
+ // It lets us listen to some events and provide our own custom messages.
116
+ let compiler;
117
+ try {
118
+ compiler = webpack(config);
119
+ } catch (err) {
120
+ console.log(chalk.red('Failed to compile.'));
121
+ console.log();
122
+ console.log(err.message || err);
123
+ console.log();
124
+ process.exit(1);
125
+ }
126
+
127
+ // "invalid" event fires when you have changed a file, and webpack is
128
+ // recompiling a bundle. WebpackDevServer takes care to pause serving the
129
+ // bundle, so if you refresh, it'll wait instead of serving the old one.
130
+ // "invalid" is short for "bundle invalidated", it doesn't imply any errors.
131
+ compiler.hooks.invalid.tap('invalid', () => {
132
+ if (isInteractive) {
133
+ clearConsole();
134
+ }
135
+ console.log('Compiling...');
136
+ });
137
+
138
+ let isFirstCompile = true;
139
+ let tsMessagesPromise;
140
+ let tsMessagesResolver;
141
+
142
+ if (useTypeScript) {
143
+ compiler.hooks.beforeCompile.tap('beforeCompile', () => {
144
+ tsMessagesPromise = new Promise(resolve => {
145
+ tsMessagesResolver = msgs => resolve(msgs);
146
+ });
147
+ });
148
+
149
+ forkTsCheckerWebpackPlugin
150
+ .getCompilerHooks(compiler)
151
+ .receive.tap('afterTypeScriptCheck', (diagnostics, lints) => {
152
+ const allMsgs = [...diagnostics, ...lints];
153
+ const format = message =>
154
+ `${message.file}\n${typescriptFormatter(message, true)}`;
155
+
156
+ tsMessagesResolver({
157
+ errors: allMsgs.filter(msg => msg.severity === 'error').map(format),
158
+ warnings: allMsgs
159
+ .filter(msg => msg.severity === 'warning')
160
+ .map(format),
161
+ });
162
+ });
163
+ }
164
+
165
+ // "done" event fires when webpack has finished recompiling the bundle.
166
+ // Whether or not you have warnings or errors, you will get this event.
167
+ compiler.hooks.done.tap('done', async stats => {
168
+ if (isInteractive) {
169
+ clearConsole();
170
+ }
171
+
172
+ // We have switched off the default webpack output in WebpackDevServer
173
+ // options so we are going to "massage" the warnings and errors and present
174
+ // them in a readable focused way.
175
+ // We only construct the warnings and errors for speed:
176
+ // https://github.com/facebook/create-react-app/issues/4492#issuecomment-421959548
177
+ const statsData = stats.toJson({
178
+ all: false,
179
+ warnings: true,
180
+ errors: true,
181
+ });
182
+
183
+ if (useTypeScript && statsData.errors.length === 0) {
184
+ const delayedMsg = setTimeout(() => {
185
+ console.log(
186
+ chalk.yellow(
187
+ 'Files successfully emitted, waiting for typecheck results...'
188
+ )
189
+ );
190
+ }, 100);
191
+
192
+ const messages = await tsMessagesPromise;
193
+ clearTimeout(delayedMsg);
194
+ if (tscCompileOnError) {
195
+ statsData.warnings.push(...messages.errors);
196
+ } else {
197
+ statsData.errors.push(...messages.errors);
198
+ }
199
+ statsData.warnings.push(...messages.warnings);
200
+
201
+ // Push errors and warnings into compilation result
202
+ // to show them after page refresh triggered by user.
203
+ if (tscCompileOnError) {
204
+ stats.compilation.warnings.push(...messages.errors);
205
+ } else {
206
+ stats.compilation.errors.push(...messages.errors);
207
+ }
208
+ stats.compilation.warnings.push(...messages.warnings);
209
+
210
+ if (messages.errors.length > 0) {
211
+ if (tscCompileOnError) {
212
+ devSocket.warnings(messages.errors);
213
+ } else {
214
+ devSocket.errors(messages.errors);
215
+ }
216
+ } else if (messages.warnings.length > 0) {
217
+ devSocket.warnings(messages.warnings);
218
+ }
219
+
220
+ if (isInteractive) {
221
+ clearConsole();
222
+ }
223
+ }
224
+
225
+ const messages = formatWebpackMessages(statsData);
226
+ const isSuccessful = !messages.errors.length && !messages.warnings.length;
227
+ if (isSuccessful) {
228
+ console.log(chalk.green('Compiled successfully!'));
229
+ }
230
+ if (isSuccessful && (isInteractive || isFirstCompile)) {
231
+ printInstructions(appName, urls, useYarn);
232
+ }
233
+ isFirstCompile = false;
234
+
235
+ // If errors exist, only show errors.
236
+ if (messages.errors.length) {
237
+ // Only keep the first error. Others are often indicative
238
+ // of the same problem, but confuse the reader with noise.
239
+ if (messages.errors.length > 1) {
240
+ messages.errors.length = 1;
241
+ }
242
+ console.log(chalk.red('Failed to compile.\n'));
243
+ console.log(messages.errors.join('\n\n'));
244
+ return;
245
+ }
246
+
247
+ // Show warnings if no errors were found.
248
+ if (messages.warnings.length) {
249
+ console.log(chalk.yellow('Compiled with warnings.\n'));
250
+ console.log(messages.warnings.join('\n\n'));
251
+
252
+ // Teach some ESLint tricks.
253
+ console.log(
254
+ '\nSearch for the ' +
255
+ chalk.underline(chalk.yellow('keywords')) +
256
+ ' to learn more about each warning.'
257
+ );
258
+ console.log(
259
+ 'To ignore, add ' +
260
+ chalk.cyan('// eslint-disable-next-line') +
261
+ ' to the line before.\n'
262
+ );
263
+ }
264
+ });
265
+
266
+ // You can safely remove this after ejecting.
267
+ // We only use this block for testing of Create React App itself:
268
+ const isSmokeTest = process.argv.some(
269
+ arg => arg.indexOf('--smoke-test') > -1
270
+ );
271
+ if (isSmokeTest) {
272
+ compiler.hooks.failed.tap('smokeTest', async () => {
273
+ await tsMessagesPromise;
274
+ process.exit(1);
275
+ });
276
+ compiler.hooks.done.tap('smokeTest', async stats => {
277
+ await tsMessagesPromise;
278
+ if (stats.hasErrors() || stats.hasWarnings()) {
279
+ process.exit(1);
280
+ } else {
281
+ process.exit(0);
282
+ }
283
+ });
284
+ }
285
+
286
+ return compiler;
287
+ }
288
+
289
+ function resolveLoopback(proxy) {
290
+ const o = url.parse(proxy);
291
+ o.host = undefined;
292
+ if (o.hostname !== 'localhost') {
293
+ return proxy;
294
+ }
295
+ // Unfortunately, many languages (unlike node) do not yet support IPv6.
296
+ // This means even though localhost resolves to ::1, the application
297
+ // must fall back to IPv4 (on 127.0.0.1).
298
+ // We can re-enable this in a few years.
299
+ /*try {
300
+ o.hostname = address.ipv6() ? '::1' : '127.0.0.1';
301
+ } catch (_ignored) {
302
+ o.hostname = '127.0.0.1';
303
+ }*/
304
+
305
+ try {
306
+ // Check if we're on a network; if we are, chances are we can resolve
307
+ // localhost. Otherwise, we can just be safe and assume localhost is
308
+ // IPv4 for maximum compatibility.
309
+ if (!address.ip()) {
310
+ o.hostname = '127.0.0.1';
311
+ }
312
+ } catch (_ignored) {
313
+ o.hostname = '127.0.0.1';
314
+ }
315
+ return url.format(o);
316
+ }
317
+
318
+ // We need to provide a custom onError function for httpProxyMiddleware.
319
+ // It allows us to log custom error messages on the console.
320
+ function onProxyError(proxy) {
321
+ return (err, req, res) => {
322
+ const host = req.headers && req.headers.host;
323
+ console.log(
324
+ chalk.red('Proxy error:') +
325
+ ' Could not proxy request ' +
326
+ chalk.cyan(req.url) +
327
+ ' from ' +
328
+ chalk.cyan(host) +
329
+ ' to ' +
330
+ chalk.cyan(proxy) +
331
+ '.'
332
+ );
333
+ console.log(
334
+ 'See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (' +
335
+ chalk.cyan(err.code) +
336
+ ').'
337
+ );
338
+ console.log();
339
+
340
+ // And immediately send the proper error response to the client.
341
+ // Otherwise, the request will eventually timeout with ERR_EMPTY_RESPONSE on the client side.
342
+ if (res.writeHead && !res.headersSent) {
343
+ res.writeHead(500);
344
+ }
345
+ res.end(
346
+ 'Proxy error: Could not proxy request ' +
347
+ req.url +
348
+ ' from ' +
349
+ host +
350
+ ' to ' +
351
+ proxy +
352
+ ' (' +
353
+ err.code +
354
+ ').'
355
+ );
356
+ };
357
+ }
358
+
359
+ function prepareProxy(proxy, appPublicFolder, servedPathname) {
360
+ // `proxy` lets you specify alternate servers for specific requests.
361
+ if (!proxy) {
362
+ return undefined;
363
+ }
364
+ if (typeof proxy !== 'string') {
365
+ console.log(
366
+ chalk.red('When specified, "proxy" in package.json must be a string.')
367
+ );
368
+ console.log(
369
+ chalk.red('Instead, the type of "proxy" was "' + typeof proxy + '".')
370
+ );
371
+ console.log(
372
+ chalk.red('Either remove "proxy" from package.json, or make it a string.')
373
+ );
374
+ process.exit(1);
375
+ }
376
+
377
+ // If proxy is specified, let it handle any request except for
378
+ // files in the public folder and requests to the WebpackDevServer socket endpoint.
379
+ // https://github.com/facebook/create-react-app/issues/6720
380
+ const sockPath = process.env.WDS_SOCKET_PATH || '/sockjs-node';
381
+ const isDefaultSockHost = !process.env.WDS_SOCKET_HOST;
382
+ function mayProxy(pathname) {
383
+ const maybePublicPath = path.resolve(
384
+ appPublicFolder,
385
+ pathname.replace(new RegExp('^' + servedPathname), '')
386
+ );
387
+ const isPublicFileRequest = fs.existsSync(maybePublicPath);
388
+ // used by webpackHotDevClient
389
+ const isWdsEndpointRequest =
390
+ isDefaultSockHost && pathname.startsWith(sockPath);
391
+ return !(isPublicFileRequest || isWdsEndpointRequest);
392
+ }
393
+
394
+ if (!/^http(s)?:\/\//.test(proxy)) {
395
+ console.log(
396
+ chalk.red(
397
+ 'When "proxy" is specified in package.json it must start with either http:// or https://'
398
+ )
399
+ );
400
+ process.exit(1);
401
+ }
402
+
403
+ let target;
404
+ if (process.platform === 'win32') {
405
+ target = resolveLoopback(proxy);
406
+ } else {
407
+ target = proxy;
408
+ }
409
+ return [
410
+ {
411
+ target,
412
+ logLevel: 'silent',
413
+ // For single page apps, we generally want to fallback to /index.html.
414
+ // However we also want to respect `proxy` for API calls.
415
+ // So if `proxy` is specified as a string, we need to decide which fallback to use.
416
+ // We use a heuristic: We want to proxy all the requests that are not meant
417
+ // for static assets and as all the requests for static assets will be using
418
+ // `GET` method, we can proxy all non-`GET` requests.
419
+ // For `GET` requests, if request `accept`s text/html, we pick /index.html.
420
+ // Modern browsers include text/html into `accept` header when navigating.
421
+ // However API calls like `fetch()` won’t generally accept text/html.
422
+ // If this heuristic doesn’t work well for you, use `src/setupProxy.js`.
423
+ context: function (pathname, req) {
424
+ return (
425
+ req.method !== 'GET' ||
426
+ (mayProxy(pathname) &&
427
+ req.headers.accept &&
428
+ req.headers.accept.indexOf('text/html') === -1)
429
+ );
430
+ },
431
+ onProxyReq: proxyReq => {
432
+ // Browsers may send Origin headers even with same-origin
433
+ // requests. To prevent CORS issues, we have to change
434
+ // the Origin to match the target URL.
435
+ if (proxyReq.getHeader('origin')) {
436
+ proxyReq.setHeader('origin', target);
437
+ }
438
+ },
439
+ onError: onProxyError(target),
440
+ secure: false,
441
+ changeOrigin: true,
442
+ ws: true,
443
+ xfwd: true,
444
+ },
445
+ ];
446
+ }
447
+
448
+ function choosePort(host, defaultPort) {
449
+ return detect(defaultPort, host).then(
450
+ port =>
451
+ new Promise(resolve => {
452
+ if (port === defaultPort) {
453
+ return resolve(port);
454
+ }
455
+ const message =
456
+ process.platform !== 'win32' && defaultPort < 1024 && !isRoot()
457
+ ? `Admin permissions are required to run a server on a port below 1024.`
458
+ : `Something is already running on port ${defaultPort}.`;
459
+ if (isInteractive) {
460
+ clearConsole();
461
+ const existingProcess = getProcessForPort(defaultPort);
462
+ const question = {
463
+ type: 'confirm',
464
+ name: 'shouldChangePort',
465
+ message:
466
+ chalk.yellow(
467
+ message +
468
+ `${existingProcess ? ` Probably:\n ${existingProcess}` : ''}`
469
+ ) + '\n\nWould you like to run the app on another port instead?',
470
+ initial: true,
471
+ };
472
+ prompts(question).then(answer => {
473
+ if (answer.shouldChangePort) {
474
+ resolve(port);
475
+ } else {
476
+ resolve(null);
477
+ }
478
+ });
479
+ } else {
480
+ console.log(chalk.red(message));
481
+ resolve(null);
482
+ }
483
+ }),
484
+ err => {
485
+ throw new Error(
486
+ chalk.red(`Could not find an open port at ${chalk.bold(host)}.`) +
487
+ '\n' +
488
+ ('Network error message: ' + err.message || err) +
489
+ '\n'
490
+ );
491
+ }
492
+ );
493
+ }
494
+
495
+ module.exports = {
496
+ choosePort,
497
+ createCompiler,
498
+ prepareProxy,
499
+ prepareUrls,
500
+ };
package/chalk.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Copyright (c) 2015-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
+
10
+ var chalk = require('chalk');
11
+
12
+ module.exports = chalk;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Copyright (c) 2015-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
+
10
+ var fs = require('fs');
11
+ var path = require('path');
12
+ var chalk = require('chalk');
13
+
14
+ function checkRequiredFiles(files) {
15
+ var currentFilePath;
16
+ try {
17
+ files.forEach(filePath => {
18
+ currentFilePath = filePath;
19
+ fs.accessSync(filePath, fs.F_OK);
20
+ });
21
+ return true;
22
+ } catch (err) {
23
+ var dirName = path.dirname(currentFilePath);
24
+ var fileName = path.basename(currentFilePath);
25
+ console.log(chalk.red('Could not find a required file.'));
26
+ console.log(chalk.red(' Name: ') + chalk.cyan(fileName));
27
+ console.log(chalk.red(' Searched in: ') + chalk.cyan(dirName));
28
+ return false;
29
+ }
30
+ }
31
+
32
+ module.exports = checkRequiredFiles;