diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d82f7c2..2b6a6821 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,9 @@ name: CI Testing -on: pull_request +on: + pull_request: + push: + branches: + - master jobs: test: runs-on: ubuntu-latest @@ -12,7 +16,7 @@ jobs: - name: Install flvtool2 run: sudo gem install flvtool2 - name: Install ffmpeg - run: sudo apt update && sudo apt install -y ffmpeg + run: sudo apt install -y ffmpeg - name: Setup node uses: actions/setup-node@v3 with: @@ -22,3 +26,21 @@ jobs: run: yarn - name: Run tests run: yarn test + - name: Generate coverage report + run: yarn coverage + - name: Store coverage + uses: coverallsapp/github-action@v2 + with: + flag-name: linux-node-${{ matrix.node }} + parallel: true + + finish: + needs: test + if: ${{ always() }} + runs-on: ubuntu-latest + steps: + - name: Coveralls Finished + uses: coverallsapp/github-action@v2 + with: + parallel-finished: true + carryforward: "linux-node-18,linux-node-20,linux-node-21" diff --git a/.gitignore b/.gitignore index 1cc5826d..604c00ea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *.project node_modules -lib-cov +.nyc_output *.swp .idea *.iml +coverage diff --git a/Makefile b/Makefile index 26e1b143..53ad230a 100644 --- a/Makefile +++ b/Makefile @@ -7,15 +7,6 @@ test: test-colors: @NODE_ENV=test $(MOCHA) --require should --reporter $(REPORTER) --colors -test-cov: test/coverage.html - -test/coverage.html: lib-cov - @FLUENTFFMPEG_COV=1 NODE_ENV=test $(MOCHA) --require should --reporter html-cov > test/coverage.html - -lib-cov: - @rm -fr ./$@ - @jscoverage lib $@ - publish: @npm version patch -m "version bump" @npm publish @@ -26,4 +17,4 @@ JSDOC_CONF = tools/jsdoc-conf.json doc: $(JSDOC) --configure $(JSDOC_CONF) -.PHONY: test test-cov lib-cov test-colors publish doc \ No newline at end of file +.PHONY: test test-colors publish doc \ No newline at end of file diff --git a/README.md b/README.md index 2a48711a..1403386e 100644 --- a/README.md +++ b/README.md @@ -1459,12 +1459,6 @@ To run unit tests, first make sure you installed npm dependencies (run `npm inst $ make test ``` -If you want to re-generate the test coverage report (filed under test/coverage.html), run - -```sh -$ make test-cov -``` - Make sure your ffmpeg installation is up-to-date to prevent strange assertion errors because of missing codecs/bugfixes. ## Main contributors diff --git a/index.js b/index.js index fb4805dd..68a1522e 100644 --- a/index.js +++ b/index.js @@ -1 +1 @@ -module.exports = require(`./lib${process.env.FLUENTFFMPEG_COV ? '-cov' : ''}/fluent-ffmpeg`); +module.exports = require('./lib/fluent-ffmpeg'); diff --git a/package.json b/package.json index 720307ba..9b191028 100644 --- a/package.json +++ b/package.json @@ -19,9 +19,10 @@ }, "repository": "git://github.com/fluent-ffmpeg/node-fluent-ffmpeg.git", "devDependencies": { + "jsdoc": "^4.0.0", "mocha": "^10.0.0", - "should": "^13.0.0", - "jsdoc": "^4.0.0" + "nyc": "^15.1.0", + "should": "^13.0.0" }, "dependencies": { "async": "^0.2.9", @@ -32,6 +33,7 @@ }, "main": "index", "scripts": { - "test": "make test" + "test": "NODE_ENV=test nyc mocha --require should --reporter spec", + "coverage": "nyc report --reporter=lcov" } } \ No newline at end of file diff --git a/test/coverage.html b/test/coverage.html deleted file mode 100644 index 58996049..00000000 --- a/test/coverage.html +++ /dev/null @@ -1,355 +0,0 @@ -make[1]: entrant dans le répertoire « /home/niko/dev/forks/node-fluent-ffmpeg » -Coverage -

Coverage

89%
945
848
97

lib/capabilities.js

86%
179
154
25
LineHitsSource
1/*jshint node:true*/
2'use strict';
3
41var fs = require('fs');
51var path = require('path');
61var async = require('async');
71var utils = require('./utils');
8
9/*
10 *! Capability helpers
11 */
12
131var avCodecRegexp = /^\s*([D ])([E ])([VAS])([S ])([D ])([T ]) ([^ ]+) +(.*)$/;
141var ffCodecRegexp = /^\s*([D\.])([E\.])([VAS])([I\.])([L\.])([S\.]) ([^ ]+) +(.*)$/;
151var ffEncodersRegexp = /\(encoders:([^\)]+)\)/;
161var ffDecodersRegexp = /\(decoders:([^\)]+)\)/;
171var formatRegexp = /^\s*([D ])([E ]) ([^ ]+) +(.*)$/;
181var lineBreakRegexp = /\r\n|\r|\n/;
191var filterRegexp = /^(?: [T\.][S\.][C\.] )?([^ ]+) +(AA?|VV?|\|)->(AA?|VV?|\|) +(.*)$/;
20
211var cache = {};
22
23function copy(src, dest) {
24125 Object.keys(src).forEach(function(k) {
25741 dest[k] = src[k];
26 });
27}
28
291module.exports = function(proto) {
30 /**
31 * Forget executable paths
32 *
33 * (only used for testing purposes)
34 *
35 * @method FfmpegCommand#_forgetPaths
36 * @private
37 */
381 proto._forgetPaths = function() {
398 delete cache.ffmpegPath;
408 delete cache.ffprobePath;
418 delete cache.flvtoolPath;
42 };
43
44
45 /**
46 * Check for ffmpeg availability
47 *
48 * If the FFMPEG_PATH environment variable is set, try to use it.
49 * If it is unset or incorrect, try to find ffmpeg in the PATH instead.
50 *
51 * @method FfmpegCommand#_getFfmpegPath
52 * @param {Function} callback callback with signature (err, path)
53 * @private
54 */
551 proto._getFfmpegPath = function(callback) {
5635 if ('ffmpegPath' in cache) {
5729 return callback(null, cache.ffmpegPath);
58 }
59
606 async.waterfall([
61 // Try FFMPEG_PATH
62 function(cb) {
636 if (process.env.FFMPEG_PATH) {
643 fs.exists(process.env.FFMPEG_PATH, function(exists) {
653 if (exists) {
661 cb(null, process.env.FFMPEG_PATH);
67 } else {
682 cb(null, '');
69 }
70 });
71 } else {
723 cb(null, '');
73 }
74 },
75
76 // Search in the PATH
77 function(ffmpeg, cb) {
786 if (ffmpeg.length) {
791 return cb(null, ffmpeg);
80 }
81
825 utils.which('ffmpeg', function(err, ffmpeg) {
835 cb(err, ffmpeg);
84 });
85 }
86 ], function(err, ffmpeg) {
876 if (err) {
880 callback(err);
89 } else {
906 callback(null, cache.ffmpegPath = (ffmpeg || ''));
91 }
92 });
93 };
94
95
96 /**
97 * Check for ffprobe availability
98 *
99 * If the FFPROBE_PATH environment variable is set, try to use it.
100 * If it is unset or incorrect, try to find ffprobe in the PATH instead.
101 * If this still fails, try to find ffprobe in the same directory as ffmpeg.
102 *
103 * @method FfmpegCommand#_getFfprobePath
104 * @param {Function} callback callback with signature (err, path)
105 * @private
106 */
1071 proto._getFfprobePath = function(callback) {
10813 if ('ffprobePath' in cache) {
1099 return callback(null, cache.ffprobePath);
110 }
111
1124 var self = this;
1134 async.waterfall([
114 // Try FFPROBE_PATH
115 function(cb) {
1164 if (process.env.FFPROBE_PATH) {
1172 fs.exists(process.env.FFPROBE_PATH, function(exists) {
1182 cb(null, exists ? process.env.FFPROBE_PATH : '');
119 });
120 } else {
1212 cb(null, '');
122 }
123 },
124
125 // Search in the PATH
126 function(ffprobe, cb) {
1274 if (ffprobe.length) {
1281 return cb(null, ffprobe);
129 }
130
1313 utils.which('ffprobe', function(err, ffprobe) {
1323 cb(err, ffprobe);
133 });
134 },
135
136 // Search in the same directory as ffmpeg
137 function(ffprobe, cb) {
1384 if (ffprobe.length) {
1394 return cb(null, ffprobe);
140 }
141
1420 self._getFfmpegPath(function(err, ffmpeg) {
1430 if (err) {
1440 cb(err);
1450 } else if (ffmpeg.length) {
1460 var name = utils.isWindows ? 'ffprobe.exe' : 'ffprobe';
1470 var ffprobe = path.join(path.dirname(ffmpeg), name);
1480 fs.exists(ffprobe, function(exists) {
1490 cb(null, exists ? ffprobe : '');
150 });
151 } else {
1520 cb(null, '');
153 }
154 });
155 }
156 ], function(err, ffprobe) {
1574 if (err) {
1580 callback(err);
159 } else {
1604 callback(null, cache.ffprobePath = (ffprobe || ''));
161 }
162 });
163 };
164
165
166 /**
167 * Check for flvtool2/flvmeta availability
168 *
169 * If the FLVTOOL2_PATH or FLVMETA_PATH environment variable are set, try to use them.
170 * If both are either unset or incorrect, try to find flvtool2 or flvmeta in the PATH instead.
171 *
172 * @method FfmpegCommand#_getFlvtoolPath
173 * @param {Function} callback callback with signature (err, path)
174 * @private
175 */
1761 proto._getFlvtoolPath = function(callback) {
17729 if ('flvtoolPath' in cache) {
17828 return callback(null, cache.flvtoolPath);
179 }
180
1811 async.waterfall([
182 // Try FLVMETA_PATH
183 function(cb) {
1841 if (process.env.FLVMETA_PATH) {
1850 fs.exists(process.env.FLVMETA_PATH, function(exists) {
1860 cb(null, exists ? process.env.FLVMETA_PATH : '');
187 });
188 } else {
1891 cb(null, '');
190 }
191 },
192
193 // Try FLVTOOL2_PATH
194 function(flvtool, cb) {
1951 if (flvtool.length) {
1960 return cb(null, flvtool);
197 }
198
1991 if (process.env.FLVTOOL2_PATH) {
2000 fs.exists(process.env.FLVTOOL2_PATH, function(exists) {
2010 cb(null, exists ? process.env.FLVTOOL2_PATH : '');
202 });
203 } else {
2041 cb(null, '');
205 }
206 },
207
208 // Search for flvmeta in the PATH
209 function(flvtool, cb) {
2101 if (flvtool.length) {
2110 return cb(null, flvtool);
212 }
213
2141 utils.which('flvmeta', function(err, flvmeta) {
2151 cb(err, flvmeta);
216 });
217 },
218
219 // Search for flvtool2 in the PATH
220 function(flvtool, cb) {
2211 if (flvtool.length) {
2221 return cb(null, flvtool);
223 }
224
2250 utils.which('flvtool2', function(err, flvtool2) {
2260 cb(err, flvtool2);
227 });
228 },
229 ], function(err, flvtool) {
2301 if (err) {
2310 callback(err);
232 } else {
2331 callback(null, cache.flvtoolPath = (flvtool || ''));
234 }
235 });
236 };
237
238
239 /**
240 * Query ffmpeg for available filters
241 *
242 * Calls 'callback' with a filters object as its second argument. This
243 * object has keys for every available filter, and values are object
244 * with filter data:
245 * - 'description': filter description
246 * - 'input': input type ('audio', 'video' or 'none')
247 * - 'multipleInputs': bool, whether the filter supports multiple inputs
248 * - 'output': output type ('audio', 'video' or 'none')
249 * - 'multipleOutputs': bool, whether the filter supports multiple outputs
250 *
251 * @method FfmpegCommand#availableFilters
252 * @category Capabilities
253 * @aliases getAvailableFilters
254 *
255 * @param {Function} callback callback with signature (err, filters)
256 */
2571 proto.availableFilters =
258 proto.getAvailableFilters = function(callback) {
2592 if ('filters' in cache) {
2601 return callback(null, cache.filters);
261 }
262
2631 this._spawnFfmpeg(['-filters'], { captureStdout: true }, function (err, stdout) {
2641 if (err) {
2650 return callback(err);
266 }
267
2681 var lines = stdout.split('\n');
2691 var data = {};
2701 var types = { A: 'audio', V: 'video', '|': 'none' };
271
2721 lines.forEach(function(line) {
273137 var match = line.match(filterRegexp);
274137 if (match) {
275135 data[match[1]] = {
276 description: match[4],
277 input: types[match[2].charAt(0)],
278 multipleInputs: match[2].length > 1,
279 output: types[match[3].charAt(0)],
280 multipleOutputs: match[3].length > 1
281 };
282 }
283 });
284
2851 callback(null, cache.filters = data);
286 });
287 };
288
289
290 /**
291 * Query ffmpeg for available codecs
292 *
293 * Calls 'callback' with a codecs object as its second argument. This
294 * object has keys for every available codec, and values are object
295 * with codec data:
296 * - 'description': codec description
297 * - 'canEncode': bool, whether the codec can encode streams
298 * - 'canDecode': bool, whether the codec can decode streams
299 *
300 * Depending on the ffmpeg version, more keys can be available.
301 *
302 * @method FfmpegCommand#availableCodecs
303 * @category Capabilities
304 * @aliases getAvailableCodecs
305 *
306 * @param {Function} callback callback with signature (err, codecs)
307 */
3081 proto.availableCodecs =
309 proto.getAvailableCodecs = function(callback) {
31025 if ('codecs' in cache) {
31124 return callback(null, cache.codecs);
312 }
313
3141 this._spawnFfmpeg(['-codecs'], { captureStdout: true }, function(err, stdout) {
3151 if (err) {
3160 return callback(err);
317 }
318
3191 var lines = stdout.split(lineBreakRegexp);
3201 var data = {};
321
3221 lines.forEach(function(line) {
323369 var match = line.match(avCodecRegexp);
324369 if (match && match[7] !== '=') {
3250 data[match[7]] = {
326 type: { 'V': 'video', 'A': 'audio', 'S': 'subtitle' }[match[3]],
327 description: match[8],
328 canDecode: match[1] === 'D',
329 canEncode: match[2] === 'E',
330 drawHorizBand: match[4] === 'S',
331 directRendering: match[5] === 'D',
332 weirdFrameTruncation: match[6] === 'T'
333 };
334 }
335
336369 match = line.match(ffCodecRegexp);
337369 if (match && match[7] !== '=') {
338357 var codecData = data[match[7]] = {
339 type: { 'V': 'video', 'A': 'audio', 'S': 'subtitle' }[match[3]],
340 description: match[8],
341 canDecode: match[1] === 'D',
342 canEncode: match[2] === 'E',
343 intraFrameOnly: match[4] === 'I',
344 isLossy: match[5] === 'L',
345 isLossless: match[6] === 'S'
346 };
347
348357 var encoders = codecData.description.match(ffEncodersRegexp);
349357 encoders = encoders ? encoders[1].trim().split(' ') : [];
350
351357 var decoders = codecData.description.match(ffDecodersRegexp);
352357 decoders = decoders ? decoders[1].trim().split(' ') : [];
353
354357 if (encoders.length || decoders.length) {
35558 var coderData = {};
35658 copy(codecData, coderData);
35758 delete coderData.canEncode;
35858 delete coderData.canDecode;
359
36058 encoders.forEach(function(name) {
36132 data[name] = {};
36232 copy(coderData, data[name]);
36332 data[name].canEncode = true;
364 });
365
36658 decoders.forEach(function(name) {
36773 if (name in data) {
36838 data[name].canDecode = true;
369 } else {
37035 data[name] = {};
37135 copy(coderData, data[name]);
37235 data[name].canDecode = true;
373 }
374 });
375 }
376 }
377 });
378
3791 callback(null, cache.codecs = data);
380 });
381 };
382
383
384 /**
385 * Query ffmpeg for available formats
386 *
387 * Calls 'callback' with a formats object as its second argument. This
388 * object has keys for every available format, and values are object
389 * with format data:
390 * - 'description': format description
391 * - 'canMux': bool, whether the format can mux streams into an output file
392 * - 'canDemux': bool, whether the format can demux streams from an input file
393 *
394 * @method FfmpegCommand#availableFormats
395 * @category Capabilities
396 * @aliases getAvailableFormats
397 *
398 * @param {Function} callback callback with signature (err, formats)
399 */
4001 proto.availableFormats =
401 proto.getAvailableFormats = function(callback) {
40228 if ('formats' in cache) {
40327 return callback(null, cache.formats);
404 }
405
406 // Run ffmpeg -formats
4071 this._spawnFfmpeg(['-formats'], { captureStdout: true }, function (err, stdout) {
4081 if (err) {
4090 return callback(err);
410 }
411
412 // Parse output
4131 var lines = stdout.split(lineBreakRegexp);
4141 var data = {};
415
4161 lines.forEach(function(line) {
417252 var match = line.match(formatRegexp);
418252 if (match) {
419247 data[match[3]] = {
420 description: match[4],
421 canDemux: match[1] === 'D',
422 canMux: match[2] === 'E'
423 };
424 }
425 });
426
4271 callback(null, cache.formats = data);
428 });
429 };
430
431
432 /**
433 * Check capabilities before executing a command
434 *
435 * Checks whether all used codecs and formats are indeed available
436 *
437 * @method FfmpegCommand#_checkCapabilities
438 * @param {Function} callback callback with signature (err)
439 * @private
440 */
4411 proto._checkCapabilities = function(callback) {
44226 var self = this;
44326 async.waterfall([
444 // Get available formats
445 function(cb) {
44626 self.availableFormats(cb);
447 },
448
449 // Check whether specified formats are available
450 function(formats, cb) {
451 // Output format
45226 var format = self._output.find('-f', 1);
453
45426 if (format) {
45524 if (!(format[0] in formats) || !(formats[format[0]].canMux)) {
4562 return cb(new Error('Output format ' + format[0] + ' is not available'));
457 }
458 }
459
460 // Input format(s)
46124 var unavailable = self._inputs.reduce(function(fmts, input) {
46224 var format = input.before.find('-f', 1);
46324 if (format) {
4644 if (!(format[0] in formats) || !(formats[format[0]].canDemux)) {
4651 fmts.push(format[0]);
466 }
467 }
468
46924 return fmts;
470 }, []);
471
47224 if (unavailable.length === 1) {
4731 cb(new Error('Input format ' + unavailable[0] + ' is not available'));
47423 } else if (unavailable.length > 1) {
4750 cb(new Error('Input formats ' + unavailable.join(', ') + ' are not available'));
476 } else {
47723 cb();
478 }
479 },
480
481 // Get available codecs
482 function(cb) {
48323 self.availableCodecs(cb);
484 },
485
486 // Check whether specified codecs are available
487 function(codecs, cb) {
488 // Audio codec
48923 var acodec = self._audio.find('-acodec', 1);
49023 if (acodec && acodec[0] !== 'copy') {
49121 if (!(acodec[0] in codecs) || codecs[acodec[0]].type !== 'audio' || !(codecs[acodec[0]].canEncode)) {
4921 return cb(new Error('Audio codec ' + acodec[0] + ' is not available'));
493 }
494 }
495
496 // Video codec
49722 var vcodec = self._video.find('-vcodec', 1);
49822 if (vcodec && vcodec[0] !== 'copy') {
49920 if (!(vcodec[0] in codecs) || codecs[vcodec[0]].type !== 'video' || !(codecs[vcodec[0]].canEncode)) {
5001 return cb(new Error('Video codec ' + vcodec[0] + ' is not available'));
501 }
502 }
503
50421 cb();
505 }
506 ], callback);
507 };
508};
509

