diff --git a/package.json b/package.json index a89301044..b248aa148 100644 --- a/package.json +++ b/package.json @@ -144,7 +144,7 @@ "web-audio-test-api": "^0.5.2", "webpack": "4.20.2", "webpack-dev-middleware": "^3.4.0", - "webpack-dev-server": "3.1.11", + "webpack-dev-server": "3.10.2", "worker-loader": "^2.0.0", "yn": "^1.3.0" }, diff --git a/packages/bemuse-notechart/src/index.ts b/packages/bemuse-notechart/src/index.ts index 548d9b094..f6c480b0e 100644 --- a/packages/bemuse-notechart/src/index.ts +++ b/packages/bemuse-notechart/src/index.ts @@ -204,6 +204,24 @@ export class Notechart { return this._spacing.factor(beat) } + /** + * Gets the keyMode from scratch + * @param scratch + * @returns {string} + */ + getKeyMode(scratch: string): string { + const usedColumns: { [column: string]: boolean } = {} + for (const note of this.notes) { + usedColumns[note.column] = true + } + if (scratch === 'off' && !usedColumns['1'] && !usedColumns['7']) return '5K' + if (scratch === 'left' && !usedColumns['6'] && !usedColumns['7']) + return '5K' + if (scratch === 'right' && !usedColumns['1'] && !usedColumns['2']) + return '5K' + return '7K' + } + _preTransform( bmsNotes: BMS.BMSNote[], playerOptions: Partial @@ -211,7 +229,7 @@ export class Notechart { let chain = _.chain(bmsNotes) let keys = getKeys(bmsNotes) if (playerOptions.scratch === 'off') { - chain = chain.map(note => { + chain = chain.map((note: BMS.BMSNote) => { if (note.column && note.column === 'SC') { return Object.assign({}, note, { column: null }) } else { diff --git a/packages/bemuse-tools/src/audio.js b/packages/bemuse-tools/src/audio.js index 6e175f39d..d25f08314 100644 --- a/packages/bemuse-tools/src/audio.js +++ b/packages/bemuse-tools/src/audio.js @@ -1,5 +1,4 @@ import Promise from 'bluebird' -import co from 'co' import fs from 'fs' import Throat from 'throat' import { cpus } from 'os' @@ -28,47 +27,35 @@ export class AudioConvertor { _doConvert(path, type) { return this._SoX(path, type) } - // TODO [#621]: Convert the `_SoX` method to async function (instead of using `co`) in [bemuse-tools] src/audio.js - // See issue #575 for more details. - _SoX(path, type) { - return co( - function*() { - let typeArgs = [] - try { - let fd = yield Promise.promisify(fs.open, fs)(path, 'r') - let buffer = Buffer.alloc(4) - let read = yield Promise.promisify(fs.read, fs)( - fd, - buffer, - 0, - 4, - null - ) - yield Promise.promisify(fs.close, fs)(fd) - if (read === 0) { - console.error('[WARN] Empty keysound file.') - } else if ( - buffer[0] === 0x49 && - buffer[1] === 0x44 && - buffer[2] === 0x33 - ) { - typeArgs = ['-t', 'mp3'] - } else if (buffer[0] === 0xff && buffer[1] === 0xfb) { - typeArgs = ['-t', 'mp3'] - } else if ( - buffer[0] === 0x4f && - buffer[1] === 0x67 && - buffer[2] === 0x67 && - buffer[3] === 0x53 - ) { - typeArgs = ['-t', 'ogg'] - } - } catch (e) { - console.error('[WARN] Unable to detect file type!') - } - return yield this._doSoX(path, type, typeArgs) - }.bind(this) - ) + async _SoX(path, type) { + let typeArgs = [] + try { + let fd = await Promise.promisify(fs.open)(path, 'r') + let buffer = Buffer.alloc(4) + let read = await Promise.promisify(fs.read)(fd, buffer, 0, 4, null) + await Promise.promisify(fs.close)(fd) + if (read === 0) { + console.error('[WARN] Empty keysound file.') + } else if ( + buffer[0] === 0x49 && + buffer[1] === 0x44 && + buffer[2] === 0x33 + ) { + typeArgs = ['-t', 'mp3'] + } else if (buffer[0] === 0xff && buffer[1] === 0xfb) { + typeArgs = ['-t', 'mp3'] + } else if ( + buffer[0] === 0x4f && + buffer[1] === 0x67 && + buffer[2] === 0x67 && + buffer[3] === 0x53 + ) { + typeArgs = ['-t', 'ogg'] + } + } catch (e) { + console.error('[WARN] Unable to detect file type!') + } + return this._doSoX(path, type, typeArgs) } _doSoX(path, type, inputTypeArgs) { return throat( diff --git a/src/auto-synchro/music/index.js b/src/auto-synchro/music/index.js index 4598a670b..45b7fff74 100644 --- a/src/auto-synchro/music/index.js +++ b/src/auto-synchro/music/index.js @@ -1,5 +1,4 @@ import _ from 'lodash' -import co from 'co' import context from 'bemuse/audio-context' import download from 'bemuse/utils/download' import SamplingMaster from 'bemuse/sampling-master' @@ -17,24 +16,21 @@ let ASSET_URLS = { /** * Loads the files and create a music instance. */ -export function load() { - // TODO [#626]: Convert the `load` function to async function (instead of using `co`) in src/auto-synchro/music.js - // See issue #575 for more details. - return co(function*() { - let master = new SamplingMaster(context) - let sample = name => - download(ASSET_URLS[`${name}.ogg`]) - .as('arraybuffer') - .then(buf => master.sample(buf)) - let samples = _.fromPairs( - yield Promise.all( - ['bgm', 'intro', 'kick', 'snare'].map(name => - sample(name).then(sampleObj => [name, sampleObj]) - ) +export async function load() { + let master = new SamplingMaster(context) + + let sample = name => + download(ASSET_URLS[`${name}.ogg`]) + .as('arraybuffer') + .then(buf => master.sample(buf)) + let samples = _.fromPairs( + await Promise.all( + ['bgm', 'intro', 'kick', 'snare'].map(name => + sample(name).then(sampleObj => [name, sampleObj]) ) ) - return music(master, samples) - }) + ) + return music(master, samples) } /** diff --git a/src/coming-soon/demo/index.js b/src/coming-soon/demo/index.js index 8fc76b834..bf38be09f 100644 --- a/src/coming-soon/demo/index.js +++ b/src/coming-soon/demo/index.js @@ -4,7 +4,6 @@ import $ from 'jquery' import { Compiler, Notes, Reader, SongInfo, Timing } from 'bms' import DndResources from 'bemuse/resources/dnd-resources' import SamplingMaster from 'bemuse/sampling-master' -import co from 'co' import ctx from 'bemuse/audio-context' import template from './template.jade' @@ -33,56 +32,53 @@ export function main(element) { } } -// TODO [#627]: Convert the `go` function to async function (instead of using `co`) in src/coming-soon/demo/index.js -// See issue #575 for more details. -function go(loader, element) { +async function go(loader, element) { let master = new SamplingMaster(ctx) let $log = element.find('.js-log') let $play = element.find('.js-play').hide() let $sampler = element.find('.js-sampler') - co(function*() { - log('Loading file list') - let list = yield loader.fileList - let bmsFile = list.filter(f => f.match(/\.(?:bms|bme|bml|pms)$/i))[0] - log('Loading ' + bmsFile) + log('Loading file list') + let list = await loader.fileList + let bmsFile = list.filter(f => f.match(/\.(?:bms|bme|bml|pms)$/i))[0] + log('Loading ' + bmsFile) - let arraybuffer = yield (yield loader.file(bmsFile)).read() - let buffer = Buffer.from(new Uint8Array(arraybuffer)) - let text = yield Promise.promisify(Reader.readAsync)(buffer) - let chart = Compiler.compile(text).chart - var timing = Timing.fromBMSChart(chart) - var notes = Notes.fromBMSChart(chart) - var info = SongInfo.fromBMSChart(chart) - $('
')
-      .text(JSON.stringify(info, null, 2))
-      .appendTo($sampler)
-    log('Loading samples')
-    var samples = yield loadSamples(notes, chart)
-    log('Click the button to play!')
-    yield waitForPlay()
-    void (function() {
-      master.unmute()
-      for (let note of notes.all()) {
-        setTimeout(() => {
-          let sample = samples[note.keysound]
-          if (!sample) {
-            console.log('warn: unknown sample ' + note.keysound)
-            return
-          }
-          let span = $('')
-            .text('[' + note.keysound + '] ')
-            .appendTo($sampler)
-          let instance = sample.play()
-          $sampler[0].scrollTop = $sampler[0].scrollHeight
-          instance.onstop = function() {
-            span.addClass('is-off')
-          }
-        }, timing.beatToSeconds(note.beat) * 1000)
-      }
-      return false
-    })()
-  }).done()
+  let loadedFile = await loader.file(bmsFile)
+  let arraybuffer = await loadedFile.read()
+  let buffer = Buffer.from(new Uint8Array(arraybuffer))
+  let text = await Promise.promisify(Reader.readAsync)(buffer)
+  let chart = Compiler.compile(text).chart
+  var timing = Timing.fromBMSChart(chart)
+  var notes = Notes.fromBMSChart(chart)
+  var info = SongInfo.fromBMSChart(chart)
+  $('
')
+    .text(JSON.stringify(info, null, 2))
+    .appendTo($sampler)
+  log('Loading samples')
+  var loadedSamples = await loadSamples(notes, chart)
+  log('Click the button to play!')
+  await waitForPlay()
+  void (function() {
+    master.unmute()
+    for (let note of notes.all()) {
+      setTimeout(() => {
+        let sample = loadedSamples[note.keysound]
+        if (!sample) {
+          console.log('warn: unknown sample ' + note.keysound)
+          return
+        }
+        let span = $('')
+          .text('[' + note.keysound + '] ')
+          .appendTo($sampler)
+        let instance = sample.play()
+        $sampler[0].scrollTop = $sampler[0].scrollHeight
+        instance.onstop = function() {
+          span.addClass('is-off')
+        }
+      }, timing.beatToSeconds(note.beat) * 1000)
+    }
+    return false
+  })()
 
   function waitForPlay() {
     return new Promise(function(resolve) {
@@ -98,17 +94,17 @@ function go(loader, element) {
     $log.text(t)
   }
 
-  function loadSamples(notes, chart) {
+  function loadSamples(_notes, _chart) {
     var samples = {}
     var promises = []
     let completed = 0
 
-    for (let note of notes.all()) {
+    for (let note of _notes.all()) {
       let keysound = note.keysound
       if (!(keysound in samples)) {
         samples[keysound] = null
         promises.push(
-          loadKeysound(chart.headers.get('wav' + keysound))
+          loadKeysound(_chart.headers.get('wav' + keysound))
             .then(blob => master.sample(blob))
             .then(sample => (samples[keysound] = sample))
             .catch(e => console.error('Unable to load ' + keysound + ': ' + e))
diff --git a/src/game/display/player-display.js b/src/game/display/player-display.js
index 3ba80aad9..d79741a20 100644
--- a/src/game/display/player-display.js
+++ b/src/game/display/player-display.js
@@ -5,15 +5,17 @@ import { getGauge } from './Gauge'
 
 export class PlayerDisplay {
   constructor(player, skinData) {
-    let notechart = player.notechart
     this._currentSpeed = 1
     this._player = player
-    this._noteArea = new NoteArea(notechart.notes, notechart.barLines)
+    this._noteArea = new NoteArea(
+      player.notechart.notes,
+      player.notechart.barLines
+    )
     this._stateful = {}
     this._defaultData = {
       placement: player.options.placement,
       scratch: player.options.scratch,
-      key_mode: getKeyMode(notechart, player.options.scratch),
+      key_mode: player.notechart.getKeyMode(player.options.scratch),
       lane_lift: Math.max(0, -player.options.laneCover),
       lane_press: Math.max(0, player.options.laneCover),
     }
@@ -221,16 +223,3 @@ export class PlayerDisplay {
 }
 
 export default PlayerDisplay
-
-// TODO [#629]: MOVE THIS (getKeyMode) TO bemuse-notechart
-//
-function getKeyMode(notechart, scratch) {
-  const usedColumns = {}
-  for (const note of notechart.notes) {
-    usedColumns[note.column] = true
-  }
-  if (scratch === 'off' && !usedColumns['1'] && !usedColumns['7']) return '5K'
-  if (scratch === 'left' && !usedColumns['6'] && !usedColumns['7']) return '5K'
-  if (scratch === 'right' && !usedColumns['1'] && !usedColumns['2']) return '5K'
-  return '7K'
-}
diff --git a/src/game/index.js b/src/game/index.js
index 7d0492a21..24c997006 100644
--- a/src/game/index.js
+++ b/src/game/index.js
@@ -3,7 +3,6 @@ import React from 'react'
 import SCENE_MANAGER from 'bemuse/scene-manager'
 import URLResource from 'bemuse/resources/url'
 import audioContext from 'bemuse/audio-context'
-import co from 'co'
 import query from 'bemuse/utils/query'
 import { resolveUrl } from 'url'
 import { unmuteAudio } from 'bemuse/sampling-master'
@@ -13,7 +12,7 @@ import GameScene from './game-scene'
 import GameShellScene from './ui/GameShellScene.jsx'
 import LoadingScene from './ui/LoadingScene.jsx'
 
-export function main() {
+export async function main() {
   // iOS
   window.addEventListener('touchstart', function unmute() {
     unmuteAudio(audioContext)
@@ -32,9 +31,7 @@ export function main() {
     })
   }
 
-  // TODO [#630]: Convert the `getSong` function to async function (instead of using `co.wrap`) in src/game/index.js
-  // See issue #575 for more details.
-  let getSong = co.wrap(function*() {
+  let getSong = async function() {
     let kbm = (query.keyboard || '').split(',').map(x => +x)
     let options = {
       url: query.bms || '/music/[snack]dddd/dddd_sph.bme',
@@ -63,7 +60,7 @@ export function main() {
         },
       ],
     }
-    options = yield displayShell(options)
+    options = await displayShell(options)
     let url = options.url
     let assetsUrl = resolveUrl(url, 'assets/')
     let metadata = {
@@ -73,27 +70,23 @@ export function main() {
       genre: '',
       subartists: [],
     }
-    let loadSpec = {
+    return {
       bms: options.resource || new URLResource(url),
       assets: options.resources || new BemusePackageResources(assetsUrl),
       metadata: metadata,
       options: Object.assign({}, options.game, { players: options.players }),
     }
-    return loadSpec
-  })
+  }
 
-  // TODO [#631]: Convert the `co` invocation to async function IIFE in src/game/index.js
-  co(function*() {
-    let loadSpec = yield getSong()
-    let { tasks, promise } = GameLoader.load(loadSpec)
-    yield SCENE_MANAGER.display(
-      React.createElement(LoadingScene, {
-        tasks: tasks,
-        song: loadSpec.metadata,
-      })
-    )
-    let controller = yield promise
-    yield SCENE_MANAGER.display(new GameScene(controller.display))
-    controller.start()
-  }).done()
+  let loadSpec = await getSong()
+  let { tasks, promise } = GameLoader.load(loadSpec)
+  await SCENE_MANAGER.display(
+    React.createElement(LoadingScene, {
+      tasks: tasks,
+      song: loadSpec.metadata,
+    })
+  )
+  let controller = await promise
+  await SCENE_MANAGER.display(new GameScene(controller.display))
+  controller.start()
 }
diff --git a/src/scene-manager/index.js b/src/scene-manager/index.js
index f1e055ff1..619353dbc 100644
--- a/src/scene-manager/index.js
+++ b/src/scene-manager/index.js
@@ -1,4 +1,3 @@
-import co from 'co'
 import React from 'react'
 import ReactDOM from 'react-dom'
 import MAIN from 'bemuse/utils/main-element'
@@ -60,41 +59,35 @@ export class SceneManager {
     })
   }
 
-  // TODO [#635]: Convert the `_transitionTo` method to async function (instead of using `co`) in src/scene-manager/index.js
-  // See issue #575 for more details.
-  _transitionTo(getNextScene) {
-    return co(
-      function*() {
-        if (this._transitioning) throw new Error('Scene is transitioning!')
-        try {
-          this._transitioning = true
+  async _transitionTo(getNextScene) {
+    if (this._transitioning) throw new Error('Scene is transitioning!')
+    try {
+      this._transitioning = true
 
-          // detach the previous scene
-          if (this.currentSceneInstance) {
-            yield Promise.resolve(this.currentSceneInstance.teardown())
-            detach(this.currentElement)
-          }
+      // detach the previous scene
+      if (this.currentSceneInstance) {
+        await Promise.resolve(this.currentSceneInstance.teardown())
+        detach(this.currentElement)
+      }
 
-          // obtain the next scene
-          let scene = getNextScene()
+      // obtain the next scene
+      let scene = getNextScene()
 
-          // coerce react elements
-          if (typeof scene !== 'function') {
-            scene = new ReactScene(scene, this.ReactSceneContainer)
-          }
+      // coerce react elements
+      if (typeof scene !== 'function') {
+        scene = new ReactScene(scene, this.ReactSceneContainer)
+      }
 
-          // set up the next scene
-          var element = document.createElement('div')
-          element.className = 'scene-manager--scene'
-          MAIN.appendChild(element)
-          this.currentElement = element
-          this.currentScene = scene
-          this.currentSceneInstance = scene(element)
-        } finally {
-          this._transitioning = false
-        }
-      }.bind(this)
-    )
+      // set up the next scene
+      var element = document.createElement('div')
+      element.className = 'scene-manager--scene'
+      MAIN.appendChild(element)
+      this.currentElement = element
+      this.currentScene = scene
+      this.currentSceneInstance = scene(element)
+    } finally {
+      this._transitioning = false
+    }
   }
 }
 
diff --git a/src/scintillator/index.spec.js b/src/scintillator/index.spec.js
index 80a0dc071..50a788d02 100644
--- a/src/scintillator/index.spec.js
+++ b/src/scintillator/index.spec.js
@@ -1,21 +1,14 @@
-import co from 'co'
-
 import * as Scintillator from './'
 
 let fixture = file => `/src/scintillator/test-fixtures/${file}`
 
 describe('Scintillator', function() {
   describe('#load', function() {
-    it(
-      'should load skin and return skin node',
-      // TODO [#636]: Convert all `co.wrap()` calls in src/scintillator/index.spec.js to async functions
-      // See issue #575 for more details.
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('bare.xml'))
-        expect(skin.width).to.equal(123)
-        expect(skin.height).to.equal(456)
-      })
-    )
+    it('should load skin and return skin node', async function() {
+      let skin = await Scintillator.load(fixture('bare.xml'))
+      expect(skin.width).to.equal(123)
+      expect(skin.height).to.equal(456)
+    })
     it('should reject if invalid', function() {
       return expect(Scintillator.load(fixture('invalid_tag.xml'))).to.be
         .rejected
@@ -23,29 +16,24 @@ describe('Scintillator', function() {
   })
 
   describe('Context', function() {
-    it(
-      'should instantiate and able to destroy',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('bare.xml'))
-        let context = new Scintillator.Context(skin)
-        context.render({})
-        context.destroy()
-      })
-    )
+    it('should instantiate and able to destroy', async function() {
+      let skin = await Scintillator.load(fixture('bare.xml'))
+      let context = new Scintillator.Context(skin)
+      context.render({})
+      context.destroy()
+    })
     describe('#input', function() {
       let skin
       let context
-      beforeEach(
-        co.wrap(function*() {
-          skin = yield Scintillator.load(fixture('bare.xml'))
-          context = new Scintillator.Context(skin)
-          context.render({})
-          context.view.style.position = 'fixed'
-          context.view.style.top = '0'
-          context.view.style.left = '0'
-          document.body.appendChild(context.view)
-        })
-      )
+      beforeEach(async function() {
+        skin = await Scintillator.load(fixture('bare.xml'))
+        context = new Scintillator.Context(skin)
+        context.render({})
+        context.view.style.position = 'fixed'
+        context.view.style.top = '0'
+        context.view.style.left = '0'
+        document.body.appendChild(context.view)
+      })
       afterEach(function() {
         context.destroy()
         document.body.removeChild(context.view)
@@ -88,81 +76,66 @@ describe('Scintillator', function() {
       })
     })
     describe('#refs', function() {
-      it(
-        'should be a set of refs to the display object',
-        co.wrap(function*() {
-          let skin = yield Scintillator.load(fixture('refs.xml'))
-          let context = new Scintillator.Context(skin)
-          context.render({})
-          expect(Array.from(context.refs['a'])[0]).to.equal(
-            context.stage.children[0]
-          )
-          context.destroy()
-        })
-      )
-    })
-  })
-
-  describe('Expressions', function() {
-    it(
-      'should be parsed and processed',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('expr_basic.xml'))
+      it('should be a set of refs to the display object', async function() {
+        let skin = await Scintillator.load(fixture('refs.xml'))
         let context = new Scintillator.Context(skin)
         context.render({})
-        let stage = context.stage
-        expect(stage.children[0].x).to.equal(6)
-        expect(stage.children[0].y).to.equal(7)
-        context.destroy()
-      })
-    )
-    it(
-      'should support variables',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('expr_variables.xml'))
-        let context = new Scintillator.Context(skin)
-        let stage = context.stage
-        context.render({ a: 4, b: 3 })
-        expect(stage.children[0].x).to.equal(7)
-        expect(stage.children[0].y).to.equal(12)
-        context.render({ a: 10, b: 20 })
-        expect(stage.children[0].x).to.equal(30)
-        expect(stage.children[0].y).to.equal(200)
+        expect(Array.from(context.refs['a'])[0]).to.equal(
+          context.stage.children[0]
+        )
         context.destroy()
       })
-    )
+    })
+  })
+
+  describe('Expressions', function() {
+    it('should be parsed and processed', async function() {
+      let skin = await Scintillator.load(fixture('expr_basic.xml'))
+      let context = new Scintillator.Context(skin)
+      context.render({})
+      let stage = context.stage
+      expect(stage.children[0].x).to.equal(6)
+      expect(stage.children[0].y).to.equal(7)
+      context.destroy()
+    })
+    it('should support variables', async function() {
+      let skin = await Scintillator.load(fixture('expr_variables.xml'))
+      let context = new Scintillator.Context(skin)
+      let stage = context.stage
+      context.render({ a: 4, b: 3 })
+      expect(stage.children[0].x).to.equal(7)
+      expect(stage.children[0].y).to.equal(12)
+      context.render({ a: 10, b: 20 })
+      expect(stage.children[0].x).to.equal(30)
+      expect(stage.children[0].y).to.equal(200)
+      context.destroy()
+    })
   })
 
   describe('SpriteNode', function() {
-    it(
-      'should allow setting sprite frame',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('sprite_attrs.xml'))
-        let context = new Scintillator.Context(skin)
-        let stage = context.stage
-        context.render({})
-        let frame = stage.children[0].texture.frame
-        expect(frame.width).to.equal(10)
-        expect(frame.height).to.equal(11)
-        expect(frame.x).to.equal(12)
-        expect(frame.y).to.equal(13)
-        context.destroy()
-      })
-    )
-    it(
-      'should allow setting visibility, width, height',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('sprite_attrs.xml'))
-        let context = new Scintillator.Context(skin)
-        let stage = context.stage
-        context.render({})
-        let sprite = stage.children[0]
-        expect(sprite.width).to.equal(3)
-        expect(sprite.height).to.equal(1)
-        expect(sprite.visible).to.equal(false)
-        context.destroy()
-      })
-    )
+    it('should allow setting sprite frame', async function() {
+      let skin = await Scintillator.load(fixture('sprite_attrs.xml'))
+      let context = new Scintillator.Context(skin)
+      let stage = context.stage
+      context.render({})
+      let frame = stage.children[0].texture.frame
+      expect(frame.width).to.equal(10)
+      expect(frame.height).to.equal(11)
+      expect(frame.x).to.equal(12)
+      expect(frame.y).to.equal(13)
+      context.destroy()
+    })
+    it('should allow setting visibility, width, height', async function() {
+      let skin = await Scintillator.load(fixture('sprite_attrs.xml'))
+      let context = new Scintillator.Context(skin)
+      let stage = context.stage
+      context.render({})
+      let sprite = stage.children[0]
+      expect(sprite.width).to.equal(3)
+      expect(sprite.height).to.equal(1)
+      expect(sprite.visible).to.equal(false)
+      context.destroy()
+    })
     it('should reject if blend mode is invalid', function() {
       return expect(Scintillator.load(fixture('sprite_invalid_blend.xml'))).to
         .be.rejected
@@ -170,197 +143,161 @@ describe('Scintillator', function() {
   })
 
   describe('TextNode', function() {
-    it(
-      'should display text',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('text.xml'))
-        let context = new Scintillator.Context(skin)
-        let stage = context.stage
-        context.render({})
-        let text = stage.children[0].children[0]
-        expect(text.text).to.equal('Hello world')
-        context.destroy()
-      })
-    )
-    it(
-      'should center text',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('text_center.xml'))
-        let context = new Scintillator.Context(skin)
-        let stage = context.stage
-        context.render({})
-        let text = stage.children[0].children[0]
-        expect(text.x).to.be.lessThan(0)
-        context.destroy()
-      })
-    )
-    it(
-      'should support data interpolation',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('text_interpolation.xml'))
-        let context = new Scintillator.Context(skin)
-        let stage = context.stage
-        context.render({ lol: 'wow' })
-        let text = stage.children[0].children[0]
-        expect(text.text).to.equal('Hello world wow')
-        context.destroy()
-      })
-    )
+    it('should display text', async function() {
+      let skin = await Scintillator.load(fixture('text.xml'))
+      let context = new Scintillator.Context(skin)
+      let stage = context.stage
+      context.render({})
+      let text = stage.children[0].children[0]
+      expect(text.text).to.equal('Hello world')
+      context.destroy()
+    })
+    it('should center text', async function() {
+      let skin = await Scintillator.load(fixture('text_center.xml'))
+      let context = new Scintillator.Context(skin)
+      let stage = context.stage
+      context.render({})
+      let text = stage.children[0].children[0]
+      expect(text.x).to.be.lessThan(0)
+      context.destroy()
+    })
+    it('should support data interpolation', async function() {
+      let skin = await Scintillator.load(fixture('text_interpolation.xml'))
+      let context = new Scintillator.Context(skin)
+      let stage = context.stage
+      context.render({ lol: 'wow' })
+      let text = stage.children[0].children[0]
+      expect(text.text).to.equal('Hello world wow')
+      context.destroy()
+    })
   })
 
   describe('IfNode', function() {
-    it(
-      'should display child when correct value',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('expr_if.xml'))
-        let context = new Scintillator.Context(skin)
-        let stage = context.stage
-        context.render({ a: 'b' })
-        expect(stage.children[0].children).to.have.length(1)
-        context.destroy()
-      })
-    )
-    it(
-      'should not display child when correct value',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('expr_if.xml'))
-        let context = new Scintillator.Context(skin)
-        let stage = context.stage
-        context.render({ a: 'x' })
-        expect(stage.children[0].children).to.have.length(0)
-        context.destroy()
-      })
-    )
+    let skin
+    let context
+    let stage
+    beforeEach(async function() {
+      skin = await Scintillator.load(fixture('expr_if.xml'))
+      context = new Scintillator.Context(skin)
+      stage = context.stage
+    })
+    afterEach(function() {
+      context.destroy()
+    })
+    it('should display child when correct value', function() {
+      context.render({ a: 'b' })
+      expect(stage.children[0].children).to.have.length(1)
+    })
+    it('should not display child when correct value', function() {
+      context.render({ a: 'x' })
+      expect(stage.children[0].children).to.have.length(0)
+    })
   })
 
   describe('ObjectNode', function() {
-    it(
-      'should display children',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('expr_object.xml'))
-        let context = new Scintillator.Context(skin)
-        let stage = context.stage
-        context.render({ notes: [] })
-        expect(stage.children[0].children).to.have.length(0)
-        context.render({ notes: [{ key: 'a', y: 20 }] })
-        expect(stage.children[0].children).to.have.length(1)
-        context.render({ notes: [{ key: 'a', y: 20 }, { key: 'b', y: 10 }] })
-        expect(stage.children[0].children).to.have.length(2)
-        context.render({ notes: [{ key: 'b', y: 10 }] })
-        expect(stage.children[0].children).to.have.length(1)
-        context.destroy()
-      })
-    )
-    it(
-      'should update same array with content changed',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('expr_object.xml'))
-        let context = new Scintillator.Context(skin)
-        let stage = context.stage
-        let notes = []
-        context.render({ notes })
-        expect(stage.children[0].children).to.have.length(0)
-        notes.push({ key: 'a', y: 20 })
-        context.render({ notes })
-        expect(stage.children[0].children).to.have.length(1)
-        context.destroy()
-      })
-    )
-    it(
-      'should let children get value from item',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('expr_object_var.xml'))
-        let context = new Scintillator.Context(skin)
-        let stage = context.stage
-        context.render({ notes: [] })
-        context.render({ notes: [{ key: 'a', y: 20 }] })
-        expect(stage.children[0].children[0].y).to.equal(20)
-        context.render({ notes: [{ key: 'a', y: 20 }, { key: 'b', y: 10 }] })
-        expect(stage.children[0].children[0].y).to.equal(20)
-        context.render({ notes: [{ key: 'b', y: 10 }] })
-        expect(stage.children[0].children[0].y).to.equal(10)
-        context.destroy()
-      })
-    )
+    it('should display children', async function() {
+      let skin = await Scintillator.load(fixture('expr_object.xml'))
+      let context = new Scintillator.Context(skin)
+      let stage = context.stage
+      context.render({ notes: [] })
+      expect(stage.children[0].children).to.have.length(0)
+      context.render({ notes: [{ key: 'a', y: 20 }] })
+      expect(stage.children[0].children).to.have.length(1)
+      context.render({ notes: [{ key: 'a', y: 20 }, { key: 'b', y: 10 }] })
+      expect(stage.children[0].children).to.have.length(2)
+      context.render({ notes: [{ key: 'b', y: 10 }] })
+      expect(stage.children[0].children).to.have.length(1)
+      context.destroy()
+    })
+    it('should update same array with content changed', async function() {
+      let skin = await Scintillator.load(fixture('expr_object.xml'))
+      let context = new Scintillator.Context(skin)
+      let stage = context.stage
+      let notes = []
+      context.render({ notes })
+      expect(stage.children[0].children).to.have.length(0)
+      notes.push({ key: 'a', y: 20 })
+      context.render({ notes })
+      expect(stage.children[0].children).to.have.length(1)
+      context.destroy()
+    })
+    it('should let children get value from item', async function() {
+      let skin = await Scintillator.load(fixture('expr_object_var.xml'))
+      let context = new Scintillator.Context(skin)
+      let stage = context.stage
+      context.render({ notes: [] })
+      context.render({ notes: [{ key: 'a', y: 20 }] })
+      expect(stage.children[0].children[0].y).to.equal(20)
+      context.render({ notes: [{ key: 'a', y: 20 }, { key: 'b', y: 10 }] })
+      expect(stage.children[0].children[0].y).to.equal(20)
+      context.render({ notes: [{ key: 'b', y: 10 }] })
+      expect(stage.children[0].children[0].y).to.equal(10)
+      context.destroy()
+    })
   })
 
   describe('GroupNode', function() {
-    it(
-      'should allow masking',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('group_mask.xml'))
-        let context = new Scintillator.Context(skin)
-        let stage = context.stage
-        let mask = stage.children[0].mask
-        expect(mask).not.to.equal(null)
-        context.destroy()
-      })
-    )
+    it('should allow masking', async function() {
+      let skin = await Scintillator.load(fixture('group_mask.xml'))
+      let context = new Scintillator.Context(skin)
+      let stage = context.stage
+      let mask = stage.children[0].mask
+      expect(mask).not.to.equal(null)
+      context.destroy()
+    })
   })
 
   describe('AnimationNode', function() {
-    it(
-      'should allow animations',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('animation.xml'))
-        let context = new Scintillator.Context(skin)
-        let group = context.stage.children[0]
-        context.render({ t: 0 })
-        expect(group.x).to.equal(10)
-        expect(group.y).to.equal(0)
-        context.render({ t: 0.5 })
-        expect(group.x).to.equal(15)
-        expect(group.y).to.equal(1)
-        context.render({ t: 1 })
-        expect(group.x).to.equal(20)
-        expect(group.y).to.equal(2)
-        context.destroy()
-      })
-    )
-    it(
-      'should allow animations on different events',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('animation.xml'))
-        let context = new Scintillator.Context(skin)
-        let group = context.stage.children[0]
-        context.render({ t: 0.5, exitEvent: 0.5 })
-        expect(group.x).to.equal(50)
-        expect(group.y).to.equal(0)
-        context.render({ t: 1, exitEvent: 0.5 })
-        expect(group.x).to.equal(60)
-        expect(group.y).to.equal(50)
-        context.render({ t: 1.5, exitEvent: 0.5 })
-        expect(group.x).to.equal(70)
-        expect(group.y).to.equal(100)
-        context.destroy()
-      })
-    )
-    it(
-      'should allow animations on different value',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('animation_timekey.xml'))
-        let context = new Scintillator.Context(skin)
-        let group = context.stage.children[0]
-        context.render({ t: 0, x: 0.5 })
-        expect(group.x).to.equal(15)
-      })
-    )
+    it('should allow animations', async function() {
+      let skin = await Scintillator.load(fixture('animation.xml'))
+      let context = new Scintillator.Context(skin)
+      let group = context.stage.children[0]
+      context.render({ t: 0 })
+      expect(group.x).to.equal(10)
+      expect(group.y).to.equal(0)
+      context.render({ t: 0.5 })
+      expect(group.x).to.equal(15)
+      expect(group.y).to.equal(1)
+      context.render({ t: 1 })
+      expect(group.x).to.equal(20)
+      expect(group.y).to.equal(2)
+      context.destroy()
+    })
+    it('should allow animations on different events', async function() {
+      let skin = await Scintillator.load(fixture('animation.xml'))
+      let context = new Scintillator.Context(skin)
+      let group = context.stage.children[0]
+      context.render({ t: 0.5, exitEvent: 0.5 })
+      expect(group.x).to.equal(50)
+      expect(group.y).to.equal(0)
+      context.render({ t: 1, exitEvent: 0.5 })
+      expect(group.x).to.equal(60)
+      expect(group.y).to.equal(50)
+      context.render({ t: 1.5, exitEvent: 0.5 })
+      expect(group.x).to.equal(70)
+      expect(group.y).to.equal(100)
+      context.destroy()
+    })
+    it('should allow animations on different value', async function() {
+      let skin = await Scintillator.load(fixture('animation_timekey.xml'))
+      let context = new Scintillator.Context(skin)
+      let group = context.stage.children[0]
+      context.render({ t: 0, x: 0.5 })
+      expect(group.x).to.equal(15)
+    })
   })
 
   describe('defs', function() {
-    it(
-      'should allow reuse of skin nodes',
-      co.wrap(function*() {
-        let skin = yield Scintillator.load(fixture('defs.xml'))
-        let context = new Scintillator.Context(skin)
-        context.render({})
-        let stage = context.stage
-        expect(stage.children[0].x).to.equal(6)
-        expect(stage.children[0].y).to.equal(7)
-        expect(stage.children[1].x).to.equal(6)
-        expect(stage.children[1].y).to.equal(7)
-        context.destroy()
-      })
-    )
+    it('should allow reuse of skin nodes', async function() {
+      let skin = await Scintillator.load(fixture('defs.xml'))
+      let context = new Scintillator.Context(skin)
+      context.render({})
+      let stage = context.stage
+      expect(stage.children[0].x).to.equal(6)
+      expect(stage.children[0].y).to.equal(7)
+      expect(stage.children[1].x).to.equal(6)
+      expect(stage.children[1].y).to.equal(7)
+      context.destroy()
+    })
   })
 })