lib/ffprobe.js

80%
66
53
13
LineHitsSource
1/*jshint node:true, laxcomma:true*/
2'use strict';
3
41var spawn = require('child_process').spawn;
5
6
7263function legacyTag(key) { return key.match(/^TAG:/); }
8263function legacyDisposition(key) { return key.match(/^DISPOSITION:/); }
9
10
111module.exports = function(proto) {
12 /**
13 * Run ffprobe on last specified input
14 *
15 * Callback will receive an object as its second argument. This object
16 * has the same format as what the following command returns:
17 *
18 * ffprobe -print_format json -show_streams -show_format INPUTFILE
19 *
20 * @method FfmpegCommand#ffprobe
21 * @category Metadata
22 *
23 * @param {Function} callback callback with signature (err, ffprobeData)
24 *
25 */
261 proto.ffprobe = function(callback) {
2710 if (!this._currentInput) {
281 return callback(new Error('No input specified'));
29 }
30
319 if (typeof this._currentInput.source !== 'string') {
321 return callback(new Error('Cannot run ffprobe on non-file input'));
33 }
34
35 // Find ffprobe
368 var self = this;
378 this._getFfprobePath(function(err, path) {
388 if (err) {
390 return callback(err);
408 } else if (!path) {
410 return callback(new Error('Cannot find ffprobe'));
42 }
43
448 var stdout = '';
458 var stdoutClosed = false;
468 var stderr = '';
478 var stderrClosed = false;
48
49 // Spawn ffprobe
508 var ffprobe = spawn(path, [
51 '-print_format', 'json',
52 '-show_streams',
53 '-show_format',
54 self._currentInput.source
55 ]);
56
578 ffprobe.on('error', function(err) {
580 callback(err);
59 });
60
61 // Ensure we wait for captured streams to end before calling callback
628 var exitError = null;
63 function handleExit(err) {
6424 if (err) {
651 exitError = err;
66 }
67
6824 if (processExited && stdoutClosed && stderrClosed) {
698 if (exitError) {
701 if (stderr) {
711 exitError.message += '\n' + stderr;
72 }
73
741 return callback(exitError);
75 }
76
77 // Process output
787 var data;
79
807 try {
817 data = JSON.parse(stdout);
82 } catch(e) {
830 return callback(e);
84 }
85
86 // Handle legacy output with "TAG:x" and "DISPOSITION:x" keys
877 [data.format].concat(data.streams).forEach(function(target) {
8815 var legacyTagKeys = Object.keys(target).filter(legacyTag);
89
9015 if (legacyTagKeys.length) {
910 target.tags = target.tags || {};
92
930 legacyTagKeys.forEach(function(tagKey) {
940 target.tags[tagKey.substr(4)] = target[tagKey];
950 delete target[tagKey];
96 });
97 }
98
9915 var legacyDispositionKeys = Object.keys(target).filter(legacyDisposition);
100
10115 if (legacyDispositionKeys.length) {
1020 target.disposition = target.disposition || {};
103
1040 legacyDispositionKeys.forEach(function(dispositionKey) {
1050 target.disposition[dispositionKey.substr(12)] = target[dispositionKey];
1060 delete target[dispositionKey];
107 });
108 }
109 });
110
1117 callback(null, data);
112 }
113 }
114
115 // Handle ffprobe exit
1168 var processExited = false;
1178 ffprobe.on('exit', function(code, signal) {
1188 processExited = true;
119
1208 if (code) {
1211 handleExit(new Error('ffprobe exited with code ' + code));
1227 } else if (signal) {
1230 handleExit(new Error('ffprobe was killed with signal ' + signal));
124 } else {
1257 handleExit();
126 }
127 });
128
129 // Handle stdout/stderr streams
1308 ffprobe.stdout.on('data', function(data) {
13118 stdout += data;
132 });
133
1348 ffprobe.stdout.on('close', function() {
1358 stdoutClosed = true;
1368 handleExit();
137 });
138
1398 ffprobe.stderr.on('data', function(data) {
14033 stderr += data;
141 });
142
1438 ffprobe.stderr.on('close', function() {
1448 stderrClosed = true;
1458 handleExit();
146 });
147 });
148 };
149};
150
151

lib/fluent-ffmpeg.js

100%
44
44
0
LineHitsSource
1/*jshint node:true*/
2'use strict';
3
41var path = require('path');
51var util = require('util');
61var EventEmitter = require('events').EventEmitter;
7
81var utils = require('./utils');
9
10
11/**
12 * Create an ffmpeg command
13 *
14 * Can be called with or without the 'new' operator, and the 'input' parameter
15 * may be specified as 'options.source' instead (or passed later with the
16 * addInput method).
17 *
18 * @constructor
19 * @param {String|ReadableStream} [input] input file path or readable stream
20 * @param {Object} [options] command options
21 * @param {Object} [options.logger=<no logging>] logger object with 'error', 'warning', 'info' and 'debug' methods
22 * @param {Number} [options.niceness=0] ffmpeg process niceness, ignored on Windows
23 * @param {Number} [options.priority=0] alias for `niceness`
24 * @param {String} [options.presets="fluent-ffmpeg/lib/presets"] directory to load presets from
25 * @param {String} [options.preset="fluent-ffmpeg/lib/presets"] alias for `presets`
26 * @param {Number} [options.timeout=<no timeout>] ffmpeg processing timeout in seconds
27 * @param {String|ReadableStream} [options.source=<no input>] alias for the `input` parameter
28 */
29function FfmpegCommand(input, options) {
30 // Make 'new' optional
31207 if (!(this instanceof FfmpegCommand)) {
321 return new FfmpegCommand(input, options);
33 }
34
35206 EventEmitter.call(this);
36
37206 if (typeof input === 'object' && !('readable' in input)) {
38 // Options object passed directly
3989 options = input;
40 } else {
41 // Input passed first
42117 options = options || {};
43117 options.source = input;
44 }
45
46 // Add input if present
47206 this._inputs = [];
48206 if (options.source) {
4994 this.addInput(options.source);
50 }
51
52 // Create argument lists
53206 this._audio = utils.args();
54206 this._audioFilters = utils.args();
55206 this._video = utils.args();
56206 this._videoFilters = utils.args();
57206 this._sizeFilters = utils.args();
58206 this._output = utils.args();
59
60 // Set default option values
61206 options.presets = options.presets || options.preset || path.join(__dirname, 'presets');
62206 options.niceness = options.niceness || options.priority || 0;
63
64 // Save options
65206 this.options = options;
66
67 // Setup logger
68206 this.logger = options.logger || {
69 debug: function() {},
70 info: function() {},
71 warn: function() {},
72 error: function() {}
73 };
74}
751util.inherits(FfmpegCommand, EventEmitter);
761module.exports = FfmpegCommand;
77
78
79/* Add methods from options submodules */
80
811require('./options/inputs')(FfmpegCommand.prototype);
821require('./options/audio')(FfmpegCommand.prototype);
831require('./options/video')(FfmpegCommand.prototype);
841require('./options/videosize')(FfmpegCommand.prototype);
851require('./options/output')(FfmpegCommand.prototype);
861require('./options/custom')(FfmpegCommand.prototype);
871require('./options/misc')(FfmpegCommand.prototype);
88
89
90/* Add processor methods */
91
921require('./processor')(FfmpegCommand.prototype);
93
94
95/* Add capabilities methods */
96
971require('./capabilities')(FfmpegCommand.prototype);
98
991FfmpegCommand.availableFilters =
100FfmpegCommand.getAvailableFilters = function(callback) {
1011 (new FfmpegCommand()).availableFilters(callback);
102};
103
1041FfmpegCommand.availableCodecs =
105FfmpegCommand.getAvailableCodecs = function(callback) {
1061 (new FfmpegCommand()).availableCodecs(callback);
107};
108
1091FfmpegCommand.availableFormats =
110FfmpegCommand.getAvailableFormats = function(callback) {
1111 (new FfmpegCommand()).availableFormats(callback);
112};
113
114
115/* Add ffprobe methods */
116
1171require('./ffprobe')(FfmpegCommand.prototype);
118
1191FfmpegCommand.ffprobe = function(file, callback) {
1204 (new FfmpegCommand(file)).ffprobe(callback);
121};
122
123

lib/options/audio.js

100%
25
25
0
LineHitsSource
1/*jshint node:true*/
2'use strict';
3
4/*
5 *! Audio-related methods
6 */
7
81module.exports = function(proto) {
9 /**
10 * Disable audio in the output
11 *
12 * @method FfmpegCommand#noAudio
13 * @category Audio
14 * @aliases withNoAudio
15 * @return FfmpegCommand
16 */
171 proto.withNoAudio =
18 proto.noAudio = function() {
192 this._audio.clear();
202 this._audio('-an');
21
222 return this;
23 };
24
25
26 /**
27 * Specify audio codec
28 *
29 * @method FfmpegCommand#audioCodec
30 * @category Audio
31 * @aliases withAudioCodec
32 *
33 * @param {String} codec audio codec name
34 * @return FfmpegCommand
35 */
361 proto.withAudioCodec =
37 proto.audioCodec = function(codec) {
3826 this._audio('-acodec', codec);
3926 return this;
40 };
41
42
43 /**
44 * Specify audio bitrate
45 *
46 * @method FfmpegCommand#audioBitrate
47 * @category Audio
48 * @aliases withAudioBitrate
49 *
50 * @param {String|Number} bitrate audio bitrate in kbps (with an optional 'k' suffix)
51 * @return FfmpegCommand
52 */
531 proto.withAudioBitrate =
54 proto.audioBitrate = function(bitrate) {
5522 this._audio('-b:a', ('' + bitrate).replace(/k?$/, 'k'));
5622 return this;
57 };
58
59
60 /**
61 * Specify audio channel count
62 *
63 * @method FfmpegCommand#audioChannels
64 * @category Audio
65 * @aliases withAudioChannels
66 *
67 * @param {Number} channels channel count
68 * @return FfmpegCommand
69 */
701 proto.withAudioChannels =
71 proto.audioChannels = function(channels) {
7222 this._audio('-ac', channels);
7322 return this;
74 };
75
76
77 /**
78 * Specify audio frequency
79 *
80 * @method FfmpegCommand#audioFrequency
81 * @category Audio
82 * @aliases withAudioFrequency
83 *
84 * @param {Number} freq audio frequency in Hz
85 * @return FfmpegCommand
86 */
871 proto.withAudioFrequency =
88 proto.audioFrequency = function(freq) {
8920 this._audio('-ar', freq);
9020 return this;
91 };
92
93
94 /**
95 * Specify audio quality
96 *
97 * @method FfmpegCommand#audioQuality
98 * @category Audio
99 * @aliases withAudioQuality
100 *
101 * @param {Number} quality audio quality factor
102 * @return FfmpegCommand
103 */
1041 proto.withAudioQuality =
105 proto.audioQuality = function(quality) {
1061 this._audio('-aq', quality);
1071 return this;
108 };
109
110
111 /**
112 * Specify custom audio filter(s)
113 *
114 * Can be called both with one or many filters, or a filter array.
115 *
116 * @example
117 * command.audioFilters('filter1');
118 *
119 * @example
120 * command.audioFilters('filter1', 'filter2');
121 *
122 * @example
123 * command.audioFilters(['filter1', 'filter2']);
124 *
125 * @method FfmpegCommand#audioFilters
126 * @aliases withAudioFilter,withAudioFilters,audioFilter
127 * @category Audio
128 *
129 * @param {String|Array} filters... audio filter strings or string array
130 * @return FfmpegCommand
131 */
1321 proto.withAudioFilter =
133 proto.withAudioFilters =
134 proto.audioFilter =
135 proto.audioFilters = function(filters) {
1363 if (arguments.length > 1) {
1371 filters = [].slice.call(arguments);
138 }
139
1403 this._audioFilters(filters);
1413 return this;
142 };
143};
144

lib/options/custom.js

100%
31
31
0
LineHitsSource
1/*jshint node:true*/
2'use strict';
3
4/*
5 *! Custom options methods
6 */
7
81module.exports = function(proto) {
9 /**
10 * Add custom input option(s)
11 *
12 * When passing a single string or an array, each string containing two
13 * words is split (eg. inputOptions('-option value') is supported) for
14 * compatibility reasons. This is not the case when passing more than
15 * one argument.
16 *
17 * @example
18 * command.inputOptions('option1');
19 *
20 * @example
21 * command.inputOptions('option1', 'option2');
22 *
23 * @example
24 * command.inputOptions(['option1', 'option2']);
25 *
26 * @method FfmpegCommand#inputOptions
27 * @category Custom options
28 * @aliases addInputOption,addInputOptions,withInputOption,withInputOptions,inputOption
29 *
30 * @param {...String} options option string(s) or string array
31 * @return FfmpegCommand
32 */
331 proto.addInputOption =
34 proto.addInputOptions =
35 proto.withInputOption =
36 proto.withInputOptions =
37 proto.inputOption =
38 proto.inputOptions = function(options) {
395 if (!this._currentInput) {
401 throw new Error('No input specified');
41 }
42
434 var doSplit = true;
44
454 if (arguments.length > 1) {
462 options = [].slice.call(arguments);
472 doSplit = false;
48 }
49
504 if (!Array.isArray(options)) {
511 options = [options];
52 }
53
544 this._currentInput.before(options.reduce(function(options, option) {
557 var split = option.split(' ');
56
577 if (doSplit && split.length === 2) {
583 options.push(split[0], split[1]);
59 } else {
604 options.push(option);
61 }
62
637 return options;
64 }, []));
654 return this;
66 };
67
68
69 /**
70 * Add custom output option(s)
71 *
72 * @example
73 * command.outputOptions('option1');
74 *
75 * @example
76 * command.outputOptions('option1', 'option2');
77 *
78 * @example
79 * command.outputOptions(['option1', 'option2']);
80 *
81 * @method FfmpegCommand#outputOptions
82 * @category Custom options
83 * @aliases addOutputOption,addOutputOptions,addOption,addOptions,withOutputOption,withOutputOptions,withOption,withOptions,outputOption
84 *
85 * @param {...String} options option string(s) or string array
86 * @return FfmpegCommand
87 */
881 proto.addOutputOption =
89 proto.addOutputOptions =
90 proto.addOption =
91 proto.addOptions =
92 proto.withOutputOption =
93 proto.withOutputOptions =
94 proto.withOption =
95 proto.withOptions =
96 proto.outputOption =
97 proto.outputOptions = function(options) {
986 var doSplit = true;
99
1006 if (arguments.length > 1) {
1012 options = [].slice.call(arguments);
1022 doSplit = false;
103 }
104
1056 if (!Array.isArray(options)) {
1061 options = [options];
107 }
108
1096 this._output(options.reduce(function(options, option) {
11045 var split = option.split(' ');
111
11245 if (doSplit && split.length === 2) {
11319 options.push(split[0], split[1]);
114 } else {
11526 options.push(option);
116 }
117
11845 return options;
119 }, []));
1206 return this;
121 };
122};
123

lib/options/inputs.js

100%
39
39
0
LineHitsSource
1/*jshint node:true*/
2'use strict';
3
41var utils = require('../utils');
5
6/*
7 *! Input-related methods
8 */
9
101module.exports = function(proto) {
11 /**
12 * Add an input to command
13 *
14 * Also switches "current input", that is the input that will be affected
15 * by subsequent input-related methods.
16 *
17 * Note: only one stream input is supported for now.
18 *
19 * @method FfmpegCommand#input
20 * @category Input
21 * @aliases mergeAdd,addInput
22 *
23 * @param {String|Readable} source input file path or readable stream
24 * @return FfmpegCommand
25 */
261 proto.mergeAdd =
27 proto.addInput =
28 proto.input = function(source) {
29101 if (typeof source !== 'string') {
306 if (!('readable' in source)) {
311 throw new Error('Invalid input');
32 }
33
345 var hasInputStream = this._inputs.some(function(input) {
351 return typeof input.source !== 'string';
36 });
37
385 if (hasInputStream) {
391 throw new Error('Only one input stream is supported');
40 }
41
424 source.pause();
43 }
44
4599 this._inputs.push(this._currentInput = {
46 source: source,
47 before: utils.args(),
48 after: utils.args(),
49 });
50
5199 return this;
52 };
53
54
55 /**
56 * Specify input format for the last specified input
57 *
58 * @method FfmpegCommand#inputFormat
59 * @category Input
60 * @aliases withInputFormat,fromFormat
61 *
62 * @param {String} format input format
63 * @return FfmpegCommand
64 */
651 proto.withInputFormat =
66 proto.inputFormat =
67 proto.fromFormat = function(format) {
686 if (!this._currentInput) {
691 throw new Error('No input specified');
70 }
71
725 this._currentInput.before('-f', format);
735 return this;
74 };
75
76
77 /**
78 * Specify input FPS for the last specified input
79 * (only valid for raw video formats)
80 *
81 * @method FfmpegCommand#inputFps
82 * @category Input
83 * @aliases withInputFps,withInputFPS,withFpsInput,withFPSInput,inputFPS,inputFps,fpsInput
84 *
85 * @param {Number} fps input FPS
86 * @return FfmpegCommand
87 */
881 proto.withInputFps =
89 proto.withInputFPS =
90 proto.withFpsInput =
91 proto.withFPSInput =
92 proto.inputFPS =
93 proto.inputFps =
94 proto.fpsInput =
95 proto.FPSInput = function(fps) {
962 if (!this._currentInput) {
971 throw new Error('No input specified');
98 }
99
1001 this._currentInput.before('-r', fps);
1011 return this;
102 };
103
104
105 /**
106 * Specify input seek time for the last specified input
107 *
108 * @method FfmpegCommand#seek
109 * @category Input
110 * @aliases setStartTime,seekTo
111 *
112 * @param {String|Number} seek seek time in seconds or as a '[hh:[mm:]]ss[.xxx]' string
113 * @param {Boolean} [fast=false] use fast (but inexact) seek
114 * @return FfmpegCommand
115 */
1161 proto.setStartTime =
117 proto.seekTo =
118 proto.seek = function(seek, fast) {
1194 if (!this._currentInput) {
1202 throw new Error('No input specified');
121 }
122
1232 if (fast) {
1241 this._currentInput.before('-ss', seek);
125 } else {
1261 this._currentInput.after('-ss', seek);
127 }
128
1292 return this;
130 };
131
132
133 /**
134 * Specify input fast-seek time for the last specified input
135 *
136 * @method FfmpegCommand#fastSeek
137 * @category Input
138 * @aliases fastSeekTo
139 *
140 * @param {String|Number} seek fast-seek time in seconds or as a '[[hh:]mm:]ss[.xxx]' string
141 * @return FfmpegCommand
142 */
1431 proto.fastSeek =
144 proto.fastSeekTo = function(seek) {
1451 return this.seek(seek, true);
146 };
147
148
149 /**
150 * Loop over the last specified input
151 *
152 * @method FfmpegCommand#loop
153 * @category Input
154 *
155 * @param {String|Number} [duration] loop duration in seconds or as a '[[hh:]mm:]ss[.xxx]' string
156 * @return FfmpegCommand
157 */
1581 proto.loop = function(duration) {
1594 if (!this._currentInput) {
1601 throw new Error('No input specified');
161 }
162
1633 this._currentInput.before('-loop', '1');
164
1653 if (typeof duration !== 'undefined') {
1662 this.duration(duration);
167 }
168
1693 return this;
170 };
171};
172