diff --git a/src/scintillator/loader.js b/src/scintillator/loader.js
index 4112b4f62..6e17ed85e 100644
--- a/src/scintillator/loader.js
+++ b/src/scintillator/loader.js
@@ -1,6 +1,5 @@
 import * as PIXI from 'pixi.js'
 import $ from 'jquery'
-import co from 'co'
 import debug from 'debug'
 import url from 'url'
 import { PERCENTAGE_FORMATTER } from 'bemuse/progress/formatters'
@@ -10,36 +9,30 @@ import Resources from './resources'
 
 const log = debug('scintillator:loader')
 
-// TODO [#637]: Convert the `load` function to async function (instead of using `co`) in src/scintillator/loader.js
-// See issue #575 for more details.
-export function load(xmlPath, progress) {
-  return co(function*() {
-    log('load XML from %s', xmlPath)
-    let $xml = yield loadXml(xmlPath)
+export async function load(xmlPath, progress) {
+  log('load XML from %s', xmlPath)
+  let $xml = await loadXml(xmlPath)
 
-    // scan all images
-    let resources = new Resources()
-    let paths = new Set()
-    for (let element of Array.from($xml.find('[image]'))) {
-      paths.add($(element).attr('image'))
-    }
-    for (let element of Array.from($xml.find('[font-src]'))) {
-      paths.add($(element).attr('font-src'))
-    }
-    for (let path of paths) {
-      let assetUrl = url.resolve(xmlPath, path)
-      resources.add(path, assetUrl)
-    }
+  // scan all images
+  let resources = new Resources()
+  let paths = new Set()
+  for (let element of Array.from($xml.find('[image]'))) {
+    paths.add($(element).attr('image'))
+  }
+  for (let element of Array.from($xml.find('[font-src]'))) {
+    paths.add($(element).attr('font-src'))
+  }
+  for (let path of paths) {
+    let assetUrl = url.resolve(xmlPath, path)
+    resources.add(path, assetUrl)
+  }
 
-    // load all images + progress reporting
-    yield loadResources(resources, progress)
+  // load all images + progress reporting
+  await loadResources(resources, progress)
 
-    // compile the skin
-    log('compiling')
-    let skin = new Compiler({ resources }).compile($xml)
-
-    return skin
-  })
+  // compile the skin
+  log('compiling')
+  return new Compiler({ resources }).compile($xml)
 }
 
 function loadXml(xmlUrl) {
diff --git a/tasks/pre-deploy.js b/tasks/pre-deploy.js
index 55ff8df0e..5b5b14db8 100644
--- a/tasks/pre-deploy.js
+++ b/tasks/pre-deploy.js
@@ -1,22 +1,16 @@
 import gulp from 'gulp'
 import fs from 'fs'
 import path from '../config/path'
-import co from 'co'
 import Promise from 'bluebird'
 
 const readFile = Promise.promisify(fs.readFile, fs)
 
-gulp.task(
-  'pre-deploy',
-  // TODO [#638]: Convert the `co.wrap()` call in tasks/pre-deploy.js to async function
-  // See issue #575 for more details.
-  co.wrap(function*() {
-    let data = yield readFile(path('dist', 'index.html'), 'utf-8')
-    check('New Relic inlined', () => /NREUM/.test(data))
-    check('Boot script inlined', () => /webpackJsonp/.test(data))
-    check('Google Analytics inlined', () => /GoogleAnalyticsObject/.test(data))
-  })
-)
+gulp.task('pre-deploy', async function() {
+  const data = await readFile(path('dist', 'index.html'), 'utf-8')
+  check('New Relic inlined', () => /NREUM/.test(data))
+  check('Boot script inlined', () => /webpackJsonp/.test(data))
+  check('Google Analytics inlined', () => /GoogleAnalyticsObject/.test(data))
+})
 
 function check(title, condition) {
   if (condition()) {
diff --git a/yarn.lock b/yarn.lock
index fdb2edc5d..a7d6984ae 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2031,6 +2031,14 @@ accepts@~1.3.4, accepts@~1.3.5:
     mime-types "~2.1.18"
     negotiator "0.6.1"
 
+accepts@~1.3.7:
+  version "1.3.7"
+  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
+  integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
+  dependencies:
+    mime-types "~2.1.24"
+    negotiator "0.6.2"
+
 acorn-dynamic-import@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz#901ceee4c7faaef7e07ad2a47e890675da50a278"
@@ -2566,6 +2574,11 @@ async-each@^1.0.0:
   resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
   integrity sha1-GdOGodntxufByF04iu28xW0zYC0=
 
+async-each@^1.0.1:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf"
+  integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==
+
 async-foreach@^0.1.3:
   version "0.1.3"
   resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542"
@@ -2588,6 +2601,13 @@ async@^2.0.0, async@^2.5.0:
   dependencies:
     lodash "^4.17.10"
 
+async@^2.6.2:
+  version "2.6.3"
+  resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
+  integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
+  dependencies:
+    lodash "^4.17.14"
+
 async@~0.2.6:
   version "0.2.10"
   resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
@@ -2963,6 +2983,13 @@ binary-extensions@^1.0.0:
   resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14"
   integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==
 
+bindings@^1.5.0:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
+  integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
+  dependencies:
+    file-uri-to-path "1.0.0"
+
 bit-twiddle@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/bit-twiddle/-/bit-twiddle-1.0.2.tgz#0c6c1fabe2b23d17173d9a61b7b7093eb9e1769e"
@@ -3019,6 +3046,22 @@ body-parser@1.18.3, body-parser@^1.16.1, body-parser@^1.18.3:
     raw-body "2.3.3"
     type-is "~1.6.16"
 
+body-parser@1.19.0:
+  version "1.19.0"
+  resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
+  integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
+  dependencies:
+    bytes "3.1.0"
+    content-type "~1.0.4"
+    debug "2.6.9"
+    depd "~1.1.2"
+    http-errors "1.7.2"
+    iconv-lite "0.4.24"
+    on-finished "~2.3.0"
+    qs "6.7.0"
+    raw-body "2.4.0"
+    type-is "~1.6.17"
+
 body@^5.1.0:
   version "5.1.0"
   resolved "https://registry.yarnpkg.com/body/-/body-5.1.0.tgz#e4ba0ce410a46936323367609ecb4e6553125069"
@@ -3077,7 +3120,7 @@ braces@^1.8.2:
     preserve "^0.2.0"
     repeat-element "^1.1.2"
 
-braces@^2.3.0, braces@^2.3.1:
+braces@^2.3.0, braces@^2.3.1, braces@^2.3.2:
   version "2.3.2"
   resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
   integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==
@@ -3402,6 +3445,11 @@ bytes@3.0.0, bytes@^3.0.0:
   resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
   integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=
 
+bytes@3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
+  integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
+
 cacache@^10.0.4:
   version "10.0.4"
   resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460"
@@ -3697,7 +3745,7 @@ cheerio@0.22.0:
     lodash.reject "^4.4.0"
     lodash.some "^4.4.0"
 
-chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3:
+chokidar@^2.0.2, chokidar@^2.0.3:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26"
   integrity sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==
@@ -3717,6 +3765,25 @@ chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3:
   optionalDependencies:
     fsevents "^1.2.2"
 
+chokidar@^2.1.8:
+  version "2.1.8"
+  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
+  integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==
+  dependencies:
+    anymatch "^2.0.0"
+    async-each "^1.0.1"
+    braces "^2.3.2"
+    glob-parent "^3.1.0"
+    inherits "^2.0.3"
+    is-binary-path "^1.0.0"
+    is-glob "^4.0.0"
+    normalize-path "^3.0.0"
+    path-is-absolute "^1.0.0"
+    readdirp "^2.2.1"
+    upath "^1.1.1"
+  optionalDependencies:
+    fsevents "^1.2.7"
+
 chownr@^1.0.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
@@ -4174,23 +4241,23 @@ component-inherit@0.0.3:
   resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
   integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=
 
-compressible@~2.0.14:
-  version "2.0.15"
-  resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.15.tgz#857a9ab0a7e5a07d8d837ed43fe2defff64fe212"
-  integrity sha512-4aE67DL33dSW9gw4CI2H/yTxqHLNcxp0yS6jB+4h+wr3e43+1z7vm0HU9qXOH8j+qjKuL8+UtkOxYQSMq60Ylw==
+compressible@~2.0.16:
+  version "2.0.18"
+  resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
+  integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==
   dependencies:
-    mime-db ">= 1.36.0 < 2"
+    mime-db ">= 1.43.0 < 2"
 
-compression@^1.5.2:
-  version "1.7.3"
-  resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.3.tgz#27e0e176aaf260f7f2c2813c3e440adb9f1993db"
-  integrity sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==
+compression@^1.7.4:
+  version "1.7.4"
+  resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f"
+  integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==
   dependencies:
     accepts "~1.3.5"
     bytes "3.0.0"
-    compressible "~2.0.14"
+    compressible "~2.0.16"
     debug "2.6.9"
-    on-headers "~1.0.1"
+    on-headers "~1.0.2"
     safe-buffer "5.1.2"
     vary "~1.1.2"
 
@@ -4236,10 +4303,10 @@ config-chain@^1.1.11:
     ini "^1.3.4"
     proto-list "~1.2.1"
 
-connect-history-api-fallback@^1.3.0:
-  version "1.5.0"
-  resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz#b06873934bc5e344fef611a196a6faae0aee015a"
-  integrity sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=
+connect-history-api-fallback@^1.6.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc"
+  integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==
 
 connect@^3.6.0, connect@^3.6.6:
   version "3.6.6"
@@ -4295,6 +4362,13 @@ content-disposition@0.5.2:
   resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
   integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ=
 
+content-disposition@0.5.3:
+  version "0.5.3"
+  resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
+  integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==
+  dependencies:
+    safe-buffer "5.1.2"
+
 content-type@~1.0.4:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
@@ -4415,6 +4489,11 @@ cookie@0.3.1:
   resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
   integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=
 
+cookie@0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
+  integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
+
 cookiejar@^2.1.0:
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c"
@@ -4978,7 +5057,7 @@ debug@3.1.0, debug@=3.1.0, debug@~3.1.0:
   dependencies:
     ms "2.0.0"
 
-debug@^3.1.0, debug@^3.2.5:
+debug@^3.1.0, debug@^3.1.1, debug@^3.2.5:
   version "3.2.6"
   resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
   integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
@@ -4992,6 +5071,13 @@ debug@^4.0.1, debug@^4.1.0:
   dependencies:
     ms "^2.1.1"
 
+debug@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
+  integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
+  dependencies:
+    ms "^2.1.1"
+
 debuglog@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
@@ -5010,13 +5096,6 @@ decamelize@^1.0.0, decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2, deca
   resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
   integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
 
-decamelize@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-2.0.0.tgz#656d7bbc8094c4c788ea53c5840908c9c7d063c7"
-  integrity sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==
-  dependencies:
-    xregexp "4.0.0"
-
 decode-uri-component@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
@@ -5134,12 +5213,12 @@ deepmerge@^2.1.1:
   resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
   integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
 
-default-gateway@^2.6.0:
-  version "2.7.2"
-  resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-2.7.2.tgz#b7ef339e5e024b045467af403d50348db4642d0f"
-  integrity sha512-lAc4i9QJR0YHSDFdzeBQKfZ1SRDG3hsJNEkrpcZa8QhBfidLAilT60BDEIVUUGqosFp425KOgB3uYqcnQrWafQ==
+default-gateway@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b"
+  integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==
   dependencies:
-    execa "^0.10.0"
+    execa "^1.0.0"
     ip-regex "^2.1.0"
 
 default-require-extensions@^1.0.0:
@@ -5220,6 +5299,19 @@ del@^3.0.0:
     pify "^3.0.0"
     rimraf "^2.2.8"
 
+del@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4"
+  integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==
+  dependencies:
+    "@types/glob" "^7.1.1"
+    globby "^6.1.0"
+    is-path-cwd "^2.0.0"
+    is-path-in-cwd "^2.0.0"
+    p-map "^2.0.0"
+    pify "^4.0.1"
+    rimraf "^2.6.3"
+
 delayed-stream@0.0.5:
   version "0.0.5"
   resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-0.0.5.tgz#d4b1f43a93e8296dfe02694f4680bc37a313c73f"
@@ -6220,6 +6312,11 @@ eventemitter3@^3.1.0:
   resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
   integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==
 
+eventemitter3@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb"
+  integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==
+
 events@^1.0.0:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
@@ -6393,7 +6490,7 @@ exports-loader@^0.7.0:
     loader-utils "^1.1.0"
     source-map "0.5.0"
 
-express@^4.15.3, express@^4.16.2, express@^4.16.4:
+express@^4.15.3, express@^4.16.4:
   version "4.16.4"
   resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e"
   integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==
@@ -6429,6 +6526,42 @@ express@^4.15.3, express@^4.16.2, express@^4.16.4:
     utils-merge "1.0.1"
     vary "~1.1.2"
 
+express@^4.17.1:
+  version "4.17.1"
+  resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
+  integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
+  dependencies:
+    accepts "~1.3.7"
+    array-flatten "1.1.1"
+    body-parser "1.19.0"
+    content-disposition "0.5.3"
+    content-type "~1.0.4"
+    cookie "0.4.0"
+    cookie-signature "1.0.6"
+    debug "2.6.9"
+    depd "~1.1.2"
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    etag "~1.8.1"
+    finalhandler "~1.1.2"
+    fresh "0.5.2"
+    merge-descriptors "1.0.1"
+    methods "~1.1.2"
+    on-finished "~2.3.0"
+    parseurl "~1.3.3"
+    path-to-regexp "0.1.7"
+    proxy-addr "~2.0.5"
+    qs "6.7.0"
+    range-parser "~1.2.1"
+    safe-buffer "5.1.2"
+    send "0.17.1"
+    serve-static "1.14.1"
+    setprototypeof "1.1.1"
+    statuses "~1.5.0"
+    type-is "~1.6.18"
+    utils-merge "1.0.1"
+    vary "~1.1.2"
+
 extend-shallow@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
@@ -6684,6 +6817,11 @@ file-type@^7.7.1:
   resolved "https://registry.yarnpkg.com/file-type/-/file-type-7.7.1.tgz#91c2f5edb8ce70688b9b68a90d931bbb6cb21f65"
   integrity sha512-bTrKkzzZI6wH+NXhyD3SOXtb2zXTw2SbwI2RxUlRcXVsnN7jNL5hJzVQLYv7FOQhxFkK4XWdAflEaWFpaLLWpQ==
 
+file-uri-to-path@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
+  integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
+
 filename-regex@^2.0.0:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
@@ -6755,6 +6893,19 @@ finalhandler@1.1.1:
     statuses "~1.4.0"
     unpipe "~1.0.0"
 
+finalhandler@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
+  integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
+  dependencies:
+    debug "2.6.9"
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    on-finished "~2.3.0"
+    parseurl "~1.3.3"
+    statuses "~1.5.0"
+    unpipe "~1.0.0"
+
 find-cache-dir@^0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9"
@@ -7060,6 +7211,14 @@ fsevents@^1.2.2:
     nan "^2.9.2"
     node-pre-gyp "^0.10.0"
 
+fsevents@^1.2.7:
+  version "1.2.11"
+  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.11.tgz#67bf57f4758f02ede88fb2a1712fef4d15358be3"
+  integrity sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==
+  dependencies:
+    bindings "^1.5.0"
+    nan "^2.12.1"
+
 fstream@^1.0.0, fstream@^1.0.2:
   version "1.0.12"
   resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
@@ -7968,7 +8127,7 @@ html-comment-regex@^1.1.0:
   resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e"
   integrity sha1-ZouTd26q5V696POtRkswekljYl4=
 
-html-entities@^1.2.0:
+html-entities@^1.2.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f"
   integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=
@@ -8013,6 +8172,28 @@ http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3:
     setprototypeof "1.1.0"
     statuses ">= 1.4.0 < 2"
 
+http-errors@1.7.2:
+  version "1.7.2"
+  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
+  integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
+  dependencies:
+    depd "~1.1.2"
+    inherits "2.0.3"
+    setprototypeof "1.1.1"
+    statuses ">= 1.5.0 < 2"
+    toidentifier "1.0.0"
+
+http-errors@~1.7.2:
+  version "1.7.3"
+  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
+  integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==
+  dependencies:
+    depd "~1.1.2"
+    inherits "2.0.4"
+    setprototypeof "1.1.1"
+    statuses ">= 1.5.0 < 2"
+    toidentifier "1.0.0"
+
 http-parser-js@>=0.4.0:
   version "0.4.13"
   resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.13.tgz#3bd6d6fde6e3172c9334c3b33b6c193d80fe1137"
@@ -8026,17 +8207,17 @@ http-proxy-agent@^2.1.0:
     agent-base "4"
     debug "3.1.0"
 
-http-proxy-middleware@~0.18.0:
-  version "0.18.0"
-  resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz#0987e6bb5a5606e5a69168d8f967a87f15dd8aab"
-  integrity sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==
+http-proxy-middleware@0.19.1:
+  version "0.19.1"
+  resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a"
+  integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==
   dependencies:
-    http-proxy "^1.16.2"
+    http-proxy "^1.17.0"
     is-glob "^4.0.0"
-    lodash "^4.17.5"
-    micromatch "^3.1.9"
+    lodash "^4.17.11"
+    micromatch "^3.1.10"
 
-http-proxy@^1.13.0, http-proxy@^1.16.2:
+http-proxy@^1.13.0:
   version "1.17.0"
   resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.17.0.tgz#7ad38494658f84605e2f6db4436df410f4e5be9a"
   integrity sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==
@@ -8045,6 +8226,15 @@ http-proxy@^1.13.0, http-proxy@^1.16.2:
     follow-redirects "^1.0.0"
     requires-port "^1.0.0"
 
+http-proxy@^1.17.0:
+  version "1.18.0"
+  resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.0.tgz#dbe55f63e75a347db7f3d99974f2692a314a6a3a"
+  integrity sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==
+  dependencies:
+    eventemitter3 "^4.0.0"
+    follow-redirects "^1.0.0"
+    requires-port "^1.0.0"
+
 http-signature@~0.10.0:
   version "0.10.1"
   resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-0.10.1.tgz#4fbdac132559aa8323121e540779c0a012b27e66"
@@ -8116,7 +8306,7 @@ iconv-lite@0.4.23:
   dependencies:
     safer-buffer ">= 2.1.2 < 3"
 
-iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
+iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
   version "0.4.24"
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
   integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@@ -8311,7 +8501,7 @@ inherits@1:
   resolved "https://registry.yarnpkg.com/inherits/-/inherits-1.0.2.tgz#ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b"
   integrity sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=
 
-inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
+inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
   integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -8449,13 +8639,13 @@ insert-module-globals@^6.1.0:
     through2 "^1.0.0"
     xtend "^4.0.0"
 
-internal-ip@^3.0.1:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-3.0.1.tgz#df5c99876e1d2eb2ea2d74f520e3f669a00ece27"
-  integrity sha512-NXXgESC2nNVtU+pqmC9e6R8B1GpKxzsAQhffvh5AL79qKnodd+L7tnEQmTiUAVngqLalPbSqRA7XGIEL5nCd0Q==
+internal-ip@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907"
+  integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==
   dependencies:
-    default-gateway "^2.6.0"
-    ipaddr.js "^1.5.2"
+    default-gateway "^4.2.0"
+    ipaddr.js "^1.9.0"
 
 interpret@^1.0.0:
   version "1.1.0"
@@ -8499,16 +8689,26 @@ ipaddr.js@1.8.0:
   resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e"
   integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4=
 
-ipaddr.js@^1.5.2:
-  version "1.8.1"
-  resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.1.tgz#fa4b79fa47fd3def5e3b159825161c0a519c9427"
-  integrity sha1-+kt5+kf9Pe9eOxWYJRYcClGclCc=
+ipaddr.js@1.9.0:
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65"
+  integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==
+
+ipaddr.js@^1.9.0:
+  version "1.9.1"
+  resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
+  integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
 
 is-absolute-url@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6"
   integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=
 
+is-absolute-url@^3.0.3:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698"
+  integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==
+
 is-absolute@^0.1.5:
   version "0.1.7"
   resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-0.1.7.tgz#847491119fccb5fb436217cc737f7faad50f603f"
@@ -8785,6 +8985,11 @@ is-path-cwd@^1.0.0:
   resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
   integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=
 
+is-path-cwd@^2.0.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb"
+  integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==
+
 is-path-in-cwd@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52"
@@ -8792,6 +8997,13 @@ is-path-in-cwd@^1.0.0:
   dependencies:
     is-path-inside "^1.0.0"
 
+is-path-in-cwd@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb"
+  integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==
+  dependencies:
+    is-path-inside "^2.1.0"
+
 is-path-inside@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
@@ -8799,6 +9011,13 @@ is-path-inside@^1.0.0:
   dependencies:
     path-is-inside "^1.0.1"
 
+is-path-inside@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2"
+  integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==
+  dependencies:
+    path-is-inside "^1.0.2"
+
 is-plain-obj@^1.0.0, is-plain-obj@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
@@ -9553,7 +9772,7 @@ keytime@^0.1.0:
     lerp-array "^1.0.2"
     xtend "^4.0.0"
 
-killable@^1.0.0:
+killable@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
   integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==
@@ -10289,10 +10508,10 @@ logalot@^2.0.0:
     figures "^1.3.5"
     squeak "^1.0.0"
 
-loglevel@^1.4.1:
-  version "1.6.1"
-  resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa"
-  integrity sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=
+loglevel@^1.6.6:
+  version "1.6.6"
+  resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.6.tgz#0ee6300cc058db6b3551fa1c4bf73b83bb771312"
+  integrity sha512-Sgr5lbboAUBo3eXCSPL4/KoVz3ROKquOjcctxmHIt+vol2DrqTQe3SwkKKuYhEiWB5kYa13YyopJ69deJ1irzQ==
 
 loglevelnext@^1.0.1:
   version "1.0.5"
@@ -10580,7 +10799,7 @@ memory-fs@^0.2.0:
   resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290"
   integrity sha1-8rslNovBIeORwlIN6Slpyu4KApA=
 
-memory-fs@^0.4.0, memory-fs@~0.4.1:
+memory-fs@^0.4.0, memory-fs@^0.4.1, memory-fs@~0.4.1:
   version "0.4.1"
   resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
   integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=
@@ -10674,7 +10893,7 @@ micromatch@^2.3.11, micromatch@^2.3.7:
     parse-glob "^3.0.4"
     regex-cache "^0.4.2"
 
-micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8, micromatch@^3.1.9:
+micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8:
   version "3.1.10"
   resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
   integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
@@ -10701,7 +10920,12 @@ miller-rabin@^4.0.0:
     bn.js "^4.0.0"
     brorand "^1.0.1"
 
-"mime-db@>= 1.36.0 < 2", mime-db@~1.36.0:
+mime-db@1.43.0, "mime-db@>= 1.43.0 < 2":
+  version "1.43.0"
+  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58"
+  integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==
+
+mime-db@~1.36.0:
   version "1.36.0"
   resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397"
   integrity sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==
@@ -10713,12 +10937,19 @@ mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.19:
   dependencies:
     mime-db "~1.36.0"
 
+mime-types@~2.1.24:
+  version "2.1.26"
+  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06"
+  integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==
+  dependencies:
+    mime-db "1.43.0"
+
 mime@1.4.1:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
   integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==
 
-mime@^1.2.11, mime@^1.4.1:
+mime@1.6.0, mime@^1.2.11, mime@^1.4.1:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
   integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
@@ -10728,6 +10959,11 @@ mime@^2.0.3, mime@^2.1.0, mime@^2.3.1:
   resolved "https://registry.yarnpkg.com/mime/-/mime-2.3.1.tgz#b1621c54d63b97c47d3cfe7f7215f7d64517c369"
   integrity sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==
 
+mime@^2.4.4:
+  version "2.4.4"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5"
+  integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==
+
 mime@~1.2.11, mime@~1.2.9:
   version "1.2.11"
   resolved "https://registry.yarnpkg.com/mime/-/mime-1.2.11.tgz#58203eed86e3a5ef17aed2b7d9ebd47f0a60dd10"
@@ -10836,6 +11072,14 @@ minipass@^2.3.5:
     safe-buffer "^5.1.2"
     yallist "^3.0.0"
 
+minipass@^2.8.6:
+  version "2.9.0"
+  resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
+  integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
+  dependencies:
+    safe-buffer "^5.1.2"
+    yallist "^3.0.0"
+
 minizlib@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb"
@@ -10986,6 +11230,11 @@ ms@2.0.0:
   resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
   integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
 
+ms@2.1.1, ms@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
+  integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
+
 ms@^0.7.2:
   version "0.7.3"
   resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff"
@@ -10996,11 +11245,6 @@ ms@^2.0.0:
   resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
   integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
 
-ms@^2.1.1:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
-  integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
-
 multicast-dns-service-types@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901"
@@ -11060,6 +11304,11 @@ nan@^2.10.0, nan@^2.9.2:
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766"
   integrity sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==
 
+nan@^2.12.1:
+  version "2.14.0"
+  resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
+  integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
+
 nanomatch@^1.2.9:
   version "1.2.13"
   resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
@@ -11101,6 +11350,11 @@ negotiator@0.6.1:
   resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
   integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=
 
+negotiator@0.6.2:
+  version "0.6.2"
+  resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
+  integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
+
 neo-async@^2.5.0:
   version "2.5.2"
   resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.2.tgz#489105ce7bc54e709d736b195f82135048c50fcc"
@@ -11169,10 +11423,10 @@ node-fetch@^2.3.0, node-fetch@^2.5.0:
   resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
   integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
 
-node-forge@0.7.5:
-  version "0.7.5"
-  resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df"
-  integrity sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==
+node-forge@0.9.0:
+  version "0.9.0"
+  resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579"
+  integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==
 
 node-gyp@^3.8.0:
   version "3.8.0"
@@ -11248,6 +11502,22 @@ node-modules-regexp@^1.0.0:
   resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40"
   integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=
 
+node-pre-gyp@*:
+  version "0.14.0"
+  resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83"
+  integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==
+  dependencies:
+    detect-libc "^1.0.2"
+    mkdirp "^0.5.1"
+    needle "^2.2.1"
+    nopt "^4.0.1"
+    npm-packlist "^1.1.6"
+    npmlog "^4.0.2"
+    rc "^1.2.7"
+    rimraf "^2.6.1"
+    semver "^5.3.0"
+    tar "^4.4.2"
+
 node-pre-gyp@^0.10.0:
   version "0.10.3"
   resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc"
@@ -11362,6 +11632,11 @@ normalize-path@^2.0.1, normalize-path@^2.1.1:
   dependencies:
     remove-trailing-separator "^1.0.1"
 
+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==
+
 normalize-range@^0.1.2:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
@@ -11663,10 +11938,10 @@ on-finished@~2.3.0:
   dependencies:
     ee-first "1.1.1"
 
-on-headers@~1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
-  integrity sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=
+on-headers@~1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
+  integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
 
 once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0:
   version "1.4.0"
@@ -11701,10 +11976,10 @@ opn@5.2.0:
   dependencies:
     is-wsl "^1.1.0"
 
-opn@^5.1.0:
-  version "5.4.0"
-  resolved "https://registry.yarnpkg.com/opn/-/opn-5.4.0.tgz#cb545e7aab78562beb11aa3bfabc7042e1761035"
-  integrity sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==
+opn@^5.5.0:
+  version "5.5.0"
+  resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc"
+  integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==
   dependencies:
     is-wsl "^1.1.0"
 
@@ -11934,6 +12209,13 @@ p-reduce@^1.0.0:
   resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa"
   integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=
 
+p-retry@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328"
+  integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==
+  dependencies:
+    retry "^0.12.0"
+
 p-try@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
@@ -12107,6 +12389,11 @@ parseurl@~1.3.2:
   resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
   integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=
 
+parseurl@~1.3.3:
+  version "1.3.3"
+  resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
+  integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
+
 pascalcase@^0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
@@ -12364,7 +12651,7 @@ pogo@0.9.4:
     uglify-js "~2.4.13"
     underscore "1.4.4"
 
-portfinder@^1.0.17, portfinder@^1.0.9:
+portfinder@^1.0.17:
   version "1.0.17"
   resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.17.tgz#a8a1691143e46c4735edefcf4fbcccedad26456a"
   integrity sha512-syFcRIRzVI1BoEFOCaAiizwDolh1S1YXSodsVhncbhjzjZQulhczNRbqnUl9N31Q4dKGOXsNDqxC2BWBgSMqeQ==
@@ -12373,6 +12660,15 @@ portfinder@^1.0.17, portfinder@^1.0.9:
     debug "^2.2.0"
     mkdirp "0.5.x"
 
+portfinder@^1.0.25:
+  version "1.0.25"
+  resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca"
+  integrity sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==
+  dependencies:
+    async "^2.6.2"
+    debug "^3.1.1"
+    mkdirp "^0.5.1"
+
 posix-character-classes@^0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
@@ -12959,6 +13255,14 @@ proxy-addr@~2.0.4:
     forwarded "~0.1.2"
     ipaddr.js "1.8.0"
 
+proxy-addr@~2.0.5:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34"
+  integrity sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==
+  dependencies:
+    forwarded "~0.1.2"
+    ipaddr.js "1.9.0"
+
 proxy-from-env@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee"
@@ -13070,6 +13374,11 @@ qs@6.5.2, qs@^6.4.0, qs@^6.5.1, qs@^6.5.2, qs@~6.5.1, qs@~6.5.2:
   resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
   integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
 
+qs@6.7.0:
+  version "6.7.0"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
+  integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
+
 qs@~0.6.0:
   version "0.6.6"
   resolved "https://registry.yarnpkg.com/qs/-/qs-0.6.6.tgz#6e015098ff51968b8a3c819001d5f2c89bc4b107"
@@ -13141,6 +13450,11 @@ range-parser@^1.0.3, range-parser@^1.2.0, range-parser@~1.2.0:
   resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
   integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=
 
+range-parser@^1.2.1, range-parser@~1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
+  integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
+
 raw-body@2.3.3:
   version "2.3.3"
   resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3"
@@ -13151,6 +13465,16 @@ raw-body@2.3.3:
     iconv-lite "0.4.23"
     unpipe "1.0.0"
 
+raw-body@2.4.0:
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
+  integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
+  dependencies:
+    bytes "3.1.0"
+    http-errors "1.7.2"
+    iconv-lite "0.4.24"
+    unpipe "1.0.0"
+
 raw-body@~1.1.0:
   version "1.1.7"
   resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-1.1.7.tgz#1d027c2bfa116acc6623bca8f00016572a87d425"
@@ -13478,7 +13802,7 @@ readdir-scoped-modules@^1.0.0:
     graceful-fs "^4.1.2"
     once "^1.3.0"
 
-readdirp@^2.0.0:
+readdirp@^2.0.0, readdirp@^2.2.1:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525"
   integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==
@@ -13918,6 +14242,11 @@ retry@^0.10.0:
   resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4"
   integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=
 
+retry@^0.12.0:
+  version "0.12.0"
+  resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
+  integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=
+
 rfc6902@^3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/rfc6902/-/rfc6902-3.0.1.tgz#03a3d38329dbc266fbc92aa7fc14546d7839e89f"
@@ -14170,12 +14499,12 @@ select@^1.1.2:
   resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
   integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=
 
-selfsigned@^1.9.1:
-  version "1.10.3"
-  resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.3.tgz#d628ecf9e3735f84e8bafba936b3cf85bea43823"
-  integrity sha512-vmZenZ+8Al3NLHkWnhBQ0x6BkML1eCP2xEi3JE+f3D9wW9fipD9NNJHYtE9XJM4TsPaHGZJIamrSI6MTg1dU2Q==
+selfsigned@^1.10.7:
+  version "1.10.7"
+  resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.7.tgz#da5819fd049d5574f28e88a9bcc6dbc6e6f3906b"
+  integrity sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==
   dependencies:
-    node-forge "0.7.5"
+    node-forge "0.9.0"
 
 semver-compare@^1.0.0:
   version "1.0.0"
@@ -14204,7 +14533,7 @@ semver@^4.0.3, semver@^4.1.0:
   resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
   integrity sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=
 
-semver@^6.0.0, semver@^6.2.0:
+semver@^6.0.0, semver@^6.2.0, semver@^6.3.0:
   version "6.3.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
   integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
@@ -14233,6 +14562,25 @@ send@0.16.2:
     range-parser "~1.2.0"
     statuses "~1.4.0"
 
+send@0.17.1:
+  version "0.17.1"
+  resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
+  integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==
+  dependencies:
+    debug "2.6.9"
+    depd "~1.1.2"
+    destroy "~1.0.4"
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    etag "~1.8.1"
+    fresh "0.5.2"
+    http-errors "~1.7.2"
+    mime "1.6.0"
+    ms "2.1.1"
+    on-finished "~2.3.0"
+    range-parser "~1.2.1"
+    statuses "~1.5.0"
+
 sequencify@~0.0.7:
   version "0.0.7"
   resolved "https://registry.yarnpkg.com/sequencify/-/sequencify-0.0.7.tgz#90cff19d02e07027fd767f5ead3e7b95d1e7380c"
@@ -14243,7 +14591,7 @@ serialize-javascript@^1.4.0:
   resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.5.0.tgz#1aa336162c88a890ddad5384baebc93a655161fe"
   integrity sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==
 
-serve-index@^1.7.2:
+serve-index@^1.9.1:
   version "1.9.1"
   resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239"
   integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=
@@ -14266,6 +14614,16 @@ serve-static@1.13.2:
     parseurl "~1.3.2"
     send "0.16.2"
 
+serve-static@1.14.1:
+  version "1.14.1"
+  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
+  integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
+  dependencies:
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    parseurl "~1.3.3"
+    send "0.17.1"
+
 serviceworker-webpack-plugin@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/serviceworker-webpack-plugin/-/serviceworker-webpack-plugin-1.0.1.tgz#481863288487e92da01d49745336c72ef8a6136b"
@@ -14320,6 +14678,11 @@ setprototypeof@1.1.0:
   resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
   integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
 
+setprototypeof@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
+  integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
+
 sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4:
   version "2.4.11"
   resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
@@ -14579,10 +14942,10 @@ sockjs-client@1.1.5:
     json3 "^3.3.2"
     url-parse "^1.1.8"
 
-sockjs-client@1.3.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.3.0.tgz#12fc9d6cb663da5739d3dc5fb6e8687da95cb177"
-  integrity sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==
+sockjs-client@1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5"
+  integrity sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==
   dependencies:
     debug "^3.2.5"
     eventsource "^1.0.7"
@@ -14776,7 +15139,7 @@ spdy-transport@^3.0.0:
     readable-stream "^3.0.6"
     wbuf "^1.7.3"
 
-spdy@^4.0.0:
+spdy@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.1.tgz#6f12ed1c5db7ea4f24ebb8b89ba58c87c08257f2"
   integrity sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA==
@@ -14917,7 +15280,7 @@ static-module@^2.2.0:
     static-eval "^2.0.0"
     through2 "~2.0.3"
 
-"statuses@>= 1.4.0 < 2":
+"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0:
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
   integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
@@ -15286,13 +15649,20 @@ supports-color@^3.1.0, supports-color@^3.1.2, supports-color@^3.2.3:
   dependencies:
     has-flag "^1.0.0"
 
-supports-color@^5.0.0, supports-color@^5.1.0, supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0:
+supports-color@^5.0.0, supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.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@^6.1.0:
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
+  integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
+  dependencies:
+    has-flag "^3.0.0"
+
 supports-hyperlinks@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz#71daedf36cc1060ac5100c351bb3da48c29c0ef7"
@@ -15419,6 +15789,19 @@ tar@^4.4.10, tar@^4.4.8:
     safe-buffer "^5.1.2"
     yallist "^3.0.3"
 
+tar@^4.4.2:
+  version "4.4.13"
+  resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
+  integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==
+  dependencies:
+    chownr "^1.1.1"
+    fs-minipass "^1.2.5"
+    minipass "^2.8.6"
+    minizlib "^1.2.1"
+    mkdirp "^0.5.0"
+    safe-buffer "^5.1.2"
+    yallist "^3.0.3"
+
 tcp-port-used@^0.1.2:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/tcp-port-used/-/tcp-port-used-0.1.2.tgz#9450e8768c83b416fd4d1a6a9449eeccbf496c29"
@@ -15695,6 +16078,11 @@ to-regex@^3.0.1, to-regex@^3.0.2:
     regex-not "^1.0.2"
     safe-regex "^1.1.0"
 
+toidentifier@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
+  integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
+
 toml@^2.3.2:
   version "2.3.3"
   resolved "https://registry.yarnpkg.com/toml/-/toml-2.3.3.tgz#8d683d729577cb286231dfc7a8affe58d31728fb"
@@ -15883,6 +16271,14 @@ type-is@~1.6.16:
     media-typer "0.3.0"
     mime-types "~2.1.18"
 
+type-is@~1.6.17, type-is@~1.6.18:
+  version "1.6.18"
+  resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
+  integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
+  dependencies:
+    media-typer "0.3.0"
+    mime-types "~2.1.24"
+
 type-name@^2.0.1:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/type-name/-/type-name-2.0.2.tgz#efe7d4123d8ac52afff7f40c7e4dec5266008fb4"
@@ -16157,6 +16553,11 @@ upath@^1.0.5:
   resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd"
   integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==
 
+upath@^1.1.1:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894"
+  integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==
+
 updeep@^0.16.0:
   version "0.16.1"
   resolved "https://registry.yarnpkg.com/updeep/-/updeep-0.16.1.tgz#8bfc34cbc2f7b8f3dc0166052c0e8bb7716cc6c8"
@@ -16530,16 +16931,6 @@ webidl-conversions@^4.0.2:
   resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
   integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
 
-webpack-dev-middleware@3.4.0, webpack-dev-middleware@^3.4.0:
-  version "3.4.0"
-  resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz#1132fecc9026fd90f0ecedac5cbff75d1fb45890"
-  integrity sha512-Q9Iyc0X9dP9bAsYskAVJ/hmIZZQwf/3Sy4xCAZgL5cUkjZmUZLt4l5HpbST/Pdgjn3u6pE7u5OdGd1apgzRujA==
-  dependencies:
-    memory-fs "~0.4.1"
-    mime "^2.3.1"
-    range-parser "^1.0.3"
-    webpack-log "^2.0.0"
-
 webpack-dev-middleware@^2.0.6:
   version "2.0.6"
   resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz#a51692801e8310844ef3e3790e1eacfe52326fd4"
@@ -16553,41 +16944,65 @@ webpack-dev-middleware@^2.0.6:
     url-join "^2.0.2"
     webpack-log "^1.0.1"
 
-webpack-dev-server@3.1.11:
-  version "3.1.11"
-  resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.1.11.tgz#3b698b5b32476f1f0d3d4014952fcf42ab118205"
-  integrity sha512-E/uGbO9ndXrXgNUzw+O2UrrvYY/eIw10fpJnbvJf8VOH/NWZuY3nUG7arbgB/kbkORlF/sPHxnv10tKFtKf3aA==
+webpack-dev-middleware@^3.4.0:
+  version "3.4.0"
+  resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz#1132fecc9026fd90f0ecedac5cbff75d1fb45890"
+  integrity sha512-Q9Iyc0X9dP9bAsYskAVJ/hmIZZQwf/3Sy4xCAZgL5cUkjZmUZLt4l5HpbST/Pdgjn3u6pE7u5OdGd1apgzRujA==
+  dependencies:
+    memory-fs "~0.4.1"
+    mime "^2.3.1"
+    range-parser "^1.0.3"
+    webpack-log "^2.0.0"
+
+webpack-dev-middleware@^3.7.2:
+  version "3.7.2"
+  resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz#0019c3db716e3fa5cecbf64f2ab88a74bab331f3"
+  integrity sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==
+  dependencies:
+    memory-fs "^0.4.1"
+    mime "^2.4.4"
+    mkdirp "^0.5.1"
+    range-parser "^1.2.1"
+    webpack-log "^2.0.0"
+
+webpack-dev-server@3.10.2:
+  version "3.10.2"
+  resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.10.2.tgz#3403287d674c7407aab6d9b3f72259ecd0aa0874"
+  integrity sha512-pxZKPYb+n77UN8u9YxXT4IaIrGcNtijh/mi8TXbErHmczw0DtPnMTTjHj+eNjkqLOaAZM/qD7V59j/qJsEiaZA==
   dependencies:
     ansi-html "0.0.7"
     bonjour "^3.5.0"
-    chokidar "^2.0.0"
-    compression "^1.5.2"
-    connect-history-api-fallback "^1.3.0"
-    debug "^3.1.0"
-    del "^3.0.0"
-    express "^4.16.2"
-    html-entities "^1.2.0"
-    http-proxy-middleware "~0.18.0"
+    chokidar "^2.1.8"
+    compression "^1.7.4"
+    connect-history-api-fallback "^1.6.0"
+    debug "^4.1.1"
+    del "^4.1.1"
+    express "^4.17.1"
+    html-entities "^1.2.1"
+    http-proxy-middleware "0.19.1"
     import-local "^2.0.0"
-    internal-ip "^3.0.1"
+    internal-ip "^4.3.0"
     ip "^1.1.5"
-    killable "^1.0.0"
-    loglevel "^1.4.1"
-    opn "^5.1.0"
-    portfinder "^1.0.9"
+    is-absolute-url "^3.0.3"
+    killable "^1.0.1"
+    loglevel "^1.6.6"
+    opn "^5.5.0"
+    p-retry "^3.0.1"
+    portfinder "^1.0.25"
     schema-utils "^1.0.0"
-    selfsigned "^1.9.1"
-    semver "^5.6.0"
-    serve-index "^1.7.2"
+    selfsigned "^1.10.7"
+    semver "^6.3.0"
+    serve-index "^1.9.1"
     sockjs "0.3.19"
-    sockjs-client "1.3.0"
-    spdy "^4.0.0"
-    strip-ansi "^3.0.0"
-    supports-color "^5.1.0"
+    sockjs-client "1.4.0"
+    spdy "^4.0.1"
+    strip-ansi "^3.0.1"
+    supports-color "^6.1.0"
     url "^0.11.0"
-    webpack-dev-middleware "3.4.0"
+    webpack-dev-middleware "^3.7.2"
     webpack-log "^2.0.0"
-    yargs "12.0.2"
+    ws "^6.2.1"
+    yargs "12.0.5"
 
 webpack-log@^1.0.1:
   version "1.2.0"
@@ -16874,6 +17289,13 @@ ws@^6.1.0:
   dependencies:
     async-limiter "~1.0.0"
 
+ws@^6.2.1:
+  version "6.2.1"
+  resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
+  integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==
+  dependencies:
+    async-limiter "~1.0.0"
+
 ws@~3.3.1:
   version "3.3.3"
   resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
@@ -16898,11 +17320,6 @@ xmlhttprequest-ssl@~1.5.4:
   resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e"
   integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=
 
-xregexp@4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020"
-  integrity sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==
-
 "xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
@@ -16946,13 +17363,6 @@ yamljs@^0.2.1:
     argparse "^1.0.7"
     glob "^7.0.5"
 
-yargs-parser@^10.1.0:
-  version "10.1.0"
-  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
-  integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==
-  dependencies:
-    camelcase "^4.1.0"
-
 yargs-parser@^11.1.1:
   version "11.1.1"
   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4"
@@ -17000,25 +17410,7 @@ yargs@11.1.0, yargs@^11.0.0:
     y18n "^3.2.1"
     yargs-parser "^9.0.2"
 
-yargs@12.0.2:
-  version "12.0.2"
-  resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.2.tgz#fe58234369392af33ecbef53819171eff0f5aadc"
-  integrity sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==
-  dependencies:
-    cliui "^4.0.0"
-    decamelize "^2.0.0"
-    find-up "^3.0.0"
-    get-caller-file "^1.0.1"
-    os-locale "^3.0.0"
-    require-directory "^2.1.1"
-    require-main-filename "^1.0.1"
-    set-blocking "^2.0.0"
-    string-width "^2.0.0"
-    which-module "^2.0.0"
-    y18n "^3.2.1 || ^4.0.0"
-    yargs-parser "^10.1.0"
-
-yargs@^12.0.1:
+yargs@12.0.5, yargs@^12.0.1:
   version "12.0.5"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"
   integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==