lib/options/misc.js

100%
19
19
0
LineHitsSource
1/*jshint node:true*/
2'use strict';
3
41var path = require('path');
5
6/*
7 *! Miscellaneous methods
8 */
9
101module.exports = function(proto) {
11 /**
12 * Use preset
13 *
14 * @method FfmpegCommand#preset
15 * @category Miscellaneous
16 * @aliases usingPreset
17 *
18 * @param {String|Function} preset preset name or preset function
19 */
201 proto.usingPreset =
21 proto.preset = function(preset) {
2223 if (typeof preset === 'function') {
231 preset(this);
24 } else {
2522 try {
2622 var modulePath = path.join(this.options.presets, preset);
2722 var module = require(modulePath);
28
2921 if (typeof module.load === 'function') {
3020 module.load(this);
31 } else {
321 throw new Error('preset ' + modulePath + ' has no load() function');
33 }
34 } catch (err) {
352 throw new Error('preset ' + modulePath + ' could not be loaded: ' + err.message);
36 }
37 }
38
3921 return this;
40 };
41
42
43 /**
44 * Enable experimental codecs
45 *
46 * @method FfmpegCommand#strict
47 * @category Miscellaneous
48 * @aliases withStrictExperimental
49 *
50 * @return FfmpegCommand
51 */
521 proto.withStrictExperimental =
53 proto.strict = function() {
5420 this._output('-strict', 'experimental');
5520 return this;
56 };
57
58
59 /**
60 * Run flvtool2/flvmeta on output
61 *
62 * @method FfmpegCommand#flvmeta
63 * @category Miscellaneous
64 * @aliases updateFlvMetadata
65 *
66 * @return FfmpegCommand
67 */
681 proto.updateFlvMetadata =
69 proto.flvmeta = function() {
7018 this.options.flvmeta = true;
7118 return this;
72 };
73};
74

lib/options/output.js

100%
7
7
0
LineHitsSource
1/*jshint node:true*/
2'use strict';
3
4/*
5 *! Output-related methods
6 */
7
81module.exports = function(proto) {
9 /**
10 * Set output duration
11 *
12 * @method FfmpegCommand#duration
13 * @category Output
14 * @aliases withDuration,setDuration
15 *
16 * @param {String|Number} duration duration in seconds or as a '[[hh:]mm:]ss[.xxx]' string
17 * @return FfmpegCommand
18 */
191 proto.withDuration =
20 proto.setDuration =
21 proto.duration = function(duration) {
223 this._output('-t', duration);
233 return this;
24 };
25
26
27 /**
28 * Set output format
29 *
30 * @method FfmpegCommand#format
31 * @category Output
32 * @aliases toFormat,withOutputFormat,outputFormat
33 *
34 * @param {String} format output format name
35 * @return FfmpegCommand
36 */
371 proto.toFormat =
38 proto.withOutputFormat =
39 proto.outputFormat =
40 proto.format = function(format) {
4127 this._output('-f', format);
4227 return this;
43 };
44};
45

lib/options/video.js

100%
27
27
0
LineHitsSource
1/*jshint node:true*/
2'use strict';
3
4/*
5 *! Video-related methods
6 */
7
81module.exports = function(proto) {
9 /**
10 * Disable video in the output
11 *
12 * @method FfmpegCommand#noVideo
13 * @category Video
14 * @aliases withNoVideo
15 *
16 * @return FfmpegCommand
17 */
181 proto.withNoVideo =
19 proto.noVideo = function() {
202 this._video.clear();
212 this._video('-vn');
22
232 return this;
24 };
25
26
27 /**
28 * Specify video codec
29 *
30 * @method FfmpegCommand#videoCodec
31 * @category Video
32 * @aliases withVideoCodec
33 *
34 * @param {String} codec video codec name
35 * @return FfmpegCommand
36 */
371 proto.withVideoCodec =
38 proto.videoCodec = function(codec) {
3927 this._video('-vcodec', codec);
4027 return this;
41 };
42
43
44 /**
45 * Specify video bitrate
46 *
47 * @method FfmpegCommand#videoBitrate
48 * @category Video
49 * @aliases withVideoBitrate
50 *
51 * @param {String|Number} bitrate video bitrate in kbps (with an optional 'k' suffix)
52 * @param {Boolean} [constant=false] enforce constant bitrate
53 * @return FfmpegCommand
54 */
551 proto.withVideoBitrate =
56 proto.videoBitrate = function(bitrate, constant) {
5722 bitrate = ('' + bitrate).replace(/k?$/, 'k');
58
5922 this._video('-b:v', bitrate);
6022 if (constant) {
611 this._video(
62 '-maxrate', bitrate,
63 '-minrate', bitrate,
64 '-bufsize', '3M'
65 );
66 }
67
6822 return this;
69 };
70
71
72 /**
73 * Specify custom video filter(s)
74 *
75 * Can be called both with one or many filters, or a filter array.
76 *
77 * @example
78 * command.videoFilters('filter1');
79 *
80 * @example
81 * command.videoFilters('filter1', 'filter2');
82 *
83 * @example
84 * command.videoFilters(['filter1', 'filter2']);
85 *
86 * @method FfmpegCommand#videoFilters
87 * @category Video
88 * @aliases withVideoFilter,withVideoFilters,videoFilter
89 *
90 * @param {String|Array} filters... video filter strings or string array
91 * @return FfmpegCommand
92 */
931 proto.withVideoFilter =
94 proto.withVideoFilters =
95 proto.videoFilter =
96 proto.videoFilters = function(filters) {
974 if (arguments.length > 1) {
982 filters = [].slice.call(arguments);
99 }
100
1014 if (Array.isArray(filters)) {
1022 this._videoFilters.apply(null, filters);
103 } else {
1042 this._videoFilters(filters);
105 }
106
1074 return this;
108 };
109
110
111 /**
112 * Specify output FPS
113 *
114 * @method FfmpegCommand#fps
115 * @category Video
116 * @aliases withOutputFps,withOutputFPS,withFpsOutput,withFPSOutput,withFps,withFPS,outputFPS,outputFps,fpsOutput,FPSOutput,FPS
117 *
118 * @param {Number} fps output FPS
119 * @return FfmpegCommand
120 */
1211 proto.withOutputFps =
122 proto.withOutputFPS =
123 proto.withFpsOutput =
124 proto.withFPSOutput =
125 proto.withFps =
126 proto.withFPS =
127 proto.outputFPS =
128 proto.outputFps =
129 proto.fpsOutput =
130 proto.FPSOutput =
131 proto.fps =
132 proto.FPS = function(fps) {
13319 this._video('-r', fps);
13419 return this;
135 };
136
137
138 /**
139 * Only transcode a certain number of frames
140 *
141 * @method FfmpegCommand#frames
142 * @category Video
143 * @aliases takeFrames,withFrames
144 *
145 * @param {Number} frames frame count
146 * @return FfmpegCommand
147 */
1481 proto.takeFrames =
149 proto.withFrames =
150 proto.frames = function(frames) {
1515 this._video('-vframes', frames);
1525 return this;
153 };
154};
155

lib/options/videosize.js

100%
62
62
0
LineHitsSource
1/*jshint node:true*/
2'use strict';
3
4/*
5 *! Size helpers
6 */
7
8
9/**
10 * Return filters to pad video to width*height,
11 *
12 * @param {Number} width output width
13 * @param {Number} height output height
14 * @param {Number} aspect video aspect ratio (without padding)
15 * @param {Number} color padding color
16 * @return scale/pad filters
17 * @private
18 */
19function getScalePadFilters(width, height, aspect, color) {
20 /*
21 let a be the input aspect ratio, A be the requested aspect ratio
22
23 if a > A, padding is done on top and bottom
24 if a < A, padding is done on left and right
25 */
26
2710 return [
28 /*
29 In both cases, we first have to scale the input to match the requested size.
30 When using computed width/height, we truncate them to multiples of 2
31
32 scale=
33 w=if(gt(a, A), width, trunc(height*a/2)*2):
34 h=if(lt(a, A), height, trunc(width/a/2)*2)
35 */
36
37 'scale=\'' +
38 'w=if(gt(a,' + aspect + '),' + width + ',trunc(' + height + '*a/2)*2):' +
39 'h=if(lt(a,' + aspect + '),' + height + ',trunc(' + width + '/a/2)*2)\'',
40
41 /*
42 Then we pad the scaled input to match the target size
43
44 pad=
45 w=width:
46 h=height:
47 x=if(gt(a, A), 0, (width - iw)/2):
48 y=if(lt(a, A), 0, (height - ih)/2)
49
50 (here iw and ih refer to the padding input, i.e the scaled output)
51 */
52
53 'pad=\'' +
54 'w=' + width + ':' +
55 'h=' + height + ':' +
56 'x=if(gt(a,' + aspect + '),0,(' + width + '-iw)/2):' +
57 'y=if(lt(a,' + aspect + '),0,(' + height + '-ih)/2):' +
58 'color=' + color + '\''
59 ];
60}
61
62
63/**
64 * Recompute size filters
65 *
66 * @param {FfmpegCommand} command
67 * @param {String} key newly-added parameter name ('size', 'aspect' or 'pad')
68 * @param {String} value newly-added parameter value
69 * @return filter string array
70 * @private
71 */
72function createSizeFilters(command, key, value) {
73 // Store parameters
7480 var data = command._sizeData = command._sizeData || {};
7580 data[key] = value;
76
7780 if (!('size' in data)) {
78 // No size requested, keep original size
792 return [];
80 }
81
82 // Try to match the different size string formats
8378 var fixedSize = data.size.match(/([0-9]+)x([0-9]+)/);
8478 var fixedWidth = data.size.match(/([0-9]+)x\?/);
8578 var fixedHeight = data.size.match(/\?x([0-9]+)/);
8678 var percentRatio = data.size.match(/\b([0-9]{1,3})%/);
8778 var width, height, aspect;
88
8978 if (percentRatio) {
905 var ratio = Number(percentRatio[1]) / 100;
915 return ['scale=trunc(iw*' + ratio + '/2)*2:trunc(ih*' + ratio + '/2)*2'];
9273 } else if (fixedSize) {
93 // Round target size to multiples of 2
9421 width = Math.round(Number(fixedSize[1]) / 2) * 2;
9521 height = Math.round(Number(fixedSize[2]) / 2) * 2;
96
9721 aspect = width / height;
98
9921 if (data.pad) {
1005 return getScalePadFilters(width, height, aspect, data.pad);
101 } else {
102 // No autopad requested, rescale to target size
10316 return ['scale=' + width + ':' + height];
104 }
10552 } else if (fixedWidth || fixedHeight) {
10651 if ('aspect' in data) {
107 // Specified aspect ratio
10814 width = fixedWidth ? fixedWidth[1] : Math.round(Number(fixedHeight[1]) * data.aspect);
10914 height = fixedHeight ? fixedHeight[1] : Math.round(Number(fixedWidth[1]) / data.aspect);
110
111 // Round to multiples of 2
11214 width = Math.round(width / 2) * 2;
11314 height = Math.round(height / 2) * 2;
114
11514 if (data.pad) {
1165 return getScalePadFilters(width, height, data.aspect, data.pad);
117 } else {
118 // No autopad requested, rescale to target size
1199 return ['scale=' + width + ':' + height];
120 }
121 } else {
122 // Keep input aspect ratio
123
12437 if (fixedWidth) {
12531 return ['scale=' + (Math.round(Number(fixedWidth[1]) / 2) * 2) + ':trunc(ow/a/2)*2'];
126 } else {
1276 return ['scale=trunc(oh*a/2)*2:' + (Math.round(Number(fixedHeight[1]) / 2) * 2)];
128 }
129 }
130 } else {
1311 throw new Error('Invalid size specified: ' + data.size);
132 }
133}
134
135
136/*
137 *! Video size-related methods
138 */
139
1401module.exports = function(proto) {
141 /**
142 * Keep display aspect ratio
143 *
144 * This method is useful when converting an input with non-square pixels to an output format
145 * that does not support non-square pixels. It rescales the input so that the display aspect
146 * ratio is the same.
147 *
148 * @method FfmpegCommand#keepDAR
149 * @category Video size
150 * @aliases keepPixelAspect,keepDisplayAspect,keepDisplayAspectRatio
151 *
152 * @return FfmpegCommand
153 */
1541 proto.keepPixelAspect = // Only for compatibility, this is not about keeping _pixel_ aspect ratio
155 proto.keepDisplayAspect =
156 proto.keepDisplayAspectRatio =
157 proto.keepDAR = function() {
1581 return this.videoFilters(
159 'scale=\'w=if(gt(sar,1),iw*sar,iw):h=if(lt(sar,1),ih/sar,ih)\'',
160 'setsar=1'
161 );
162 };
163
164
165 /**
166 * Set output size
167 *
168 * The 'size' parameter can have one of 4 forms:
169 * - 'X%': rescale to xx % of the original size
170 * - 'WxH': specify width and height
171 * - 'Wx?': specify width and compute height from input aspect ratio
172 * - '?xH': specify height and compute width from input aspect ratio
173 *
174 * Note: both dimensions will be truncated to multiples of 2.
175 *
176 * @method FfmpegCommand#size
177 * @category Video size
178 * @aliases withSize,setSize
179 *
180 * @param {String} size size string, eg. '33%', '320x240', '320x?', '?x240'
181 * @return FfmpegCommand
182 */
1831 proto.withSize =
184 proto.setSize =
185 proto.size = function(size) {
18652 var filters = createSizeFilters(this, 'size', size);
187
18851 this._sizeFilters.clear();
18951 this._sizeFilters(filters);
190
19151 return this;
192 };
193
194
195 /**
196 * Set output aspect ratio
197 *
198 * @method FfmpegCommand#aspect
199 * @category Video size
200 * @aliases withAspect,withAspectRatio,setAspect,setAspectRatio,aspectRatio
201 *
202 * @param {String|Number} aspect aspect ratio (number or 'X:Y' string)
203 * @return FfmpegCommand
204 */
2051 proto.withAspect =
206 proto.withAspectRatio =
207 proto.setAspect =
208 proto.setAspectRatio =
209 proto.aspect =
210 proto.aspectRatio = function(aspect) {
21115 var a = Number(aspect);
21215 if (isNaN(a)) {
2133 var match = aspect.match(/^(\d+):(\d+)$/);
2143 if (match) {
2152 a = Number(match[1]) / Number(match[2]);
216 } else {
2171 throw new Error('Invalid aspect ratio: ' + aspect);
218 }
219 }
220
22114 var filters = createSizeFilters(this, 'aspect', a);
222
22314 this._sizeFilters.clear();
22414 this._sizeFilters(filters);
225
22614 return this;
227 };
228
229
230 /**
231 * Enable auto-padding the output
232 *
233 * @method FfmpegCommand#autopad
234 * @category Video size
235 * @aliases applyAutopadding,applyAutoPadding,applyAutopad,applyAutoPad,withAutopadding,withAutoPadding,withAutopad,withAutoPad,autoPad
236 *
237 * @param {Boolean} [pad=true] enable/disable auto-padding
238 * @param {String} [color='black'] pad color
239 */
2401 proto.applyAutopadding =
241 proto.applyAutoPadding =
242 proto.applyAutopad =
243 proto.applyAutoPad =
244 proto.withAutopadding =
245 proto.withAutoPadding =
246 proto.withAutopad =
247 proto.withAutoPad =
248 proto.autoPad =
249 proto.autopad = function(pad, color) {
250 // Allow autopad(color)
25114 if (typeof pad === 'string') {
2521 color = pad;
2531 pad = true;
254 }
255
256 // Allow autopad() and autopad(undefined, color)
25714 if (typeof pad === 'undefined') {
2581 pad = true;
259 }
260
26114 var filters = createSizeFilters(this, 'pad', pad ? color || 'black' : false);
262
26314 this._sizeFilters.clear();
26414 this._sizeFilters(filters);
265
26614 return this;
267 };
268};
269

lib/presets/flashvideo.js

100%
2
2
0
LineHitsSource
1/*jshint node:true */
2'use strict';
3
41exports.load = function(ffmpeg) {
518 ffmpeg
6 .format('flv')
7 .flvmeta()
8 .size('320x?')
9 .videoBitrate('512k')
10 .videoCodec('libx264')
11 .fps(24)
12 .audioBitrate('96k')
13 .audioCodec('aac')
14 .strict()
15 .audioFrequency(22050)
16 .audioChannels(2);
17};
18

lib/presets/podcast.js

100%
2
2
0
LineHitsSource
1/*jshint node:true */
2'use strict';
3
41exports.load = function(ffmpeg) {
51 ffmpeg
6 .format('m4v')
7 .videoBitrate('512k')
8 .videoCodec('libx264')
9 .size('320x176')
10 .audioBitrate('128k')
11 .audioCodec('aac')
12 .strict()
13 .audioChannels(1)
14 .outputOptions(['-flags', '+loop', '-cmp', '+chroma', '-partitions','+parti4x4+partp8x8+partb8x8', '-flags2',
15 '+mixed_refs', '-me_method umh', '-subq 5', '-bufsize 2M', '-rc_eq \'blurCplx^(1-qComp)\'',
16 '-qcomp 0.6', '-qmin 10', '-qmax 51', '-qdiff 4', '-level 13' ]);
17};
18

lib/processor.js

85%
360
307
53
LineHitsSource
1/*jshint node:true*/
2'use strict';
3
41var spawn = require('child_process').spawn;
51var PassThrough = require('stream').PassThrough;
61var path = require('path');
71var fs = require('fs');
81var async = require('async');
91var utils = require('./utils');
10
11
12/*
13 *! Processor methods
14 */
15
16
17/**
18 * @param {FfmpegCommand} command
19 * @param {String|Writable} target
20 * @param {Object} [pipeOptions]
21 * @private
22 */
23function _process(command, target, pipeOptions) {
2419 var isStream;
25
2619 if (typeof target === 'string') {
2716 isStream = false;
28 } else {
293 isStream = true;
303 pipeOptions = pipeOptions || {};
31 }
32
33 // Ensure we send 'end' or 'error' only once
3419 var ended = false;
35 function emitEnd(err, stdout, stderr) {
3624 if (!ended) {
3719 ended = true;
38
3919 if (err) {
405 command.emit('error', err, stdout, stderr);
41 } else {
4214 command.emit('end', stdout, stderr);
43 }
44 }
45 }
46
4719 command._prepare(function(err, args) {
4819 if (err) {
491 return emitEnd(err);
50 }
51
5218 if (isStream) {
533 args.push('pipe:1');
54
553 if (command.options.flvmeta) {
563 command.logger.warn('Updating flv metadata is not supported for streams');
573 command.options.flvmeta = false;
58 }
59 } else {
6015 args.push('-y', target);
61 }
62
63 // Get input stream if any
6418 var inputStream = command._inputs.filter(function(input) {
6518 return typeof input.source !== 'string';
66 })[0];
67
68 // Run ffmpeg
6918 var stdout = null;
7018 var stderr = '';
7118 command._spawnFfmpeg(
72 args,
73
74 { niceness: command.options.niceness },
75
76 function processCB(ffmpegProc) {
7718 command.ffmpegProc = ffmpegProc;
7818 command.emit('start', 'ffmpeg ' + args.join(' '));
79
80 // Pipe input stream if any
8118 if (inputStream) {
822 inputStream.source.on('error', function(err) {
830 emitEnd(new Error('Input stream error: ' + err.message));
840 ffmpegProc.kill();
85 });
86
872 inputStream.source.resume();
882 inputStream.source.pipe(ffmpegProc.stdin);
89 }
90
91 // Setup timeout if requested
9218 var processTimer;
9318 if (command.options.timeout) {
944 processTimer = setTimeout(function() {
953 var msg = 'process ran into a timeout (' + command.options.timeout + 's)';
96
973 emitEnd(new Error(msg), stdout, stderr);
983 ffmpegProc.kill();
99 }, command.options.timeout * 1000);
100 }
101
10218 if (isStream) {
103 // Pipe ffmpeg stdout to output stream
1043 ffmpegProc.stdout.pipe(target, pipeOptions);
105
106 // Handle output stream events
1073 target.on('close', function() {
1082 command.logger.debug('Output stream closed, scheduling kill for ffmpgeg process');
109
110 // Don't kill process yet, to give a chance to ffmpeg to
111 // terminate successfully first This is necessary because
112 // under load, the process 'exit' event sometimes happens
113 // after the output stream 'close' event.
1142 setTimeout(function() {
1152 emitEnd(new Error('Output stream closed'));
1162 ffmpegProc.kill();
117 }, 20);
118 });
119
1203 target.on('error', function(err) {
1210 command.logger.debug('Output stream error, killing ffmpgeg process');
1220 emitEnd(new Error('Output stream error: ' + err.message));
1230 ffmpegProc.kill();
124 });
125 } else {
126 // Gather ffmpeg stdout
12715 stdout = '';
12815 ffmpegProc.stdout.on('data', function (data) {
1290 stdout += data;
130 });
131 }
132
133 // Process ffmpeg stderr data
13418 command._codecDataSent = false;
13518 ffmpegProc.stderr.on('data', function (data) {
136324 stderr += data;
137
138324 if (!command._codecDataSent && command.listeners('codecData').length) {
13911 utils.extractCodecData(command, stderr);
140 }
141
142324 if (command.listeners('progress').length) {
14326 var duration = 0;
144
14526 if (command._ffprobeData && command._ffprobeData.format && command._ffprobeData.format.duration) {
14621 duration = Number(command._ffprobeData.format.duration);
147 }
148
14926 utils.extractProgress(command, stderr, duration);
150 }
151 });
152 },
153
154 function endCB(err) {
15518 delete command.ffmpegProc;
156
15718 if (err) {
1584 emitEnd(err, stdout, stderr);
159 } else {
16014 if (command.options.flvmeta) {
16111 command._getFlvtoolPath(function(err, flvtool) {
162 // No error possible here, _getFlvtoolPath was called by _prepare
163
16411 spawn(flvtool, ['-U', target])
165 .on('error', function(err) {
1660 emitEnd(new Error('Error running ' + flvtool + ': ' + err.message));
167 })
168 .on('exit', function(code, signal) {
16911 if (code !== 0 || signal) {
1700 emitEnd(
171 new Error(flvtool + ' ' +
172 (signal ? 'received signal ' + signal
173 : 'exited with code ' + code))
174 );
175 } else {
17611 emitEnd(null, stdout, stderr);
177 }
178 });
179 });
180 } else {
1813 emitEnd(null, stdout, stderr);
182 }
183 }
184 }
185 );
186 });
187}
188
189
190/**
191 * Run ffprobe asynchronously and store data in command
192 *
193 * @param {FfmpegCommand} command
194 * @private
195 */
196function runFfprobe(command) {
1971 command.ffprobe(function(err, data) {
1981 command._ffprobeData = data;
199 });
200}
201
202
2031module.exports = function(proto) {
204 /**
205 * Emitted just after ffmpeg has been spawned.
206 *
207 * @event FfmpegCommand#start
208 * @param {String} command ffmpeg command line
209 */
210
211 /**
212 * Emitted when ffmpeg reports progress information
213 *
214 * @event FfmpegCommand#progress
215 * @param {Object} progress progress object
216 */
217
218 /**
219 * Emitted when ffmpeg reports input codec data
220 *
221 * @event FfmpegCommand#codecData
222 * @param {Object} codecData codec data object
223 */
224
225 /**
226 * Emitted when an error happens when preparing or running a command
227 *
228 * @event FfmpegCommand#error
229 * @param {Error} error error
230 * @param {String|null} stdout ffmpeg stdout, unless outputting to a stream
231 * @param {String|null} stderr ffmpeg stderr
232 */
233
234 /**
235 * Emitted when a command finishes processing
236 *
237 * @event FfmpegCommand#end
238 * @param {Array|null} [filenames] generated filenames when taking screenshots, null otherwise
239 */
240
241
242 /**
243 * Spawn an ffmpeg process
244 *
245 * The 'options' argument may contain the following keys:
246 * - 'niceness': specify process niceness, ignored on Windows (default: 0)
247 * - 'captureStdout': capture stdout and pass it to 'endCB' as its 2nd argument (default: false)
248 * - 'captureStderr': capture stderr and pass it to 'endCB' as its 3rd argument (default: false)
249 *
250 * The 'processCB' callback, if present, is called as soon as the process is created and
251 * receives a nodejs ChildProcess object. It may not be called at all if an error happens
252 * before spawning the process.
253 *
254 * The 'endCB' callback is called either when an error occurs or when the ffmpeg process finishes.
255 *
256 * @method FfmpegCommand#_spawnFfmpeg
257 * @param {Array} args ffmpeg command line argument list
258 * @param {Object} [options] spawn options (see above)
259 * @param {Function} [processCB] callback called with process object when it has been created
260 * @param {Function} endCB callback with signature (err, stdout, stderr)
261 * @private
262 */
2631 proto._spawnFfmpeg = function(args, options, processCB, endCB) {
264 // Enable omitting options
26530 if (typeof options === 'function') {
2668 endCB = processCB;
2678 processCB = options;
2688 options = {};
269 }
270
271 // Enable omitting processCB
27230 if (typeof endCB === 'undefined') {
27312 endCB = processCB;
27412 processCB = function() {};
275 }
276
277 // Find ffmpeg
27830 this._getFfmpegPath(function(err, command) {
27930 if (err) {
2800 return endCB(err);
28130 } else if (!command || command.length === 0) {
2820 return endCB(new Error('Cannot find ffmpeg'));
283 }
284
285 // Apply niceness
28630 if (options.niceness && options.niceness !== 0 && !utils.isWindows) {
2870 args.unshift('-n', options.niceness, command);
2880 command = 'nice';
289 }
290
29130 var stdout = null;
29230 var stdoutClosed = false;
293
29430 var stderr = null;
29530 var stderrClosed = false;
296
297 // Spawn process
29830 var ffmpegProc = spawn(command, args, options);
299
30030 if (ffmpegProc.stderr && options.captureStderr) {
3011 ffmpegProc.stderr.setEncoding('utf8');
302 }
303
30430 ffmpegProc.on('error', function(err) {
3050 endCB(err);
306 });
307
308 // Ensure we wait for captured streams to end before calling endCB
30930 var exitError = null;
310 function handleExit(err) {
31135 if (err) {
3124 exitError = err;
313 }
314
31535 if (processExited &&
316 (stdoutClosed || !options.captureStdout) &&
317 (stderrClosed || !options.captureStderr)) {
31830 endCB(exitError, stdout, stderr);
319 }
320 }
321
322 // Handle process exit
32330 var processExited = false;
32430 ffmpegProc.on('exit', function(code, signal) {
32530 processExited = true;
326
32730 if (code) {
3283 handleExit(new Error('ffmpeg exited with code ' + code));
32927 } else if (signal) {
3301 handleExit(new Error('ffmpeg was killed with signal ' + signal));
331 } else {
33226 handleExit();
333 }
334 });
335
336 // Capture stdout if specified
33730 if (options.captureStdout) {
3384 stdout = '';
339
3404 ffmpegProc.stdout.on('data', function(data) {
34111 stdout += data;
342 });
343
3444 ffmpegProc.stdout.on('close', function() {
3454 stdoutClosed = true;
3464 handleExit();
347 });
348 }
349
350 // Capture stderr if specified
35130 if (options.captureStderr) {
3521 stderr = '';
353
3541 ffmpegProc.stderr.on('data', function(data) {
3550 stderr += data;
356 });
357
3581 ffmpegProc.stderr.on('close', function() {
3591 stderrClosed = true;
3601 handleExit();
361 });
362 }
363
364 // Call process callback
36530 processCB(ffmpegProc);
366 });
367 };
368
369
370 /**
371 * Build the argument list for an ffmpeg command
372 *
373 * @method FfmpegCommand#_getArguments
374 * @return argument list
375 * @private
376 */
3771 proto._getArguments = function() {
37853 var audioFilters = this._audioFilters.get();
37953 var videoFilters = this._videoFilters.get().concat(this._sizeFilters.get());
380
38153 return this._inputs.reduce(function(args, input) {
38254 var source = (typeof input.source === 'string') ? input.source : '-';
383
38454 return args.concat(
385 input.before.get(),
386 ['-i', source],
387 input.after.get()
388 );
389 }, [])
390 .concat(
391 this._audio.get(),
392 audioFilters.length ? ['-filter:a', audioFilters.join(',')] : [],
393 this._video.get(),
394 videoFilters.length ? ['-filter:v', videoFilters.join(',')] : [],
395 this._output.get()
396 );
397 };
398
399
400 /**
401 * Prepare execution of an ffmpeg command
402 *
403 * Checks prerequisites for the execution of the command (codec/format availability, flvtool...),
404 * then builds the argument list for ffmpeg and pass them to 'callback'.
405 *
406 * @method FfmpegCommand#_prepare
407 * @param {Function} callback callback with signature (err, args)
408 * @param {Boolean} [readMetadata=false] read metadata before processing
409 * @private
410 */
4111 proto._prepare = function(callback, readMetadata) {
41221 var self = this;
413
41421 async.waterfall([
415 // Check codecs and formats
416 function(cb) {
41721 self._checkCapabilities(cb);
418 },
419
420 // Read metadata if required
421 function(cb) {
42220 if (!readMetadata) {
42318 return cb();
424 }
425
4262 self.ffprobe(function(err, data) {
4272 if (!err) {
4282 self._ffprobeData = data;
429 }
430
4312 cb();
432 });
433 },
434
435 // Check for flvtool2/flvmeta if necessary
436 function(cb) {
43720 if (self.options.flvmeta) {
43818 self._getFlvtoolPath(function(err) {
43918 cb(err);
440 });
441 } else {
4422 cb();
443 }
444 },
445
446 // Build argument list
447 function(cb) {
44820 var args;
44920 try {
45020 args = self._getArguments();
451 } catch(e) {
4520 return cb(e);
453 }
454
45520 cb(null, args);
456 }
457 ], callback);
458
45921 if (!readMetadata) {
460 // Read metadata as soon as 'progress' listeners are added
461
46219 if (this.listeners('progress').length > 0) {
463 // Read metadata in parallel
4641 runFfprobe(this);
465 } else {
466 // Read metadata as soon as the first 'progress' listener is added
46718 this.once('newListener', function(event) {
4680 if (event === 'progress') {
4690 runFfprobe(this);
470 }
471 });
472 }
473 }
474 };
475
476
477 /**
478 * Execute ffmpeg command and save output to a file
479 *
480 * @method FfmpegCommand#save
481 * @category Processing
482 * @aliases saveToFile
483 *
484 * @param {String} output file path
485 * @return FfmpegCommand
486 */
4871 proto.saveToFile =
488 proto.save = function(output) {
48916 _process(this, output);
490 };
491
492
493 /**
494 * Execute ffmpeg command and save output to a stream
495 *
496 * If 'stream' is not specified, a PassThrough stream is created and returned.
497 * 'options' will be used when piping ffmpeg output to the output stream
498 * (@see http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options)
499 *
500 * @method FfmpegCommand#pipe
501 * @category Processing
502 * @aliases stream,writeToStream
503 *
504 * @param {stream.Writable} [stream] output stream
505 * @param {Object} [options={}] pipe options
506 * @return Output stream
507 */
5081 proto.writeToStream =
509 proto.pipe =
510 proto.stream = function(stream, options) {
5113 if (stream && !('writable' in stream)) {
5121 options = stream;
5131 stream = undefined;
514 }
515
5163 if (!stream) {
5171 if (process.version.match(/v0\.8\./)) {
5180 throw new Error('PassThrough stream is not supported on node v0.8');
519 }
520
5211 stream = new PassThrough();
522 }
523
5243 _process(this, stream, options);
5253 return stream;
526 };
527
528
529 /**
530 * Merge (concatenate) inputs to a single file
531 *
532 * Warning: soon to be deprecated
533 *
534 * @method FfmpegCommand#mergeToFile
535 * @category Processing
536 *
537 * @param {String} targetfile output file path
538 */
5391 proto.mergeToFile = function(targetfile) {
5401 var outputfile = path.normalize(targetfile);
5411 if(fs.existsSync(outputfile)){
5420 return this.emit('error', new Error('Output file already exists, merge aborted'));
543 }
544
5451 var self = this;
546
547 // creates intermediate copies of each video.
548 function makeIntermediateFile(_mergeSource,_callback) {
5493 var fname = _mergeSource + '.temp.mpg';
5503 var args = self._output.get().concat(['-i', _mergeSource, '-qscale:v', 1, fname]);
551
5523 self._spawnFfmpeg(args, function(err) {
5533 _callback(err, fname);
554 });
555 }
556
557 // concat all created intermediate copies
558 function concatIntermediates(target, intermediatesList, _callback) {
5591 var fname = path.normalize(target) + '.temp.merged.mpg';
560
5611 var args = [
562 // avoid too many log messages from ffmpeg
563 '-loglevel', 'panic',
564 '-i', 'concat:' + intermediatesList.join('|'),
565 '-c', 'copy',
566 fname
567 ];
568
5691 self._spawnFfmpeg(args, {captureStdout:true,captureStderr:true}, function(err) {
5701 _callback(err, fname);
571 });
572 }
573
574 function quantizeConcat(concatResult, numFiles, _callback) {
5751 var args = [
576 '-i', concatResult,
577 '-qscale:v',numFiles,
578 targetfile
579 ];
580
5811 self._spawnFfmpeg(args, function(err) {
5821 _callback(err);
583 });
584 }
585
586 function deleteIntermediateFiles(intermediates, callback) {
5872 async.each(intermediates, function(item,cb){
5888 fs.exists(item,function(exists){
5898 if(exists){
5904 fs.unlink(item ,cb);
591 }
592 else{
5934 cb();
594 }
595
596 });
597 }, callback);
598 }
599
600 function makeProgress() {
6015 progress.createdFiles = progress.createdFiles + 1;
6025 progress.percent = progress.createdFiles / progress.totalFiles * 100;
6035 self.emit('progress', progress);
604 }
605
6061 if (this._inputs.length < 2) {
6070 return this.emit('error', new Error('No file added to be merged'));
608 }
609
6104 var mergeList = this._inputs.map(function(input) { return input.source; });
611
6121 var progress = {frames : 0,
613 currentFps: 0,
614 currentKbps: 0,
615 targetSize: 0,
616 timemark: 0,
617 percent: 0,
618 totalFiles: mergeList.length + 2,
619 createdFiles: 0};
620
6214 var toDelete = mergeList.map(function(name) { return name + '.temp.mpg'; });
6221 toDelete.push(outputfile + '.temp.merged.mpg');
6231 deleteIntermediateFiles(toDelete);
624
6251 var intermediateFiles = [];
626
6271 async.whilst(
628 function(){
6294 return (mergeList.length !== 0);
630 },
631 function (callback){
6323 makeIntermediateFile(mergeList.shift(), function(err, createdIntermediateFile) {
6333 if(err) {
6340 return callback(err);
635 }
636
6373 if(!createdIntermediateFile) {
6380 return callback(new Error('Invalid intermediate file'));
639 }
640
6413 intermediateFiles.push(createdIntermediateFile);
6423 makeProgress();
6433 callback();
644 });
645 },
646 function(err) {
6471 if (err) {
6480 return self.emit('error', err);
649 }
650
6511 concatIntermediates(targetfile, intermediateFiles, function(err, concatResult) {
6521 if(err) {
6530 return self.emit('error', err);
654 }
655
6561 if(!concatResult) {
6570 return self.emit('error', new Error('Invalid concat result file'));
658 }
659
6601 makeProgress();
6611 quantizeConcat(concatResult, intermediateFiles.length, function() {
6621 makeProgress();
663 // add concatResult to intermediates list so it can be deleted too.
6641 intermediateFiles.push(concatResult);
6651 deleteIntermediateFiles(intermediateFiles, function(err) {
6661 if (err) {
6670 self.emit('error', err);
668 } else {
6691 self.emit('end');
670 }
671 });
672 });
673 });
674 }
675 );
676 };
677
678
679 /**
680 * Take screenshots
681 *
682 * The 'config' parameter may either be the number of screenshots to take or an object
683 * with the following keys:
684 * - 'count': screenshot count
685 * - 'timemarks': array of screenshot timestamps in seconds (defaults to taking screenshots at regular intervals)
686 * - 'filename': screenshot filename pattern (defaults to 'tn_%ss' or 'tn_%ss_%i' for multiple screenshots)
687 *
688 * The 'filename' option may contain tokens that will be replaced for each screenshot taken:
689 * - '%s': offset in seconds
690 * - '%w': screenshot width
691 * - '%h': screenshot height
692 * - '%r': screenshot resolution (eg. '320x240')
693 * - '%f': input filename
694 * - '%b': input basename (filename w/o extension)
695 * - '%i': index of screenshot in timemark array (can be zero-padded by using it like `%000i`)
696 *
697 * @method FfmpegCommand#takeScreenshots
698 * @category Processing
699 *
700 * @param {Number|Object} config screenshot count or configuration object (see above)
701 * @param {String} [folder='.'] output directory
702 */
7031 proto.takeScreenshots = function(config, folder) {
7042 var width, height;
7052 var self = this;
706
707 function _computeSize(size) {
708 // Select video stream with biggest resolution
7092 var vstream = self._ffprobeData.streams.reduce(function(max, stream) {
7102 if (stream.codec_type !== 'video') return max;
7112 return max.width * max.height < stream.width * stream.height ? stream : max;
712 }, { width: 0, height: 0 });
713
7142 var w = vstream.width;
7152 var h = vstream.height;
7162 var a = w / h;
717
7182 var fixedSize = size.match(/([0-9]+)x([0-9]+)/);
7192 var fixedWidth = size.match(/([0-9]+)x\?/);
7202 var fixedHeight = size.match(/\?x([0-9]+)/);
7212 var percentRatio = size.match(/\b([0-9]{1,3})%/);
722
7232 if (fixedSize) {
7240 width = Number(fixedSize[1]);
7250 height = Number(fixedSize[2]);
7262 } else if (fixedWidth) {
7272 width = Number(fixedWidth[1]);
7282 height = width / a;
7290 } else if (fixedHeight) {
7300 height = Number(fixedHeight[1]);
7310 width = height * a;
732 } else {
7330 var pc = Number(percentRatio[0]) / 100;
7340 width = w * pc;
7350 height = h * pc;
736 }
737 }
738
739 function _zeroPad(number, len) {
7404 len = len-String(number).length+2;
7414 return new Array(len<0?0:len).join('0')+number;
742 }
743
744 function _renderOutputName(j, offset) {
7454 var result = filename;
7464 if(/%0*i/.test(result)) {
7474 var numlen = String(result.match(/%(0*)i/)[1]).length;
7484 result = result.replace(/%0*i/, _zeroPad(j, numlen));
749 }
7504 result = result.replace('%s', offset);
7514 result = result.replace('%w', width);
7524 result = result.replace('%h', height);
7534 result = result.replace('%r', width+'x'+height);
7544 result = result.replace('%f', path.basename(inputfile));
7554 result = result.replace('%b', path.basename(inputfile, path.extname(inputfile)));
7564 return result;
757 }
758
759 function _screenShotInternal() {
7602 self._prepare(function(err, args) {
7612 if(err) {
7620 return self.emit('error', err);
763 }
764
7652 _computeSize(self._sizeData.size);
766
7672 var duration = 0;
7682 if (self._ffprobeData && self._ffprobeData.format && self._ffprobeData.format.duration) {
7692 duration = Number(self._ffprobeData.format.duration);
770 }
771
7722 if (!duration) {
7730 var errString = 'meta data contains no duration, aborting screenshot creation';
7740 return self.emit('error', new Error(errString));
775 }
776
777 // check if all timemarks are inside duration
7782 if (Array.isArray(timemarks)) {
7792 for (var i = 0; i < timemarks.length; i++) {
780 /* convert percentage to seconds */
7814 if( timemarks[i].indexOf('%') > 0 ) {
7820 timemarks[i] = (parseInt(timemarks[i], 10) / 100) * duration;
783 }
7844 if (parseInt(timemarks[i], 10) > duration) {
785 // remove timemark from array
7860 timemarks.splice(i, 1);
7870 --i;
788 }
789 }
790 // if there are no more timemarks around, add one at end of the file
7912 if (timemarks.length === 0) {
7920 timemarks[0] = (duration * 0.9);
793 }
794 }
795 // get positions for screenshots (using duration of file minus 10% to remove fade-in/fade-out)
7962 var secondOffset = (duration * 0.9) / screenshotcount;
797
798 // reset iterator
7992 var j = 1;
800
8012 var filenames = [];
802
803 // use async helper function to generate all screenshots and
804 // fire callback just once after work is done
8052 async.until(
806 function() {
8076 return j > screenshotcount;
808 },
809 function(taskcallback) {
8104 var offset;
8114 if (Array.isArray(timemarks)) {
812 // get timemark for current iteration
8134 offset = timemarks[(j - 1)];
814 } else {
8150 offset = secondOffset * j;
816 }
817
8184 var fname = _renderOutputName(j, offset) + (fileextension ? fileextension : '.jpg');
8194 var target = path.join(folder, fname);
820
821 // build screenshot command
8224 var allArgs = [
823 '-ss', Math.floor(offset * 100) / 100
824 ]
825 .concat(args)
826 .concat([
827 '-vframes', '1',
828 '-an',
829 '-vcodec', 'mjpeg',
830 '-f', 'rawvideo',
831 '-y', target
832 ]);
833
8344 j++;
835
8364 self._spawnFfmpeg(allArgs, taskcallback);
8374 filenames.push(fname);
838 },
839 function(err) {
8402 if (err) {
8410 self.emit('error', err);
842 } else {
8432 self.emit('end', filenames);
844 }
845 }
846 );
847 }, true);
848 }
849
8502 var timemarks, screenshotcount, filename, fileextension;
8512 if (typeof config === 'object') {
852 // use json object as config
8532 if (config.count) {
8542 screenshotcount = config.count;
855 }
8562 if (config.timemarks) {
8572 timemarks = config.timemarks;
858 }
8592 if (config.fileextension){
8600 fileextension = config.fileextension;
861 }
862 } else {
863 // assume screenshot count as parameter
8640 screenshotcount = config;
8650 timemarks = null;
866 }
867
8682 if (!this._sizeData || !this._sizeData.size) {
8690 throw new Error('Size must be specified');
870 }
871
8722 var inputfile = this._currentInput.source;
873
8742 filename = config.filename || 'tn_%ss';
8752 if(!/%0*i/.test(filename) && Array.isArray(timemarks) && timemarks.length > 1 ) {
876 // if there are multiple timemarks but no %i in filename add one
877 // so we won't overwrite the same thumbnail with each timemark
8781 filename += '_%i';
879 }
8802 folder = folder || '.';
881
882 // check target folder
8832 fs.exists(folder, function(exists) {
8842 if (!exists) {
8852 fs.mkdir(folder, '0755', function(err) {
8862 if (err !== null) {
8870 self.emit('error', err);
888 } else {
8892 _screenShotInternal();
890 }
891 });
892 } else {
8930 _screenShotInternal();
894 }
895 });
896 };
897
898
899 /**
900 * Renice current and/or future ffmpeg processes
901 *
902 * Ignored on Windows platforms.
903 *
904 * @method FfmpegCommand#renice
905 * @category Processing
906 *
907 * @param {Number} [niceness=0] niceness value between -20 (highest priority) and 20 (lowest priority)
908 * @return FfmpegCommand
909 */
9101 proto.renice = function(niceness) {
9112 if (!utils.isWindows) {
9122 niceness = niceness || 0;
913
9142 if (niceness < -20 || niceness > 20) {
9151 this.logger.warn('Invalid niceness value: ' + niceness + ', must be between -20 and 20');
916 }
917
9182 niceness = Math.min(20, Math.max(-20, niceness));
9192 this.options.niceness = niceness;
920
9212 if (this.ffmpegProc) {
9221 var logger = this.logger;
9231 var pid = this.ffmpegProc.pid;
9241 var renice = spawn('renice', [niceness, '-p', pid]);
925
9261 renice.on('error', function(err) {
9270 logger.warn('could not renice process ' + pid + ': ' + err.message);
928 });
929
9301 renice.on('exit', function(code, signal) {
9311 if (code) {
9320 logger.warn('could not renice process ' + pid + ': renice exited with ' + code);
9331 } else if (signal) {
9340 logger.warn('could not renice process ' + pid + ': renice was killed by signal ' + signal);
935 } else {
9361 logger.info('successfully reniced process ' + pid + ' to ' + niceness + ' niceness');
937 }
938 });
939 }
940 }
941
9422 return this;
943 };
944
945
946 /**
947 * Kill current ffmpeg process, if any
948 *
949 * @method FfmpegCommand#kill
950 * @category Processing
951 *
952 * @param {String} [signal=SIGKILL] signal name
953 * @return FfmpegCommand
954 */
9551 proto.kill = function(signal) {
9563 if (!this.ffmpegProc) {
9570 this.options.logger.warn('No running ffmpeg process, cannot send signal');
958 } else {
9593 this.ffmpegProc.kill(signal || 'SIGKILL');
960 }
961
9623 return this;
963 };
964};
965

lib/utils.js

92%
82
76
6
LineHitsSource
1/*jshint node:true*/
2'use strict';
3
41var exec = require('child_process').exec;
51var isWindows = require('os').platform().match(/win(32|64)/);
6
71var whichCache = {};
8
9/**
10 * Parse progress line from ffmpeg stderr
11 *
12 * @param {String} line progress line
13 * @return progress object
14 * @private
15 */
16function parseProgressLine(line) {
1726 var progress = {};
18
19 // Remove all spaces after = and trim
2026 line = line.replace(/=\s+/g, '=').trim();
2126 var progressParts = line.split(' ');
22
23 // Split every progress part by "=" to get key and value
2426 for(var i = 0; i < progressParts.length; i++) {
25110 var progressSplit = progressParts[i].split('=', 2);
26110 var key = progressSplit[0];
27110 var value = progressSplit[1];
28
29 // This is not a progress line
30110 if(typeof value === 'undefined')
3114 return null;
32
3396 progress[key] = value;
34 }
35
3612 return progress;
37}
38
39
401var utils = module.exports = {
41 isWindows: isWindows,
42
43 /**
44 * Create an argument list
45 *
46 * Returns a function that adds new arguments to the list.
47 * It also has the following methods:
48 * - clear() empties the argument list
49 * - get() returns the argument list
50 * - find(arg, count) finds 'arg' in the list and return the following 'count' items, or undefined if not found
51 * - remove(arg, count) remove 'arg' in the list as well as the following 'count' items
52 *
53 * @private
54 */
55 args: function() {
561434 var list = [];
571434 var argfunc = function() {
58326 if (arguments.length === 1 && Array.isArray(arguments[0])) {
5990 list = list.concat(arguments[0]);
60 } else {
61236 list = list.concat([].slice.call(arguments));
62 }
63 };
64
651434 argfunc.clear = function() {
6683 list = [];
67 };
68
691434 argfunc.get = function() {
70485 return list;
71 };
72
731434 argfunc.find = function(arg, count) {
7495 var index = list.indexOf(arg);
7595 if (index !== -1) {
7669 return list.slice(index + 1, index + 1 + (count || 0));
77 }
78 };
79
801434 argfunc.remove = function(arg, count) {
810 var index = list.indexOf(arg);
820 if (index !== -1) {
830 list.splice(index, (count || 0) + 1);
84 }
85 };
86
871434 return argfunc;
88 },
89
90
91 /**
92 * Search for an executable
93 *
94 * Uses 'which' or 'where' depending on platform
95 *
96 * @param {String} name executable name
97 * @param {Function} callback callback with signature (err, path)
98 * @private
99 */
100 which: function(name, callback) {
1019 if (name in whichCache) {
1026 return callback(null, whichCache[name]);
103 }
104
1053 var cmd = 'which ' + name;
1063 if (isWindows) {
1070 cmd = 'where ' + name + '.exe';
108 }
109
1103 exec(cmd, function(err, stdout) {
1113 if (err) {
112 // Treat errors as not found
1130 callback(null, whichCache[name] = '');
114 } else {
1153 callback(null, whichCache[name] = stdout.replace(/\n$/, ''));
116 }
117 });
118 },
119
120
121 /**
122 * Convert a [[hh:]mm:]ss[.xxx] timemark into seconds
123 *
124 * @param {String} timemark timemark string
125 * @return Number
126 * @private
127 */
128 timemarkToSeconds: function(timemark) {
12912 if(timemark.indexOf(':') === -1 && timemark.indexOf('.') >= 0)
1300 return Number(timemark);
131
13212 var parts = timemark.split(':');
133
134 // add seconds
13512 var secs = Number(parts.pop());
136
13712 if (parts.length) {
138 // add minutes
13912 secs += Number(parts.pop()) * 60;
140 }
141
14212 if (parts.length) {
143 // add hours
14412 secs += Number(parts.pop()) * 3600;
145 }
146
14712 return secs;
148 },
149
150
151 /**
152 * Extract codec data from ffmpeg stderr and emit 'codecData' event if appropriate
153 *
154 * @param {FfmpegCommand} command event emitter
155 * @param {String} stderr ffmpeg stderr output
156 * @private
157 */
158 extractCodecData: function(command, stderr) {
15911 var format= /Input #[0-9]+, ([^ ]+),/.exec(stderr);
16011 var dur = /Duration\: ([^,]+)/.exec(stderr);
16111 var audio = /Audio\: (.*)/.exec(stderr);
16211 var video = /Video\: (.*)/.exec(stderr);
16311 var codecObject = { format: '', audio: '', video: '', duration: '' };
164
16511 if (format && format.length > 1) {
1668 codecObject.format = format[1];
167 }
168
16911 if (dur && dur.length > 1) {
1708 codecObject.duration = dur[1];
171 }
172
17311 if (audio && audio.length > 1) {
1747 audio = audio[1].split(', ');
1757 codecObject.audio = audio[0];
1767 codecObject.audio_details = audio;
177 }
17811 if (video && video.length > 1) {
1797 video = video[1].split(', ');
1807 codecObject.video = video[0];
1817 codecObject.video_details = video;
182 }
183
18411 var codecInfoPassed = /Press (\[q\]|ctrl-c) to stop/.test(stderr);
18511 if (codecInfoPassed) {
1861 command.emit('codecData', codecObject);
1871 command._codecDataSent = true;
188 }
189 },
190
191
192 /**
193 * Extract progress data from ffmpeg stderr and emit 'progress' event if appropriate
194 *
195 * @param {FfmpegCommand} command event emitter
196 * @param {Number} [duration=0] expected output duration in seconds
197 */
198 extractProgress: function(command, stderr, duration) {
19926 var lines = stderr.split(/\r\n|\r|\n/g);
20026 var lastline = lines[lines.length - 2];
20126 var progress;
202
20326 if (lastline) {
20426 progress = parseProgressLine(lastline);
205 }
206
20726 if (progress) {
208 // build progress report object
20912 var ret = {
210 frames: parseInt(progress.frame, 10),
211 currentFps: parseInt(progress.fps, 10),
212 currentKbps: parseFloat(progress.bitrate.replace('kbits/s', '')),
213 targetSize: parseInt(progress.size, 10),
214 timemark: progress.time
215 };
216
217 // calculate percent progress using duration
21812 if (duration && duration > 0) {
21912 ret.percent = (utils.timemarkToSeconds(ret.timemark) / duration) * 100;
220 }
221
22212 command.emit('progress', ret);
223 }
224 }
225};
226
make[1]: quittant le répertoire « /home/niko/dev/forks/node-fluent-ffmpeg » diff --git a/yarn.lock b/yarn.lock index 770445be..7c783672 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,11 +2,241 @@ # yarn lockfile v1 -"@babel/parser@^7.20.15": +"@ampproject/remapping@^2.2.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/code-frame@^7.22.13": + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" + integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== + dependencies: + "@babel/highlight" "^7.22.13" + chalk "^2.4.2" + +"@babel/compat-data@^7.22.9": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.3.tgz#3febd552541e62b5e883a25eb3effd7c7379db11" + integrity sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ== + +"@babel/core@^7.7.5": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.3.tgz#5ec09c8803b91f51cc887dedc2654a35852849c9" + integrity sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.3" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helpers" "^7.23.2" + "@babel/parser" "^7.23.3" + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.23.3" + "@babel/types" "^7.23.3" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.3.tgz#86e6e83d95903fbe7613f448613b8b319f330a8e" + integrity sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg== + dependencies: + "@babel/types" "^7.23.3" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + +"@babel/helper-compilation-targets@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52" + integrity sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw== + dependencies: + "@babel/compat-data" "^7.22.9" + "@babel/helper-validator-option" "^7.22.15" + browserslist "^4.21.9" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + +"@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" + +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-module-imports@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" + integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== + dependencies: + "@babel/types" "^7.22.15" + +"@babel/helper-module-transforms@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" + integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.20" + +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-string-parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" + integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + +"@babel/helper-validator-option@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040" + integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA== + +"@babel/helpers@^7.23.2": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.2.tgz#2832549a6e37d484286e15ba36a5330483cac767" + integrity sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ== + dependencies: + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.23.2" + "@babel/types" "^7.23.0" + +"@babel/highlight@^7.22.13": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" + integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.20.15", "@babel/parser@^7.22.15", "@babel/parser@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.3.tgz#0ce0be31a4ca4f1884b5786057cadcb6c3be58f9" integrity sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw== +"@babel/template@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" + +"@babel/traverse@^7.23.2", "@babel/traverse@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.3.tgz#26ee5f252e725aa7aca3474aa5b324eaf7908b5b" + integrity sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.3" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.3" + "@babel/types" "^7.23.3" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.3.tgz#d5ea892c07f2ec371ac704420f4dcdb07b5f9598" + integrity sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.20" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" + integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@jsdoc/salty@^0.2.1": version "0.2.5" resolved "https://registry.yarnpkg.com/@jsdoc/salty/-/salty-0.2.5.tgz#1b2fa5bb8c66485b536d86eee877c263d322f692" @@ -32,6 +262,24 @@ resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.5.tgz#3e0d2db570e9fb6ccb2dc8fde0be1d79ac810d39" integrity sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA== +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv@^6.12.3: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" @@ -42,6 +290,13 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" @@ -57,21 +312,74 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +append-transform@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" + integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== + dependencies: + default-require-extensions "^3.0.0" + +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + async@^0.2.9: version "0.2.10" resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" integrity sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== + +aws4@^1.8.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" + integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== + dependencies: + tweetnacl "^0.14.3" + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -109,11 +417,46 @@ browser-stdout@1.3.1: resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== +browserslist@^4.21.9: + version "4.22.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.1.tgz#ba91958d1a59b87dab6fed8dfbcb3da5e2e9c619" + integrity sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ== + dependencies: + caniuse-lite "^1.0.30001541" + electron-to-chromium "^1.4.535" + node-releases "^2.0.13" + update-browserslist-db "^1.0.13" + +caching-transform@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" + integrity sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA== + dependencies: + hasha "^5.0.0" + make-dir "^3.0.0" + package-hash "^4.0.0" + write-file-atomic "^3.0.0" + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + camelcase@^6.0.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== +caniuse-lite@^1.0.30001541: + version "1.0.30001561" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001561.tgz#752f21f56f96f1b1a52e97aae98c57c562d5d9da" + integrity sha512-NTt0DNoKe958Q0BE0j0c1V9jbUzhBxHIEJy7asmGrpE0yG63KTV7PLHPnK2E1O9RsQrQ081I3NLuXGS6zht3cw== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + catharsis@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/catharsis/-/catharsis-0.9.0.tgz#40382a168be0e6da308c277d3a2b3eb40c7d2121" @@ -121,6 +464,15 @@ catharsis@^0.9.0: dependencies: lodash "^4.17.15" +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -144,6 +496,20 @@ chokidar@3.5.3: optionalDependencies: fsevents "~2.3.2" +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -153,6 +519,13 @@ cliui@^7.0.2: strip-ansi "^6.0.0" wrap-ansi "^7.0.0" +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -160,33 +533,122 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -debug@4.3.4: +convert-source-map@^1.7.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== + +coveralls@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.1.tgz#f5d4431d8b5ae69c5079c8f8ca00d64ac77cf081" + integrity sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww== + dependencies: + js-yaml "^3.13.1" + lcov-parse "^1.0.0" + log-driver "^1.2.7" + minimist "^1.2.5" + request "^2.88.2" + +cross-spawn@^7.0.0, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== + dependencies: + assert-plus "^1.0.0" + +debug@4.3.4, debug@^4.1.0, debug@^4.1.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + decamelize@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== +default-require-extensions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.1.tgz#bfae00feeaeada68c2ae256c62540f60b80625bd" + integrity sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw== + dependencies: + strip-bom "^4.0.0" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + diff@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +electron-to-chromium@^1.4.535: + version "1.4.581" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.581.tgz#23b684c67bf56d4284e95598c05a5d266653b6d8" + integrity sha512-6uhqWBIapTJUxgPTCHH9sqdbxIMPt7oXl0VcAL1kOtlU6aECdcMncCrX5Z7sHQ/invtrC9jUQUef7+HhO8vVFw== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -197,6 +659,11 @@ entities@~2.1.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== +es6-error@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -207,11 +674,46 @@ escape-string-regexp@4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + escape-string-regexp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -219,6 +721,15 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +find-cache-dir@^3.2.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" + integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + find-up@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -227,11 +738,46 @@ find-up@5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + flat@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== +foreground-child@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" + integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^3.0.2" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +fromentries@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.3.2.tgz#e4bca6808816bf8f93b52750f1127f5a6fd86e3a" + integrity sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg== + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -242,11 +788,28 @@ fsevents@~2.3.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -get-caller-file@^2.0.5: +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== + dependencies: + assert-plus "^1.0.0" + glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -266,21 +829,88 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" -graceful-fs@^4.1.9: +glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +graceful-fs@^4.1.15, graceful-fs@^4.1.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +hasha@^5.0.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.2.tgz#a48477989b3b327aea3c04f53096d816d97522a1" + integrity sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ== + dependencies: + is-stream "^2.0.0" + type-fest "^0.8.0" + he@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -328,16 +958,101 @@ is-plain-obj@^2.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-typedarray@^1.0.0, is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + is-unicode-supported@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-hook@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" + integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== + dependencies: + append-transform "^2.0.0" + +istanbul-lib-instrument@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== + dependencies: + "@babel/core" "^7.7.5" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" + +istanbul-lib-processinfo@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz#366d454cd0dcb7eb6e0e419378e60072c8626169" + integrity sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg== + dependencies: + archy "^1.0.0" + cross-spawn "^7.0.3" + istanbul-lib-coverage "^3.2.0" + p-map "^3.0.0" + rimraf "^3.0.0" + uuid "^8.3.2" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.0.2: + version "3.1.6" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" + integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + js-yaml@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -345,6 +1060,14 @@ js-yaml@4.1.0: dependencies: argparse "^2.0.1" +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js2xmlparser@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/js2xmlparser/-/js2xmlparser-4.0.2.tgz#2a1fdf01e90585ef2ae872a01bc169c6a8d5e60a" @@ -352,6 +1075,11 @@ js2xmlparser@^4.0.2: dependencies: xmlcreate "^2.0.4" +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== + jsdoc@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/jsdoc/-/jsdoc-4.0.2.tgz#a1273beba964cf433ddf7a70c23fd02c3c60296e" @@ -373,6 +1101,41 @@ jsdoc@^4.0.0: strip-json-comments "^3.1.0" underscore "~1.13.2" +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + klaw@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/klaw/-/klaw-3.0.0.tgz#b11bec9cf2492f06756d6e809ab73a2910259146" @@ -380,6 +1143,11 @@ klaw@^3.0.0: dependencies: graceful-fs "^4.1.9" +lcov-parse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" + integrity sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ== + linkify-it@^3.0.1: version "3.0.3" resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e" @@ -387,6 +1155,13 @@ linkify-it@^3.0.1: dependencies: uc.micro "^1.0.1" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -394,11 +1169,21 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash.flattendeep@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" + integrity sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ== + lodash@^4.17.15, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +log-driver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" + integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== + log-symbols@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" @@ -407,6 +1192,34 @@ log-symbols@4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +make-dir@^3.0.0, make-dir@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + markdown-it-anchor@^8.4.1: version "8.6.7" resolved "https://registry.yarnpkg.com/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz#ee6926daf3ad1ed5e4e3968b1740eef1c6399634" @@ -433,6 +1246,18 @@ mdurl@^1.0.1: resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + minimatch@5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" @@ -440,13 +1265,18 @@ minimatch@5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^3.0.4: +minimatch@^3.0.4, minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" +minimist@^1.2.5: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" @@ -494,11 +1324,61 @@ nanoid@3.3.3: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== +node-preload@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" + integrity sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ== + dependencies: + process-on-spawn "^1.0.0" + +node-releases@^2.0.13: + version "2.0.13" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" + integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +nyc@^15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.1.0.tgz#1335dae12ddc87b6e249d5a1994ca4bdaea75f02" + integrity sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A== + dependencies: + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + caching-transform "^4.0.0" + convert-source-map "^1.7.0" + decamelize "^1.2.0" + find-cache-dir "^3.2.0" + find-up "^4.1.0" + foreground-child "^2.0.0" + get-package-type "^0.1.0" + glob "^7.1.6" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-hook "^3.0.0" + istanbul-lib-instrument "^4.0.0" + istanbul-lib-processinfo "^2.0.2" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + make-dir "^3.0.0" + node-preload "^0.2.1" + p-map "^3.0.0" + process-on-spawn "^1.0.0" + resolve-from "^5.0.0" + rimraf "^3.0.0" + signal-exit "^3.0.2" + spawn-wrap "^2.0.0" + test-exclude "^6.0.0" + yargs "^15.0.2" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -506,6 +1386,13 @@ once@^1.3.0: dependencies: wrappy "1" +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" @@ -513,6 +1400,13 @@ p-limit@^3.0.2: dependencies: yocto-queue "^0.1.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-locate@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" @@ -520,6 +1414,28 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506" + integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== + dependencies: + graceful-fs "^4.1.15" + hasha "^5.0.0" + lodash.flattendeep "^4.4.0" + release-zalgo "^1.0.0" + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -530,11 +1446,55 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + picomatch@^2.0.4, picomatch@^2.2.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pkg-dir@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +process-on-spawn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/process-on-spawn/-/process-on-spawn-1.0.0.tgz#95b05a23073d30a17acfdc92a440efd2baefdc93" + integrity sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg== + dependencies: + fromentries "^1.2.0" + +psl@^1.1.28: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +punycode@^2.1.0, punycode@^2.1.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -549,11 +1509,49 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +release-zalgo@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" + integrity sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA== + dependencies: + es6-error "^4.0.1" + +request@^2.88.2: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + requizzle@^0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/requizzle/-/requizzle-0.2.4.tgz#319eb658b28c370f0c20f968fa8ceab98c13d27c" @@ -561,11 +1559,40 @@ requizzle@^0.2.3: dependencies: lodash "^4.17.21" -safe-buffer@^5.1.0: +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +rimraf@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.3: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + serialize-javascript@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" @@ -573,6 +1600,23 @@ serialize-javascript@6.0.0: dependencies: randombytes "^2.1.0" +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + should-equal@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/should-equal/-/should-equal-2.0.0.tgz#6072cf83047360867e68e98b09d71143d04ee0c3" @@ -617,6 +1661,48 @@ should@^13.0.0: should-type-adaptors "^1.0.1" should-util "^1.0.0" +signal-exit@^3.0.2: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spawn-wrap@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e" + integrity sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg== + dependencies: + foreground-child "^2.0.0" + is-windows "^1.0.2" + make-dir "^3.0.0" + rimraf "^3.0.0" + signal-exit "^3.0.2" + which "^2.0.1" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +sshpk@^1.7.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" + integrity sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + string-width@^4.1.0, string-width@^4.2.0: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -633,6 +1719,11 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + strip-json-comments@3.1.1, strip-json-comments@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -645,6 +1736,13 @@ supports-color@8.1.1: dependencies: has-flag "^4.0.0" +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -652,6 +1750,20 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -659,6 +1771,38 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + +type-fest@^0.8.0: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" @@ -669,6 +1813,45 @@ underscore@~1.13.2: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== +update-browserslist-db@^1.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" + integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +which-module@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== + which@^1.1.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -676,11 +1859,27 @@ which@^1.1.1: dependencies: isexe "^2.0.0" +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + workerpool@6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -695,21 +1894,54 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + xmlcreate@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/xmlcreate/-/xmlcreate-2.0.4.tgz#0c5ab0f99cdd02a81065fa9cd8f8ae87624889be" integrity sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg== +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^20.2.2: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" @@ -738,6 +1970,23 @@ yargs@16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" +yargs@^15.0.2: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"