Index: node_modules/node-gyp/lib/Find-VisualStudio.cs
===================================================================
--- node_modules/node-gyp/lib/Find-VisualStudio.cs	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/node-gyp/lib/Find-VisualStudio.cs	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,250 @@
+// Copyright 2017 - Refael Ackermann
+// Distributed under MIT style license
+// See accompanying file LICENSE at https://github.com/node4good/windows-autoconf
+
+// Usage:
+// powershell -ExecutionPolicy Unrestricted -Command "Add-Type -Path Find-VisualStudio.cs; [VisualStudioConfiguration.Main]::PrintJson()"
+// This script needs to be compatible with PowerShell v2 to run on Windows 2008R2 and Windows 7.
+
+using System;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+namespace VisualStudioConfiguration
+{
+    [Flags]
+    public enum InstanceState : uint
+    {
+        None = 0,
+        Local = 1,
+        Registered = 2,
+        NoRebootRequired = 4,
+        NoErrors = 8,
+        Complete = 4294967295,
+    }
+
+    [Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")]
+    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+    [ComImport]
+    public interface IEnumSetupInstances
+    {
+
+        void Next([MarshalAs(UnmanagedType.U4), In] int celt,
+            [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface), Out] ISetupInstance[] rgelt,
+            [MarshalAs(UnmanagedType.U4)] out int pceltFetched);
+
+        void Skip([MarshalAs(UnmanagedType.U4), In] int celt);
+
+        void Reset();
+
+        [return: MarshalAs(UnmanagedType.Interface)]
+        IEnumSetupInstances Clone();
+    }
+
+    [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
+    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+    [ComImport]
+    public interface ISetupConfiguration
+    {
+    }
+
+    [Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")]
+    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+    [ComImport]
+    public interface ISetupConfiguration2 : ISetupConfiguration
+    {
+
+        [return: MarshalAs(UnmanagedType.Interface)]
+        IEnumSetupInstances EnumInstances();
+
+        [return: MarshalAs(UnmanagedType.Interface)]
+        ISetupInstance GetInstanceForCurrentProcess();
+
+        [return: MarshalAs(UnmanagedType.Interface)]
+        ISetupInstance GetInstanceForPath([MarshalAs(UnmanagedType.LPWStr), In] string path);
+
+        [return: MarshalAs(UnmanagedType.Interface)]
+        IEnumSetupInstances EnumAllInstances();
+    }
+
+    [Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")]
+    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+    [ComImport]
+    public interface ISetupInstance
+    {
+    }
+
+    [Guid("89143C9A-05AF-49B0-B717-72E218A2185C")]
+    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+    [ComImport]
+    public interface ISetupInstance2 : ISetupInstance
+    {
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string GetInstanceId();
+
+        [return: MarshalAs(UnmanagedType.Struct)]
+        System.Runtime.InteropServices.ComTypes.FILETIME GetInstallDate();
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string GetInstallationName();
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string GetInstallationPath();
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string GetInstallationVersion();
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string GetDisplayName([MarshalAs(UnmanagedType.U4), In] int lcid);
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string GetDescription([MarshalAs(UnmanagedType.U4), In] int lcid);
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string ResolvePath([MarshalAs(UnmanagedType.LPWStr), In] string pwszRelativePath);
+
+        [return: MarshalAs(UnmanagedType.U4)]
+        InstanceState GetState();
+
+        [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
+        ISetupPackageReference[] GetPackages();
+
+        ISetupPackageReference GetProduct();
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string GetProductPath();
+
+        [return: MarshalAs(UnmanagedType.VariantBool)]
+        bool IsLaunchable();
+
+        [return: MarshalAs(UnmanagedType.VariantBool)]
+        bool IsComplete();
+
+        [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
+        ISetupPropertyStore GetProperties();
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string GetEnginePath();
+    }
+
+    [Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")]
+    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+    [ComImport]
+    public interface ISetupPackageReference
+    {
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string GetId();
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string GetVersion();
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string GetChip();
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string GetLanguage();
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string GetBranch();
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string GetType();
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string GetUniqueId();
+
+        [return: MarshalAs(UnmanagedType.VariantBool)]
+        bool GetIsExtension();
+    }
+
+    [Guid("c601c175-a3be-44bc-91f6-4568d230fc83")]
+    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+    [ComImport]
+    public interface ISetupPropertyStore
+    {
+
+        [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
+        string[] GetNames();
+
+        object GetValue([MarshalAs(UnmanagedType.LPWStr), In] string pwszName);
+    }
+
+    [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
+    [CoClass(typeof(SetupConfigurationClass))]
+    [ComImport]
+    public interface SetupConfiguration : ISetupConfiguration2, ISetupConfiguration
+    {
+    }
+
+    [Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")]
+    [ClassInterface(ClassInterfaceType.None)]
+    [ComImport]
+    public class SetupConfigurationClass
+    {
+    }
+
+    public static class Main
+    {
+        public static void PrintJson()
+        {
+            ISetupConfiguration query = new SetupConfiguration();
+            ISetupConfiguration2 query2 = (ISetupConfiguration2)query;
+            IEnumSetupInstances e = query2.EnumAllInstances();
+
+            int pceltFetched;
+            ISetupInstance2[] rgelt = new ISetupInstance2[1];
+            List<string> instances = new List<string>();
+            while (true)
+            {
+                e.Next(1, rgelt, out pceltFetched);
+                if (pceltFetched <= 0)
+                {
+                    Console.WriteLine(String.Format("[{0}]", string.Join(",", instances.ToArray())));
+                    return;
+                }
+
+                try
+                {
+                    instances.Add(InstanceJson(rgelt[0]));
+                }
+                catch (COMException)
+                {
+                    // Ignore instances that can't be queried.
+                }
+            }
+        }
+
+        private static string JsonString(string s)
+        {
+            return "\"" + s.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
+        }
+
+        private static string InstanceJson(ISetupInstance2 setupInstance2)
+        {
+            // Visual Studio component directory:
+            // https://docs.microsoft.com/en-us/visualstudio/install/workload-and-component-ids
+
+            StringBuilder json = new StringBuilder();
+            json.Append("{");
+
+            string path = JsonString(setupInstance2.GetInstallationPath());
+            json.Append(String.Format("\"path\":{0},", path));
+
+            string version = JsonString(setupInstance2.GetInstallationVersion());
+            json.Append(String.Format("\"version\":{0},", version));
+
+            List<string> packages = new List<string>();
+            foreach (ISetupPackageReference package in setupInstance2.GetPackages())
+            {
+                string id = JsonString(package.GetId());
+                packages.Add(id);
+            }
+            json.Append(String.Format("\"packages\":[{0}]", string.Join(",", packages.ToArray())));
+
+            json.Append("}");
+            return json.ToString();
+        }
+    }
+}
Index: node_modules/node-gyp/lib/build.js
===================================================================
--- node_modules/node-gyp/lib/build.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/node-gyp/lib/build.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,204 @@
+'use strict'
+
+const fs = require('graceful-fs')
+const path = require('path')
+const glob = require('glob')
+const log = require('npmlog')
+const which = require('which')
+const win = process.platform === 'win32'
+
+function build (gyp, argv, callback) {
+  var platformMake = 'make'
+  if (process.platform === 'aix') {
+    platformMake = 'gmake'
+  } else if (process.platform.indexOf('bsd') !== -1) {
+    platformMake = 'gmake'
+  } else if (win && argv.length > 0) {
+    argv = argv.map(function (target) {
+      return '/t:' + target
+    })
+  }
+
+  var makeCommand = gyp.opts.make || process.env.MAKE || platformMake
+  var command = win ? 'msbuild' : makeCommand
+  var jobs = gyp.opts.jobs || process.env.JOBS
+  var buildType
+  var config
+  var arch
+  var nodeDir
+  var guessedSolution
+
+  loadConfigGypi()
+
+  /**
+   * Load the "config.gypi" file that was generated during "configure".
+   */
+
+  function loadConfigGypi () {
+    var configPath = path.resolve('build', 'config.gypi')
+
+    fs.readFile(configPath, 'utf8', function (err, data) {
+      if (err) {
+        if (err.code === 'ENOENT') {
+          callback(new Error('You must run `node-gyp configure` first!'))
+        } else {
+          callback(err)
+        }
+        return
+      }
+      config = JSON.parse(data.replace(/#.+\n/, ''))
+
+      // get the 'arch', 'buildType', and 'nodeDir' vars from the config
+      buildType = config.target_defaults.default_configuration
+      arch = config.variables.target_arch
+      nodeDir = config.variables.nodedir
+
+      if ('debug' in gyp.opts) {
+        buildType = gyp.opts.debug ? 'Debug' : 'Release'
+      }
+      if (!buildType) {
+        buildType = 'Release'
+      }
+
+      log.verbose('build type', buildType)
+      log.verbose('architecture', arch)
+      log.verbose('node dev dir', nodeDir)
+
+      if (win) {
+        findSolutionFile()
+      } else {
+        doWhich()
+      }
+    })
+  }
+
+  /**
+   * On Windows, find the first build/*.sln file.
+   */
+
+  function findSolutionFile () {
+    glob('build/*.sln', function (err, files) {
+      if (err) {
+        return callback(err)
+      }
+      if (files.length === 0) {
+        return callback(new Error('Could not find *.sln file. Did you run "configure"?'))
+      }
+      guessedSolution = files[0]
+      log.verbose('found first Solution file', guessedSolution)
+      doWhich()
+    })
+  }
+
+  /**
+   * Uses node-which to locate the msbuild / make executable.
+   */
+
+  function doWhich () {
+    // On Windows use msbuild provided by node-gyp configure
+    if (win) {
+      if (!config.variables.msbuild_path) {
+        return callback(new Error(
+          'MSBuild is not set, please run `node-gyp configure`.'))
+      }
+      command = config.variables.msbuild_path
+      log.verbose('using MSBuild:', command)
+      doBuild()
+      return
+    }
+    // First make sure we have the build command in the PATH
+    which(command, function (err, execPath) {
+      if (err) {
+        // Some other error or 'make' not found on Unix, report that to the user
+        callback(err)
+        return
+      }
+      log.verbose('`which` succeeded for `' + command + '`', execPath)
+      doBuild()
+    })
+  }
+
+  /**
+   * Actually spawn the process and compile the module.
+   */
+
+  function doBuild () {
+    // Enable Verbose build
+    var verbose = log.levels[log.level] <= log.levels.verbose
+    var j
+
+    if (!win && verbose) {
+      argv.push('V=1')
+    }
+
+    if (win && !verbose) {
+      argv.push('/clp:Verbosity=minimal')
+    }
+
+    if (win) {
+      // Turn off the Microsoft logo on Windows
+      argv.push('/nologo')
+    }
+
+    // Specify the build type, Release by default
+    if (win) {
+      // Convert .gypi config target_arch to MSBuild /Platform
+      // Since there are many ways to state '32-bit Intel', default to it.
+      // N.B. msbuild's Condition string equality tests are case-insensitive.
+      var archLower = arch.toLowerCase()
+      var p = archLower === 'x64' ? 'x64'
+        : (archLower === 'arm' ? 'ARM'
+          : (archLower === 'arm64' ? 'ARM64' : 'Win32'))
+      argv.push('/p:Configuration=' + buildType + ';Platform=' + p)
+      if (jobs) {
+        j = parseInt(jobs, 10)
+        if (!isNaN(j) && j > 0) {
+          argv.push('/m:' + j)
+        } else if (jobs.toUpperCase() === 'MAX') {
+          argv.push('/m:' + require('os').cpus().length)
+        }
+      }
+    } else {
+      argv.push('BUILDTYPE=' + buildType)
+      // Invoke the Makefile in the 'build' dir.
+      argv.push('-C')
+      argv.push('build')
+      if (jobs) {
+        j = parseInt(jobs, 10)
+        if (!isNaN(j) && j > 0) {
+          argv.push('--jobs')
+          argv.push(j)
+        } else if (jobs.toUpperCase() === 'MAX') {
+          argv.push('--jobs')
+          argv.push(require('os').cpus().length)
+        }
+      }
+    }
+
+    if (win) {
+      // did the user specify their own .sln file?
+      var hasSln = argv.some(function (arg) {
+        return path.extname(arg) === '.sln'
+      })
+      if (!hasSln) {
+        argv.unshift(gyp.opts.solution || guessedSolution)
+      }
+    }
+
+    var proc = gyp.spawn(command, argv)
+    proc.on('exit', onExit)
+  }
+
+  function onExit (code, signal) {
+    if (code !== 0) {
+      return callback(new Error('`' + command + '` failed with exit code: ' + code))
+    }
+    if (signal) {
+      return callback(new Error('`' + command + '` got signal: ' + signal))
+    }
+    callback()
+  }
+}
+
+module.exports = build
+module.exports.usage = 'Invokes `' + (win ? 'msbuild' : 'make') + '` and builds the module'
Index: node_modules/node-gyp/lib/clean.js
===================================================================
--- node_modules/node-gyp/lib/clean.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/node-gyp/lib/clean.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,15 @@
+'use strict'
+
+const rm = require('rimraf')
+const log = require('npmlog')
+
+function clean (gyp, argv, callback) {
+  // Remove the 'build' dir
+  var buildDir = 'build'
+
+  log.verbose('clean', 'removing "%s" directory', buildDir)
+  rm(buildDir, callback)
+}
+
+module.exports = clean
+module.exports.usage = 'Removes any generated build files and the "out" dir'
Index: node_modules/node-gyp/lib/configure.js
===================================================================
--- node_modules/node-gyp/lib/configure.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/node-gyp/lib/configure.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,294 @@
+'use strict'
+
+const fs = require('graceful-fs')
+const path = require('path')
+const log = require('npmlog')
+const os = require('os')
+const processRelease = require('./process-release')
+const win = process.platform === 'win32'
+const findNodeDirectory = require('./find-node-directory')
+const createConfigGypi = require('./create-config-gypi')
+const msgFormat = require('util').format
+var findPython = require('./find-python')
+if (win) {
+  var findVisualStudio = require('./find-visualstudio')
+}
+
+function configure (gyp, argv, callback) {
+  var python
+  var buildDir = path.resolve('build')
+  var configNames = ['config.gypi', 'common.gypi']
+  var configs = []
+  var nodeDir
+  var release = processRelease(argv, gyp, process.version, process.release)
+
+  findPython(gyp.opts.python, function (err, found) {
+    if (err) {
+      callback(err)
+    } else {
+      python = found
+      getNodeDir()
+    }
+  })
+
+  function getNodeDir () {
+    // 'python' should be set by now
+    process.env.PYTHON = python
+
+    if (gyp.opts.nodedir) {
+      // --nodedir was specified. use that for the dev files
+      nodeDir = gyp.opts.nodedir.replace(/^~/, os.homedir())
+
+      log.verbose('get node dir', 'compiling against specified --nodedir dev files: %s', nodeDir)
+      createBuildDir()
+    } else {
+      // if no --nodedir specified, ensure node dependencies are installed
+      if ('v' + release.version !== process.version) {
+        // if --target was given, then determine a target version to compile for
+        log.verbose('get node dir', 'compiling against --target node version: %s', release.version)
+      } else {
+        // if no --target was specified then use the current host node version
+        log.verbose('get node dir', 'no --target version specified, falling back to host node version: %s', release.version)
+      }
+
+      if (!release.semver) {
+        // could not parse the version string with semver
+        return callback(new Error('Invalid version number: ' + release.version))
+      }
+
+      // If the tarball option is set, always remove and reinstall the headers
+      // into devdir. Otherwise only install if they're not already there.
+      gyp.opts.ensure = !gyp.opts.tarball
+
+      gyp.commands.install([release.version], function (err) {
+        if (err) {
+          return callback(err)
+        }
+        log.verbose('get node dir', 'target node version installed:', release.versionDir)
+        nodeDir = path.resolve(gyp.devDir, release.versionDir)
+        createBuildDir()
+      })
+    }
+  }
+
+  function createBuildDir () {
+    log.verbose('build dir', 'attempting to create "build" dir: %s', buildDir)
+    fs.mkdir(buildDir, { recursive: true }, function (err, isNew) {
+      if (err) {
+        return callback(err)
+      }
+      log.verbose(
+        'build dir', '"build" dir needed to be created?', isNew ? 'Yes' : 'No'
+      )
+      if (win) {
+        findVisualStudio(release.semver, gyp.opts.msvs_version,
+          createConfigFile)
+      } else {
+        createConfigFile()
+      }
+    })
+  }
+
+  function createConfigFile (err, vsInfo) {
+    if (err) {
+      return callback(err)
+    }
+    if (process.platform === 'win32') {
+      process.env.GYP_MSVS_VERSION = Math.min(vsInfo.versionYear, 2015)
+      process.env.GYP_MSVS_OVERRIDE_PATH = vsInfo.path
+    }
+    createConfigGypi({ gyp, buildDir, nodeDir, vsInfo }).then(configPath => {
+      configs.push(configPath)
+      findConfigs()
+    }).catch(err => {
+      callback(err)
+    })
+  }
+
+  function findConfigs () {
+    var name = configNames.shift()
+    if (!name) {
+      return runGyp()
+    }
+    var fullPath = path.resolve(name)
+
+    log.verbose(name, 'checking for gypi file: %s', fullPath)
+    fs.stat(fullPath, function (err) {
+      if (err) {
+        if (err.code === 'ENOENT') {
+          findConfigs() // check next gypi filename
+        } else {
+          callback(err)
+        }
+      } else {
+        log.verbose(name, 'found gypi file')
+        configs.push(fullPath)
+        findConfigs()
+      }
+    })
+  }
+
+  function runGyp (err) {
+    if (err) {
+      return callback(err)
+    }
+
+    if (!~argv.indexOf('-f') && !~argv.indexOf('--format')) {
+      if (win) {
+        log.verbose('gyp', 'gyp format was not specified; forcing "msvs"')
+        // force the 'make' target for non-Windows
+        argv.push('-f', 'msvs')
+      } else {
+        log.verbose('gyp', 'gyp format was not specified; forcing "make"')
+        // force the 'make' target for non-Windows
+        argv.push('-f', 'make')
+      }
+    }
+
+    // include all the ".gypi" files that were found
+    configs.forEach(function (config) {
+      argv.push('-I', config)
+    })
+
+    // For AIX and z/OS we need to set up the path to the exports file
+    // which contains the symbols needed for linking.
+    var nodeExpFile
+    if (process.platform === 'aix' || process.platform === 'os390') {
+      var ext = process.platform === 'aix' ? 'exp' : 'x'
+      var nodeRootDir = findNodeDirectory()
+      var candidates
+
+      if (process.platform === 'aix') {
+        candidates = [
+          'include/node/node',
+          'out/Release/node',
+          'out/Debug/node',
+          'node'
+        ].map(function (file) {
+          return file + '.' + ext
+        })
+      } else {
+        candidates = [
+          'out/Release/obj.target/libnode',
+          'out/Debug/obj.target/libnode',
+          'lib/libnode'
+        ].map(function (file) {
+          return file + '.' + ext
+        })
+      }
+
+      var logprefix = 'find exports file'
+      nodeExpFile = findAccessibleSync(logprefix, nodeRootDir, candidates)
+      if (nodeExpFile !== undefined) {
+        log.verbose(logprefix, 'Found exports file: %s', nodeExpFile)
+      } else {
+        var msg = msgFormat('Could not find node.%s file in %s', ext, nodeRootDir)
+        log.error(logprefix, 'Could not find exports file')
+        return callback(new Error(msg))
+      }
+    }
+
+    // this logic ported from the old `gyp_addon` python file
+    var gypScript = path.resolve(__dirname, '..', 'gyp', 'gyp_main.py')
+    var addonGypi = path.resolve(__dirname, '..', 'addon.gypi')
+    var commonGypi = path.resolve(nodeDir, 'include/node/common.gypi')
+    fs.stat(commonGypi, function (err) {
+      if (err) {
+        commonGypi = path.resolve(nodeDir, 'common.gypi')
+      }
+
+      var outputDir = 'build'
+      if (win) {
+        // Windows expects an absolute path
+        outputDir = buildDir
+      }
+      var nodeGypDir = path.resolve(__dirname, '..')
+
+      var nodeLibFile = path.join(nodeDir,
+        !gyp.opts.nodedir ? '<(target_arch)' : '$(Configuration)',
+        release.name + '.lib')
+
+      argv.push('-I', addonGypi)
+      argv.push('-I', commonGypi)
+      argv.push('-Dlibrary=shared_library')
+      argv.push('-Dvisibility=default')
+      argv.push('-Dnode_root_dir=' + nodeDir)
+      if (process.platform === 'aix' || process.platform === 'os390') {
+        argv.push('-Dnode_exp_file=' + nodeExpFile)
+      }
+      argv.push('-Dnode_gyp_dir=' + nodeGypDir)
+
+      // Do this to keep Cygwin environments happy, else the unescaped '\' gets eaten up,
+      // resulting in bad paths, Ex c:parentFolderfolderanotherFolder instead of c:\parentFolder\folder\anotherFolder
+      if (win) {
+        nodeLibFile = nodeLibFile.replace(/\\/g, '\\\\')
+      }
+      argv.push('-Dnode_lib_file=' + nodeLibFile)
+      argv.push('-Dmodule_root_dir=' + process.cwd())
+      argv.push('-Dnode_engine=' +
+        (gyp.opts.node_engine || process.jsEngine || 'v8'))
+      argv.push('--depth=.')
+      argv.push('--no-parallel')
+
+      // tell gyp to write the Makefile/Solution files into output_dir
+      argv.push('--generator-output', outputDir)
+
+      // tell make to write its output into the same dir
+      argv.push('-Goutput_dir=.')
+
+      // enforce use of the "binding.gyp" file
+      argv.unshift('binding.gyp')
+
+      // execute `gyp` from the current target nodedir
+      argv.unshift(gypScript)
+
+      // make sure python uses files that came with this particular node package
+      var pypath = [path.join(__dirname, '..', 'gyp', 'pylib')]
+      if (process.env.PYTHONPATH) {
+        pypath.push(process.env.PYTHONPATH)
+      }
+      process.env.PYTHONPATH = pypath.join(win ? ';' : ':')
+
+      var cp = gyp.spawn(python, argv)
+      cp.on('exit', onCpExit)
+    })
+  }
+
+  function onCpExit (code) {
+    if (code !== 0) {
+      callback(new Error('`gyp` failed with exit code: ' + code))
+    } else {
+      // we're done
+      callback()
+    }
+  }
+}
+
+/**
+ * Returns the first file or directory from an array of candidates that is
+ * readable by the current user, or undefined if none of the candidates are
+ * readable.
+ */
+function findAccessibleSync (logprefix, dir, candidates) {
+  for (var next = 0; next < candidates.length; next++) {
+    var candidate = path.resolve(dir, candidates[next])
+    try {
+      var fd = fs.openSync(candidate, 'r')
+    } catch (e) {
+      // this candidate was not found or not readable, do nothing
+      log.silly(logprefix, 'Could not open %s: %s', candidate, e.message)
+      continue
+    }
+    fs.closeSync(fd)
+    log.silly(logprefix, 'Found readable %s', candidate)
+    return candidate
+  }
+
+  return undefined
+}
+
+module.exports = configure
+module.exports.test = {
+  findAccessibleSync: findAccessibleSync
+}
+module.exports.usage = 'Generates ' + (win ? 'MSVC project files' : 'a Makefile') + ' for the current module'
Index: node_modules/node-gyp/lib/create-config-gypi.js
===================================================================
--- node_modules/node-gyp/lib/create-config-gypi.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/node-gyp/lib/create-config-gypi.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,146 @@
+'use strict'
+
+const fs = require('graceful-fs')
+const log = require('npmlog')
+const path = require('path')
+
+function parseConfigGypi (config) {
+  // translated from tools/js2c.py of Node.js
+  // 1. string comments
+  config = config.replace(/#.*/g, '')
+  // 2. join multiline strings
+  config = config.replace(/'$\s+'/mg, '')
+  // 3. normalize string literals from ' into "
+  config = config.replace(/'/g, '"')
+  return JSON.parse(config)
+}
+
+async function getBaseConfigGypi ({ gyp, nodeDir }) {
+  // try reading $nodeDir/include/node/config.gypi first when:
+  // 1. --dist-url or --nodedir is specified
+  // 2. and --force-process-config is not specified
+  const shouldReadConfigGypi = (gyp.opts.nodedir || gyp.opts['dist-url']) && !gyp.opts['force-process-config']
+  if (shouldReadConfigGypi && nodeDir) {
+    try {
+      const baseConfigGypiPath = path.resolve(nodeDir, 'include/node/config.gypi')
+      const baseConfigGypi = await fs.promises.readFile(baseConfigGypiPath)
+      return parseConfigGypi(baseConfigGypi.toString())
+    } catch (err) {
+      log.warn('read config.gypi', err.message)
+    }
+  }
+
+  // fallback to process.config if it is invalid
+  return JSON.parse(JSON.stringify(process.config))
+}
+
+async function getCurrentConfigGypi ({ gyp, nodeDir, vsInfo }) {
+  const config = await getBaseConfigGypi({ gyp, nodeDir })
+  if (!config.target_defaults) {
+    config.target_defaults = {}
+  }
+  if (!config.variables) {
+    config.variables = {}
+  }
+
+  const defaults = config.target_defaults
+  const variables = config.variables
+
+  // don't inherit the "defaults" from the base config.gypi.
+  // doing so could cause problems in cases where the `node` executable was
+  // compiled on a different machine (with different lib/include paths) than
+  // the machine where the addon is being built to
+  defaults.cflags = []
+  defaults.defines = []
+  defaults.include_dirs = []
+  defaults.libraries = []
+
+  // set the default_configuration prop
+  if ('debug' in gyp.opts) {
+    defaults.default_configuration = gyp.opts.debug ? 'Debug' : 'Release'
+  }
+
+  if (!defaults.default_configuration) {
+    defaults.default_configuration = 'Release'
+  }
+
+  // set the target_arch variable
+  variables.target_arch = gyp.opts.arch || process.arch || 'ia32'
+  if (variables.target_arch === 'arm64') {
+    defaults.msvs_configuration_platform = 'ARM64'
+    defaults.xcode_configuration_platform = 'arm64'
+  }
+
+  // set the node development directory
+  variables.nodedir = nodeDir
+
+  // disable -T "thin" static archives by default
+  variables.standalone_static_library = gyp.opts.thin ? 0 : 1
+
+  if (process.platform === 'win32') {
+    defaults.msbuild_toolset = vsInfo.toolset
+    if (vsInfo.sdk) {
+      defaults.msvs_windows_target_platform_version = vsInfo.sdk
+    }
+    if (variables.target_arch === 'arm64') {
+      if (vsInfo.versionMajor > 15 ||
+          (vsInfo.versionMajor === 15 && vsInfo.versionMajor >= 9)) {
+        defaults.msvs_enable_marmasm = 1
+      } else {
+        log.warn('Compiling ARM64 assembly is only available in\n' +
+          'Visual Studio 2017 version 15.9 and above')
+      }
+    }
+    variables.msbuild_path = vsInfo.msBuild
+  }
+
+  // loop through the rest of the opts and add the unknown ones as variables.
+  // this allows for module-specific configure flags like:
+  //
+  //   $ node-gyp configure --shared-libxml2
+  Object.keys(gyp.opts).forEach(function (opt) {
+    if (opt === 'argv') {
+      return
+    }
+    if (opt in gyp.configDefs) {
+      return
+    }
+    variables[opt.replace(/-/g, '_')] = gyp.opts[opt]
+  })
+
+  return config
+}
+
+async function createConfigGypi ({ gyp, buildDir, nodeDir, vsInfo }) {
+  const configFilename = 'config.gypi'
+  const configPath = path.resolve(buildDir, configFilename)
+
+  log.verbose('build/' + configFilename, 'creating config file')
+
+  const config = await getCurrentConfigGypi({ gyp, nodeDir, vsInfo })
+
+  // ensures that any boolean values in config.gypi get stringified
+  function boolsToString (k, v) {
+    if (typeof v === 'boolean') {
+      return String(v)
+    }
+    return v
+  }
+
+  log.silly('build/' + configFilename, config)
+
+  // now write out the config.gypi file to the build/ dir
+  const prefix = '# Do not edit. File was generated by node-gyp\'s "configure" step'
+
+  const json = JSON.stringify(config, boolsToString, 2)
+  log.verbose('build/' + configFilename, 'writing out config file: %s', configPath)
+  await fs.promises.writeFile(configPath, [prefix, json, ''].join('\n'))
+
+  return configPath
+}
+
+module.exports = createConfigGypi
+module.exports.test = {
+  parseConfigGypi: parseConfigGypi,
+  getCurrentConfigGypi: getCurrentConfigGypi
+}
Index: node_modules/node-gyp/lib/find-node-directory.js
===================================================================
--- node_modules/node-gyp/lib/find-node-directory.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/node-gyp/lib/find-node-directory.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,63 @@
+'use strict'
+
+const path = require('path')
+const log = require('npmlog')
+
+function findNodeDirectory (scriptLocation, processObj) {
+  // set dirname and process if not passed in
+  // this facilitates regression tests
+  if (scriptLocation === undefined) {
+    scriptLocation = __dirname
+  }
+  if (processObj === undefined) {
+    processObj = process
+  }
+
+  // Have a look to see what is above us, to try and work out where we are
+  var npmParentDirectory = path.join(scriptLocation, '../../../..')
+  log.verbose('node-gyp root', 'npm_parent_directory is ' +
+              path.basename(npmParentDirectory))
+  var nodeRootDir = ''
+
+  log.verbose('node-gyp root', 'Finding node root directory')
+  if (path.basename(npmParentDirectory) === 'deps') {
+    // We are in a build directory where this script lives in
+    // deps/npm/node_modules/node-gyp/lib
+    nodeRootDir = path.join(npmParentDirectory, '..')
+    log.verbose('node-gyp root', 'in build directory, root = ' +
+                nodeRootDir)
+  } else if (path.basename(npmParentDirectory) === 'node_modules') {
+    // We are in a node install directory where this script lives in
+    // lib/node_modules/npm/node_modules/node-gyp/lib or
+    // node_modules/npm/node_modules/node-gyp/lib depending on the
+    // platform
+    if (processObj.platform === 'win32') {
+      nodeRootDir = path.join(npmParentDirectory, '..')
+    } else {
+      nodeRootDir = path.join(npmParentDirectory, '../..')
+    }
+    log.verbose('node-gyp root', 'in install directory, root = ' +
+                nodeRootDir)
+  } else {
+    // We don't know where we are, try working it out from the location
+    // of the node binary
+    var nodeDir = path.dirname(processObj.execPath)
+    var directoryUp = path.basename(nodeDir)
+    if (directoryUp === 'bin') {
+      nodeRootDir = path.join(nodeDir, '..')
+    } else if (directoryUp === 'Release' || directoryUp === 'Debug') {
+      // If we are a recently built node, and the directory structure
+      // is that of a repository. If we are on Windows then we only need
+      // to go one level up, everything else, two
+      if (processObj.platform === 'win32') {
+        nodeRootDir = path.join(nodeDir, '..')
+      } else {
+        nodeRootDir = path.join(nodeDir, '../..')
+      }
+    }
+    // Else return the default blank, "".
+  }
+  return nodeRootDir
+}
+
+module.exports = findNodeDirectory
Index: node_modules/node-gyp/lib/find-python.js
===================================================================
--- node_modules/node-gyp/lib/find-python.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/node-gyp/lib/find-python.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,344 @@
+'use strict'
+
+const log = require('npmlog')
+const semver = require('semver')
+const cp = require('child_process')
+const extend = require('util')._extend // eslint-disable-line
+const win = process.platform === 'win32'
+const logWithPrefix = require('./util').logWithPrefix
+
+const systemDrive = process.env.SystemDrive || 'C:'
+const username = process.env.USERNAME || process.env.USER || getOsUserInfo()
+const localAppData = process.env.LOCALAPPDATA || `${systemDrive}\\${username}\\AppData\\Local`
+const foundLocalAppData = process.env.LOCALAPPDATA || username
+const programFiles = process.env.ProgramW6432 || process.env.ProgramFiles || `${systemDrive}\\Program Files`
+const programFilesX86 = process.env['ProgramFiles(x86)'] || `${programFiles} (x86)`
+
+const winDefaultLocationsArray = []
+for (const majorMinor of ['39', '38', '37', '36']) {
+  if (foundLocalAppData) {
+    winDefaultLocationsArray.push(
+      `${localAppData}\\Programs\\Python\\Python${majorMinor}\\python.exe`,
+      `${programFiles}\\Python${majorMinor}\\python.exe`,
+      `${localAppData}\\Programs\\Python\\Python${majorMinor}-32\\python.exe`,
+      `${programFiles}\\Python${majorMinor}-32\\python.exe`,
+      `${programFilesX86}\\Python${majorMinor}-32\\python.exe`
+    )
+  } else {
+    winDefaultLocationsArray.push(
+      `${programFiles}\\Python${majorMinor}\\python.exe`,
+      `${programFiles}\\Python${majorMinor}-32\\python.exe`,
+      `${programFilesX86}\\Python${majorMinor}-32\\python.exe`
+    )
+  }
+}
+
+function getOsUserInfo () {
+  try {
+    return require('os').userInfo().username
+  } catch (e) {}
+}
+
+function PythonFinder (configPython, callback) {
+  this.callback = callback
+  this.configPython = configPython
+  this.errorLog = []
+}
+
+PythonFinder.prototype = {
+  log: logWithPrefix(log, 'find Python'),
+  argsExecutable: ['-c', 'import sys; print(sys.executable);'],
+  argsVersion: ['-c', 'import sys; print("%s.%s.%s" % sys.version_info[:3]);'],
+  semverRange: '>=3.6.0',
+
+  // These can be overridden for testing:
+  execFile: cp.execFile,
+  env: process.env,
+  win: win,
+  pyLauncher: 'py.exe',
+  winDefaultLocations: winDefaultLocationsArray,
+
+  // Logs a message at verbose level, but also saves it to be displayed later
+  // at error level if an error occurs. This should help diagnose the problem.
+  addLog: function addLog (message) {
+    this.log.verbose(message)
+    this.errorLog.push(message)
+  },
+
+  // Find Python by trying a sequence of possibilities.
+  // Ignore errors, keep trying until Python is found.
+  findPython: function findPython () {
+    const SKIP = 0; const FAIL = 1
+    var toCheck = getChecks.apply(this)
+
+    function getChecks () {
+      if (this.env.NODE_GYP_FORCE_PYTHON) {
+        return [{
+          before: () => {
+            this.addLog(
+              'checking Python explicitly set from NODE_GYP_FORCE_PYTHON')
+            this.addLog('- process.env.NODE_GYP_FORCE_PYTHON is ' +
+              `"${this.env.NODE_GYP_FORCE_PYTHON}"`)
+          },
+          check: this.checkCommand,
+          arg: this.env.NODE_GYP_FORCE_PYTHON
+        }]
+      }
+
+      var checks = [
+        {
+          before: () => {
+            if (!this.configPython) {
+              this.addLog(
+                'Python is not set from command line or npm configuration')
+              return SKIP
+            }
+            this.addLog('checking Python explicitly set from command line or ' +
+              'npm configuration')
+            this.addLog('- "--python=" or "npm config get python" is ' +
+              `"${this.configPython}"`)
+          },
+          check: this.checkCommand,
+          arg: this.configPython
+        },
+        {
+          before: () => {
+            if (!this.env.PYTHON) {
+              this.addLog('Python is not set from environment variable ' +
+                'PYTHON')
+              return SKIP
+            }
+            this.addLog('checking Python explicitly set from environment ' +
+              'variable PYTHON')
+            this.addLog(`- process.env.PYTHON is "${this.env.PYTHON}"`)
+          },
+          check: this.checkCommand,
+          arg: this.env.PYTHON
+        },
+        {
+          before: () => { this.addLog('checking if "python3" can be used') },
+          check: this.checkCommand,
+          arg: 'python3'
+        },
+        {
+          before: () => { this.addLog('checking if "python" can be used') },
+          check: this.checkCommand,
+          arg: 'python'
+        }
+      ]
+
+      if (this.win) {
+        for (var i = 0; i < this.winDefaultLocations.length; ++i) {
+          const location = this.winDefaultLocations[i]
+          checks.push({
+            before: () => {
+              this.addLog('checking if Python is ' +
+                `${location}`)
+            },
+            check: this.checkExecPath,
+            arg: location
+          })
+        }
+        checks.push({
+          before: () => {
+            this.addLog(
+              'checking if the py launcher can be used to find Python 3')
+          },
+          check: this.checkPyLauncher
+        })
+      }
+
+      return checks
+    }
+
+    function runChecks (err) {
+      this.log.silly('runChecks: err = %j', (err && err.stack) || err)
+
+      const check = toCheck.shift()
+      if (!check) {
+        return this.fail()
+      }
+
+      const before = check.before.apply(this)
+      if (before === SKIP) {
+        return runChecks.apply(this)
+      }
+      if (before === FAIL) {
+        return this.fail()
+      }
+
+      const args = [runChecks.bind(this)]
+      if (check.arg) {
+        args.unshift(check.arg)
+      }
+      check.check.apply(this, args)
+    }
+
+    runChecks.apply(this)
+  },
+
+  // Check if command is a valid Python to use.
+  // Will exit the Python finder on success.
+  // If on Windows, run in a CMD shell to support BAT/CMD launchers.
+  checkCommand: function checkCommand (command, errorCallback) {
+    var exec = command
+    var args = this.argsExecutable
+    var shell = false
+    if (this.win) {
+      // Arguments have to be manually quoted
+      exec = `"${exec}"`
+      args = args.map(a => `"${a}"`)
+      shell = true
+    }
+
+    this.log.verbose(`- executing "${command}" to get executable path`)
+    this.run(exec, args, shell, function (err, execPath) {
+      // Possible outcomes:
+      // - Error: not in PATH, not executable or execution fails
+      // - Gibberish: the next command to check version will fail
+      // - Absolute path to executable
+      if (err) {
+        this.addLog(`- "${command}" is not in PATH or produced an error`)
+        return errorCallback(err)
+      }
+      this.addLog(`- executable path is "${execPath}"`)
+      this.checkExecPath(execPath, errorCallback)
+    }.bind(this))
+  },
+
+  // Check if the py launcher can find a valid Python to use.
+  // Will exit the Python finder on success.
+  // Distributions of Python on Windows by default install with the "py.exe"
+  // Python launcher which is more likely to exist than the Python executable
+  // being in the $PATH.
+  // Because the Python launcher supports Python 2 and Python 3, we should
+  // explicitly request a Python 3 version. This is done by supplying "-3" as
+  // the first command line argument. Since "py.exe -3" would be an invalid
+  // executable for "execFile", we have to use the launcher to figure out
+  // where the actual "python.exe" executable is located.
+  checkPyLauncher: function checkPyLauncher (errorCallback) {
+    this.log.verbose(
+      `- executing "${this.pyLauncher}" to get Python 3 executable path`)
+    this.run(this.pyLauncher, ['-3', ...this.argsExecutable], false,
+      function (err, execPath) {
+      // Possible outcomes: same as checkCommand
+        if (err) {
+          this.addLog(
+            `- "${this.pyLauncher}" is not in PATH or produced an error`)
+          return errorCallback(err)
+        }
+        this.addLog(`- executable path is "${execPath}"`)
+        this.checkExecPath(execPath, errorCallback)
+      }.bind(this))
+  },
+
+  // Check if a Python executable is the correct version to use.
+  // Will exit the Python finder on success.
+  checkExecPath: function checkExecPath (execPath, errorCallback) {
+    this.log.verbose(`- executing "${execPath}" to get version`)
+    this.run(execPath, this.argsVersion, false, function (err, version) {
+      // Possible outcomes:
+      // - Error: executable can not be run (likely meaning the command wasn't
+      //   a Python executable and the previous command produced gibberish)
+      // - Gibberish: somehow the last command produced an executable path,
+      //   this will fail when verifying the version
+      // - Version of the Python executable
+      if (err) {
+        this.addLog(`- "${execPath}" could not be run`)
+        return errorCallback(err)
+      }
+      this.addLog(`- version is "${version}"`)
+
+      const range = new semver.Range(this.semverRange)
+      var valid = false
+      try {
+        valid = range.test(version)
+      } catch (err) {
+        this.log.silly('range.test() threw:\n%s', err.stack)
+        this.addLog(`- "${execPath}" does not have a valid version`)
+        this.addLog('- is it a Python executable?')
+        return errorCallback(err)
+      }
+
+      if (!valid) {
+        this.addLog(`- version is ${version} - should be ${this.semverRange}`)
+        this.addLog('- THIS VERSION OF PYTHON IS NOT SUPPORTED')
+        return errorCallback(new Error(
+          `Found unsupported Python version ${version}`))
+      }
+      this.succeed(execPath, version)
+    }.bind(this))
+  },
+
+  // Run an executable or shell command, trimming the output.
+  run: function run (exec, args, shell, callback) {
+    var env = extend({}, this.env)
+    env.TERM = 'dumb'
+    const opts = { env: env, shell: shell }
+
+    this.log.silly('execFile: exec = %j', exec)
+    this.log.silly('execFile: args = %j', args)
+    this.log.silly('execFile: opts = %j', opts)
+    try {
+      this.execFile(exec, args, opts, execFileCallback.bind(this))
+    } catch (err) {
+      this.log.silly('execFile: threw:\n%s', err.stack)
+      return callback(err)
+    }
+
+    function execFileCallback (err, stdout, stderr) {
+      this.log.silly('execFile result: err = %j', (err && err.stack) || err)
+      this.log.silly('execFile result: stdout = %j', stdout)
+      this.log.silly('execFile result: stderr = %j', stderr)
+      if (err) {
+        return callback(err)
+      }
+      const execPath = stdout.trim()
+      callback(null, execPath)
+    }
+  },
+
+  succeed: function succeed (execPath, version) {
+    this.log.info(`using Python version ${version} found at "${execPath}"`)
+    process.nextTick(this.callback.bind(null, null, execPath))
+  },
+
+  fail: function fail () {
+    const errorLog = this.errorLog.join('\n')
+
+    const pathExample = this.win ? 'C:\\Path\\To\\python.exe'
+      : '/path/to/pythonexecutable'
+    // For Windows 80 col console, use up to the column before the one marked
+    // with X (total 79 chars including logger prefix, 58 chars usable here):
+    //                                                           X
+    const info = [
+      '**********************************************************',
+      'You need to install the latest version of Python.',
+      'Node-gyp should be able to find and use Python. If not,',
+      'you can try one of the following options:',
+      `- Use the switch --python="${pathExample}"`,
+      '  (accepted by both node-gyp and npm)',
+      '- Set the environment variable PYTHON',
+      '- Set the npm configuration variable python:',
+      `  npm config set python "${pathExample}"`,
+      'For more information consult the documentation at:',
+      'https://github.com/nodejs/node-gyp#installation',
+      '**********************************************************'
+    ].join('\n')
+
+    this.log.error(`\n${errorLog}\n\n${info}\n`)
+    process.nextTick(this.callback.bind(null, new Error(
+      'Could not find any Python installation to use')))
+  }
+}
+
+function findPython (configPython, callback) {
+  var finder = new PythonFinder(configPython, callback)
+  finder.findPython()
+}
+
+module.exports = findPython
+module.exports.test = {
+  PythonFinder: PythonFinder,
+  findPython: findPython
+}
Index: node_modules/node-gyp/lib/find-visualstudio.js
===================================================================
--- node_modules/node-gyp/lib/find-visualstudio.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/node-gyp/lib/find-visualstudio.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,446 @@
+'use strict'
+
+const log = require('npmlog')
+const execFile = require('child_process').execFile
+const fs = require('fs')
+const path = require('path').win32
+const logWithPrefix = require('./util').logWithPrefix
+const regSearchKeys = require('./util').regSearchKeys
+
+function findVisualStudio (nodeSemver, configMsvsVersion, callback) {
+  const finder = new VisualStudioFinder(nodeSemver, configMsvsVersion,
+    callback)
+  finder.findVisualStudio()
+}
+
+function VisualStudioFinder (nodeSemver, configMsvsVersion, callback) {
+  this.nodeSemver = nodeSemver
+  this.configMsvsVersion = configMsvsVersion
+  this.callback = callback
+  this.errorLog = []
+  this.validVersions = []
+}
+
+VisualStudioFinder.prototype = {
+  log: logWithPrefix(log, 'find VS'),
+
+  regSearchKeys: regSearchKeys,
+
+  // Logs a message at verbose level, but also saves it to be displayed later
+  // at error level if an error occurs. This should help diagnose the problem.
+  addLog: function addLog (message) {
+    this.log.verbose(message)
+    this.errorLog.push(message)
+  },
+
+  findVisualStudio: function findVisualStudio () {
+    this.configVersionYear = null
+    this.configPath = null
+    if (this.configMsvsVersion) {
+      this.addLog('msvs_version was set from command line or npm config')
+      if (this.configMsvsVersion.match(/^\d{4}$/)) {
+        this.configVersionYear = parseInt(this.configMsvsVersion, 10)
+        this.addLog(
+          `- looking for Visual Studio version ${this.configVersionYear}`)
+      } else {
+        this.configPath = path.resolve(this.configMsvsVersion)
+        this.addLog(
+          `- looking for Visual Studio installed in "${this.configPath}"`)
+      }
+    } else {
+      this.addLog('msvs_version not set from command line or npm config')
+    }
+
+    if (process.env.VCINSTALLDIR) {
+      this.envVcInstallDir =
+        path.resolve(process.env.VCINSTALLDIR, '..')
+      this.addLog('running in VS Command Prompt, installation path is:\n' +
+        `"${this.envVcInstallDir}"\n- will only use this version`)
+    } else {
+      this.addLog('VCINSTALLDIR not set, not running in VS Command Prompt')
+    }
+
+    this.findVisualStudio2017OrNewer((info) => {
+      if (info) {
+        return this.succeed(info)
+      }
+      this.findVisualStudio2015((info) => {
+        if (info) {
+          return this.succeed(info)
+        }
+        this.findVisualStudio2013((info) => {
+          if (info) {
+            return this.succeed(info)
+          }
+          this.fail()
+        })
+      })
+    })
+  },
+
+  succeed: function succeed (info) {
+    this.log.info(`using VS${info.versionYear} (${info.version}) found at:` +
+                  `\n"${info.path}"` +
+                  '\nrun with --verbose for detailed information')
+    process.nextTick(this.callback.bind(null, null, info))
+  },
+
+  fail: function fail () {
+    if (this.configMsvsVersion && this.envVcInstallDir) {
+      this.errorLog.push(
+        'msvs_version does not match this VS Command Prompt or the',
+        'installation cannot be used.')
+    } else if (this.configMsvsVersion) {
+      // If msvs_version was specified but finding VS failed, print what would
+      // have been accepted
+      this.errorLog.push('')
+      if (this.validVersions) {
+        this.errorLog.push('valid versions for msvs_version:')
+        this.validVersions.forEach((version) => {
+          this.errorLog.push(`- "${version}"`)
+        })
+      } else {
+        this.errorLog.push('no valid versions for msvs_version were found')
+      }
+    }
+
+    const errorLog = this.errorLog.join('\n')
+
+    // For Windows 80 col console, use up to the column before the one marked
+    // with X (total 79 chars including logger prefix, 62 chars usable here):
+    //                                                               X
+    const infoLog = [
+      '**************************************************************',
+      'You need to install the latest version of Visual Studio',
+      'including the "Desktop development with C++" workload.',
+      'For more information consult the documentation at:',
+      'https://github.com/nodejs/node-gyp#on-windows',
+      '**************************************************************'
+    ].join('\n')
+
+    this.log.error(`\n${errorLog}\n\n${infoLog}\n`)
+    process.nextTick(this.callback.bind(null, new Error(
+      'Could not find any Visual Studio installation to use')))
+  },
+
+  // Invoke the PowerShell script to get information about Visual Studio 2017
+  // or newer installations
+  findVisualStudio2017OrNewer: function findVisualStudio2017OrNewer (cb) {
+    var ps = path.join(process.env.SystemRoot, 'System32',
+      'WindowsPowerShell', 'v1.0', 'powershell.exe')
+    var csFile = path.join(__dirname, 'Find-VisualStudio.cs')
+    var psArgs = [
+      '-ExecutionPolicy',
+      'Unrestricted',
+      '-NoProfile',
+      '-Command',
+      '&{Add-Type -Path \'' + csFile + '\';' + '[VisualStudioConfiguration.Main]::PrintJson()}'
+    ]
+
+    this.log.silly('Running', ps, psArgs)
+    var child = execFile(ps, psArgs, { encoding: 'utf8' },
+      (err, stdout, stderr) => {
+        this.parseData(err, stdout, stderr, cb)
+      })
+    child.stdin.end()
+  },
+
+  // Parse the output of the PowerShell script and look for an installation
+  // of Visual Studio 2017 or newer to use
+  parseData: function parseData (err, stdout, stderr, cb) {
+    this.log.silly('PS stderr = %j', stderr)
+
+    const failPowershell = () => {
+      this.addLog(
+        'could not use PowerShell to find Visual Studio 2017 or newer, try re-running with \'--loglevel silly\' for more details')
+      cb(null)
+    }
+
+    if (err) {
+      this.log.silly('PS err = %j', err && (err.stack || err))
+      return failPowershell()
+    }
+
+    var vsInfo
+    try {
+      vsInfo = JSON.parse(stdout)
+    } catch (e) {
+      this.log.silly('PS stdout = %j', stdout)
+      this.log.silly(e)
+      return failPowershell()
+    }
+
+    if (!Array.isArray(vsInfo)) {
+      this.log.silly('PS stdout = %j', stdout)
+      return failPowershell()
+    }
+
+    vsInfo = vsInfo.map((info) => {
+      this.log.silly(`processing installation: "${info.path}"`)
+      info.path = path.resolve(info.path)
+      var ret = this.getVersionInfo(info)
+      ret.path = info.path
+      ret.msBuild = this.getMSBuild(info, ret.versionYear)
+      ret.toolset = this.getToolset(info, ret.versionYear)
+      ret.sdk = this.getSDK(info)
+      return ret
+    })
+    this.log.silly('vsInfo:', vsInfo)
+
+    // Remove future versions or errors parsing version number
+    vsInfo = vsInfo.filter((info) => {
+      if (info.versionYear) {
+        return true
+      }
+      this.addLog(`unknown version "${info.version}" found at "${info.path}"`)
+      return false
+    })
+
+    // Sort to place newer versions first
+    vsInfo.sort((a, b) => b.versionYear - a.versionYear)
+
+    for (var i = 0; i < vsInfo.length; ++i) {
+      const info = vsInfo[i]
+      this.addLog(`checking VS${info.versionYear} (${info.version}) found ` +
+                  `at:\n"${info.path}"`)
+
+      if (info.msBuild) {
+        this.addLog('- found "Visual Studio C++ core features"')
+      } else {
+        this.addLog('- "Visual Studio C++ core features" missing')
+        continue
+      }
+
+      if (info.toolset) {
+        this.addLog(`- found VC++ toolset: ${info.toolset}`)
+      } else {
+        this.addLog('- missing any VC++ toolset')
+        continue
+      }
+
+      if (info.sdk) {
+        this.addLog(`- found Windows SDK: ${info.sdk}`)
+      } else {
+        this.addLog('- missing any Windows SDK')
+        continue
+      }
+
+      if (!this.checkConfigVersion(info.versionYear, info.path)) {
+        continue
+      }
+
+      return cb(info)
+    }
+
+    this.addLog(
+      'could not find a version of Visual Studio 2017 or newer to use')
+    cb(null)
+  },
+
+  // Helper - process version information
+  getVersionInfo: function getVersionInfo (info) {
+    const match = /^(\d+)\.(\d+)\..*/.exec(info.version)
+    if (!match) {
+      this.log.silly('- failed to parse version:', info.version)
+      return {}
+    }
+    this.log.silly('- version match = %j', match)
+    var ret = {
+      version: info.version,
+      versionMajor: parseInt(match[1], 10),
+      versionMinor: parseInt(match[2], 10)
+    }
+    if (ret.versionMajor === 15) {
+      ret.versionYear = 2017
+      return ret
+    }
+    if (ret.versionMajor === 16) {
+      ret.versionYear = 2019
+      return ret
+    }
+    if (ret.versionMajor === 17) {
+      ret.versionYear = 2022
+      return ret
+    }
+    this.log.silly('- unsupported version:', ret.versionMajor)
+    return {}
+  },
+
+  // Helper - process MSBuild information
+  getMSBuild: function getMSBuild (info, versionYear) {
+    const pkg = 'Microsoft.VisualStudio.VC.MSBuild.Base'
+    const msbuildPath = path.join(info.path, 'MSBuild', 'Current', 'Bin', 'MSBuild.exe')
+    if (info.packages.indexOf(pkg) !== -1) {
+      this.log.silly('- found VC.MSBuild.Base')
+      if (versionYear === 2017) {
+        return path.join(info.path, 'MSBuild', '15.0', 'Bin', 'MSBuild.exe')
+      }
+      if (versionYear === 2019) {
+        return msbuildPath
+      }
+    }
+    // visual studio 2022 don't has msbuild pkg
+    if (fs.existsSync(msbuildPath)) {
+      return msbuildPath
+    }
+    return null
+  },
+
+  // Helper - process toolset information
+  getToolset: function getToolset (info, versionYear) {
+    const pkg = 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64'
+    const express = 'Microsoft.VisualStudio.WDExpress'
+
+    if (info.packages.indexOf(pkg) !== -1) {
+      this.log.silly('- found VC.Tools.x86.x64')
+    } else if (info.packages.indexOf(express) !== -1) {
+      this.log.silly('- found Visual Studio Express (looking for toolset)')
+    } else {
+      return null
+    }
+
+    if (versionYear === 2017) {
+      return 'v141'
+    } else if (versionYear === 2019) {
+      return 'v142'
+    } else if (versionYear === 2022) {
+      return 'v143'
+    }
+    this.log.silly('- invalid versionYear:', versionYear)
+    return null
+  },
+
+  // Helper - process Windows SDK information
+  getSDK: function getSDK (info) {
+    const win8SDK = 'Microsoft.VisualStudio.Component.Windows81SDK'
+    const win10SDKPrefix = 'Microsoft.VisualStudio.Component.Windows10SDK.'
+
+    var Win10SDKVer = 0
+    info.packages.forEach((pkg) => {
+      if (!pkg.startsWith(win10SDKPrefix)) {
+        return
+      }
+      const parts = pkg.split('.')
+      if (parts.length > 5 && parts[5] !== 'Desktop') {
+        this.log.silly('- ignoring non-Desktop Win10SDK:', pkg)
+        return
+      }
+      const foundSdkVer = parseInt(parts[4], 10)
+      if (isNaN(foundSdkVer)) {
+        // Microsoft.VisualStudio.Component.Windows10SDK.IpOverUsb
+        this.log.silly('- failed to parse Win10SDK number:', pkg)
+        return
+      }
+      this.log.silly('- found Win10SDK:', foundSdkVer)
+      Win10SDKVer = Math.max(Win10SDKVer, foundSdkVer)
+    })
+
+    if (Win10SDKVer !== 0) {
+      return `10.0.${Win10SDKVer}.0`
+    } else if (info.packages.indexOf(win8SDK) !== -1) {
+      this.log.silly('- found Win8SDK')
+      return '8.1'
+    }
+    return null
+  },
+
+  // Find an installation of Visual Studio 2015 to use
+  findVisualStudio2015: function findVisualStudio2015 (cb) {
+    return this.findOldVS({
+      version: '14.0',
+      versionMajor: 14,
+      versionMinor: 0,
+      versionYear: 2015,
+      toolset: 'v140'
+    }, cb)
+  },
+
+  // Find an installation of Visual Studio 2013 to use
+  findVisualStudio2013: function findVisualStudio2013 (cb) {
+    if (this.nodeSemver.major >= 9) {
+      this.addLog(
+        'not looking for VS2013 as it is only supported up to Node.js 8')
+      return cb(null)
+    }
+    return this.findOldVS({
+      version: '12.0',
+      versionMajor: 12,
+      versionMinor: 0,
+      versionYear: 2013,
+      toolset: 'v120'
+    }, cb)
+  },
+
+  // Helper - common code for VS2013 and VS2015
+  findOldVS: function findOldVS (info, cb) {
+    const regVC7 = ['HKLM\\Software\\Microsoft\\VisualStudio\\SxS\\VC7',
+      'HKLM\\Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7']
+    const regMSBuild = 'HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions'
+
+    this.addLog(`looking for Visual Studio ${info.versionYear}`)
+    this.regSearchKeys(regVC7, info.version, [], (err, res) => {
+      if (err) {
+        this.addLog('- not found')
+        return cb(null)
+      }
+
+      const vsPath = path.resolve(res, '..')
+      this.addLog(`- found in "${vsPath}"`)
+
+      const msBuildRegOpts = process.arch === 'ia32' ? [] : ['/reg:32']
+      this.regSearchKeys([`${regMSBuild}\\${info.version}`],
+        'MSBuildToolsPath', msBuildRegOpts, (err, res) => {
+          if (err) {
+            this.addLog(
+              '- could not find MSBuild in registry for this version')
+            return cb(null)
+          }
+
+          const msBuild = path.join(res, 'MSBuild.exe')
+          this.addLog(`- MSBuild in "${msBuild}"`)
+
+          if (!this.checkConfigVersion(info.versionYear, vsPath)) {
+            return cb(null)
+          }
+
+          info.path = vsPath
+          info.msBuild = msBuild
+          info.sdk = null
+          cb(info)
+        })
+    })
+  },
+
+  // After finding a usable version of Visual Studio:
+  // - add it to validVersions to be displayed at the end if a specific
+  //   version was requested and not found;
+  // - check if this is the version that was requested.
+  // - check if this matches the Visual Studio Command Prompt
+  checkConfigVersion: function checkConfigVersion (versionYear, vsPath) {
+    this.validVersions.push(versionYear)
+    this.validVersions.push(vsPath)
+
+    if (this.configVersionYear && this.configVersionYear !== versionYear) {
+      this.addLog('- msvs_version does not match this version')
+      return false
+    }
+    if (this.configPath &&
+        path.relative(this.configPath, vsPath) !== '') {
+      this.addLog('- msvs_version does not point to this installation')
+      return false
+    }
+    if (this.envVcInstallDir &&
+        path.relative(this.envVcInstallDir, vsPath) !== '') {
+      this.addLog('- does not match this Visual Studio Command Prompt')
+      return false
+    }
+
+    return true
+  }
+}
+
+module.exports = findVisualStudio
+module.exports.test = {
+  VisualStudioFinder: VisualStudioFinder,
+  findVisualStudio: findVisualStudio
+}
Index: node_modules/node-gyp/lib/install.js
===================================================================
--- node_modules/node-gyp/lib/install.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/node-gyp/lib/install.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,376 @@
+'use strict'
+
+const fs = require('graceful-fs')
+const os = require('os')
+const tar = require('tar')
+const path = require('path')
+const util = require('util')
+const stream = require('stream')
+const crypto = require('crypto')
+const log = require('npmlog')
+const semver = require('semver')
+const fetch = require('make-fetch-happen')
+const processRelease = require('./process-release')
+const win = process.platform === 'win32'
+const streamPipeline = util.promisify(stream.pipeline)
+
+/**
+ * @param {typeof import('graceful-fs')} fs
+ */
+
+async function install (fs, gyp, argv) {
+  const release = processRelease(argv, gyp, process.version, process.release)
+
+  // Determine which node dev files version we are installing
+  log.verbose('install', 'input version string %j', release.version)
+
+  if (!release.semver) {
+    // could not parse the version string with semver
+    throw new Error('Invalid version number: ' + release.version)
+  }
+
+  if (semver.lt(release.version, '0.8.0')) {
+    throw new Error('Minimum target version is `0.8.0` or greater. Got: ' + release.version)
+  }
+
+  // 0.x.y-pre versions are not published yet and cannot be installed. Bail.
+  if (release.semver.prerelease[0] === 'pre') {
+    log.verbose('detected "pre" node version', release.version)
+    if (!gyp.opts.nodedir) {
+      throw new Error('"pre" versions of node cannot be installed, use the --nodedir flag instead')
+    }
+    log.verbose('--nodedir flag was passed; skipping install', gyp.opts.nodedir)
+    return
+  }
+
+  // flatten version into String
+  log.verbose('install', 'installing version: %s', release.versionDir)
+
+  // the directory where the dev files will be installed
+  const devDir = path.resolve(gyp.devDir, release.versionDir)
+
+  // If '--ensure' was passed, then don't *always* install the version;
+  // check if it is already installed, and only install when needed
+  if (gyp.opts.ensure) {
+    log.verbose('install', '--ensure was passed, so won\'t reinstall if already installed')
+    try {
+      await fs.promises.stat(devDir)
+    } catch (err) {
+      if (err.code === 'ENOENT') {
+        log.verbose('install', 'version not already installed, continuing with install', release.version)
+        try {
+          return await go()
+        } catch (err) {
+          return rollback(err)
+        }
+      } else if (err.code === 'EACCES') {
+        return eaccesFallback(err)
+      }
+      throw err
+    }
+    log.verbose('install', 'version is already installed, need to check "installVersion"')
+    const installVersionFile = path.resolve(devDir, 'installVersion')
+    let installVersion = 0
+    try {
+      const ver = await fs.promises.readFile(installVersionFile, 'ascii')
+      installVersion = parseInt(ver, 10) || 0
+    } catch (err) {
+      if (err.code !== 'ENOENT') {
+        throw err
+      }
+    }
+    log.verbose('got "installVersion"', installVersion)
+    log.verbose('needs "installVersion"', gyp.package.installVersion)
+    if (installVersion < gyp.package.installVersion) {
+      log.verbose('install', 'version is no good; reinstalling')
+      try {
+        return await go()
+      } catch (err) {
+        return rollback(err)
+      }
+    }
+    log.verbose('install', 'version is good')
+  } else {
+    try {
+      return await go()
+    } catch (err) {
+      return rollback(err)
+    }
+  }
+
+  async function go () {
+    log.verbose('ensuring nodedir is created', devDir)
+
+    // first create the dir for the node dev files
+    try {
+      const created = await fs.promises.mkdir(devDir, { recursive: true })
+
+      if (created) {
+        log.verbose('created nodedir', created)
+      }
+    } catch (err) {
+      if (err.code === 'EACCES') {
+        return eaccesFallback(err)
+      }
+
+      throw err
+    }
+
+    // now download the node tarball
+    const tarPath = gyp.opts.tarball
+    let extractCount = 0
+    const contentShasums = {}
+    const expectShasums = {}
+
+    // checks if a file to be extracted from the tarball is valid.
+    // only .h header files and the gyp files get extracted
+    function isValid (path) {
+      const isValid = valid(path)
+      if (isValid) {
+        log.verbose('extracted file from tarball', path)
+        extractCount++
+      } else {
+        // invalid
+        log.silly('ignoring from tarball', path)
+      }
+      return isValid
+    }
+
+    // download the tarball and extract!
+
+    if (tarPath) {
+      await tar.extract({
+        file: tarPath,
+        strip: 1,
+        filter: isValid,
+        cwd: devDir
+      })
+    } else {
+      try {
+        const res = await download(gyp, release.tarballUrl)
+
+        if (res.status !== 200) {
+          throw new Error(`${res.status} response downloading ${release.tarballUrl}`)
+        }
+
+        await streamPipeline(
+          res.body,
+          // content checksum
+          new ShaSum((_, checksum) => {
+            const filename = path.basename(release.tarballUrl).trim()
+            contentShasums[filename] = checksum
+            log.verbose('content checksum', filename, checksum)
+          }),
+          tar.extract({
+            strip: 1,
+            cwd: devDir,
+            filter: isValid
+          })
+        )
+      } catch (err) {
+        // something went wrong downloading the tarball?
+        if (err.code === 'ENOTFOUND') {
+          throw new Error('This is most likely not a problem with node-gyp or the package itself and\n' +
+            'is related to network connectivity. In most cases you are behind a proxy or have bad \n' +
+            'network settings.')
+        }
+        throw err
+      }
+    }
+
+    // invoked after the tarball has finished being extracted
+    if (extractCount === 0) {
+      throw new Error('There was a fatal problem while downloading/extracting the tarball')
+    }
+
+    log.verbose('tarball', 'done parsing tarball')
+
+    const installVersionPath = path.resolve(devDir, 'installVersion')
+    await Promise.all([
+      // need to download node.lib
+      ...(win ? downloadNodeLib() : []),
+      // write the "installVersion" file
+      fs.promises.writeFile(installVersionPath, gyp.package.installVersion + '\n'),
+      // Only download SHASUMS.txt if we downloaded something in need of SHA verification
+      ...(!tarPath || win ? [downloadShasums()] : [])
+    ])
+
+    log.verbose('download contents checksum', JSON.stringify(contentShasums))
+    // check content shasums
+    for (const k in contentShasums) {
+      log.verbose('validating download checksum for ' + k, '(%s == %s)', contentShasums[k], expectShasums[k])
+      if (contentShasums[k] !== expectShasums[k]) {
+        throw new Error(k + ' local checksum ' + contentShasums[k] + ' not match remote ' + expectShasums[k])
+      }
+    }
+
+    async function downloadShasums () {
+      log.verbose('check download content checksum, need to download `SHASUMS256.txt`...')
+      log.verbose('checksum url', release.shasumsUrl)
+
+      const res = await download(gyp, release.shasumsUrl)
+
+      if (res.status !== 200) {
+        throw new Error(`${res.status}  status code downloading checksum`)
+      }
+
+      for (const line of (await res.text()).trim().split('\n')) {
+        const items = line.trim().split(/\s+/)
+        if (items.length !== 2) {
+          return
+        }
+
+        // 0035d18e2dcf9aad669b1c7c07319e17abfe3762  ./node-v0.11.4.tar.gz
+        const name = items[1].replace(/^\.\//, '')
+        expectShasums[name] = items[0]
+      }
+
+      log.verbose('checksum data', JSON.stringify(expectShasums))
+    }
+
+    function downloadNodeLib () {
+      log.verbose('on Windows; need to download `' + release.name + '.lib`...')
+      const archs = ['ia32', 'x64', 'arm64']
+      return archs.map(async (arch) => {
+        const dir = path.resolve(devDir, arch)
+        const targetLibPath = path.resolve(dir, release.name + '.lib')
+        const { libUrl, libPath } = release[arch]
+        const name = `${arch} ${release.name}.lib`
+        log.verbose(name, 'dir', dir)
+        log.verbose(name, 'url', libUrl)
+
+        await fs.promises.mkdir(dir, { recursive: true })
+        log.verbose('streaming', name, 'to:', targetLibPath)
+
+        const res = await download(gyp, libUrl)
+
+        if (res.status === 403 || res.status === 404) {
+          if (arch === 'arm64') {
+            // Arm64 is a newer platform on Windows and not all node distributions provide it.
+            log.verbose(`${name} was not found in ${libUrl}`)
+          } else {
+            log.warn(`${name} was not found in ${libUrl}`)
+          }
+          return
+        } else if (res.status !== 200) {
+          throw new Error(`${res.status} status code downloading ${name}`)
+        }
+
+        return streamPipeline(
+          res.body,
+          new ShaSum((_, checksum) => {
+            contentShasums[libPath] = checksum
+            log.verbose('content checksum', libPath, checksum)
+          }),
+          fs.createWriteStream(targetLibPath)
+        )
+      })
+    } // downloadNodeLib()
+  } // go()
+
+  /**
+   * Checks if a given filename is "valid" for this installation.
+   */
+
+  function valid (file) {
+    // header files
+    const extname = path.extname(file)
+    return extname === '.h' || extname === '.gypi'
+  }
+
+  async function rollback (err) {
+    log.warn('install', 'got an error, rolling back install')
+    // roll-back the install if anything went wrong
+    await util.promisify(gyp.commands.remove)([release.versionDir])
+    throw err
+  }
+
+  /**
+   * The EACCES fallback is a workaround for npm's `sudo` behavior, where
+   * it drops the permissions before invoking any child processes (like
+   * node-gyp). So what happens is the "nobody" user doesn't have
+   * permission to create the dev dir. As a fallback, make the tmpdir() be
+   * the dev dir for this installation. This is not ideal, but at least
+   * the compilation will succeed...
+   */
+
+  async function eaccesFallback (err) {
+    const noretry = '--node_gyp_internal_noretry'
+    if (argv.indexOf(noretry) !== -1) {
+      throw err
+    }
+    const tmpdir = os.tmpdir()
+    gyp.devDir = path.resolve(tmpdir, '.node-gyp')
+    let userString = ''
+    try {
+      // os.userInfo can fail on some systems, it's not critical here
+      userString = ` ("${os.userInfo().username}")`
+    } catch (e) {}
+    log.warn('EACCES', 'current user%s does not have permission to access the dev dir "%s"', userString, devDir)
+    log.warn('EACCES', 'attempting to reinstall using temporary dev dir "%s"', gyp.devDir)
+    if (process.cwd() === tmpdir) {
+      log.verbose('tmpdir == cwd', 'automatically will remove dev files after to save disk space')
+      gyp.todo.push({ name: 'remove', args: argv })
+    }
+    return util.promisify(gyp.commands.install)([noretry].concat(argv))
+  }
+}
+
+class ShaSum extends stream.Transform {
+  constructor (callback) {
+    super()
+    this._callback = callback
+    this._digester = crypto.createHash('sha256')
+  }
+
+  _transform (chunk, _, callback) {
+    this._digester.update(chunk)
+    callback(null, chunk)
+  }
+
+  _flush (callback) {
+    this._callback(null, this._digester.digest('hex'))
+    callback()
+  }
+}
+
+async function download (gyp, url) {
+  log.http('GET', url)
+
+  const requestOpts = {
+    headers: {
+      'User-Agent': `node-gyp v${gyp.version} (node ${process.version})`,
+      Connection: 'keep-alive'
+    },
+    proxy: gyp.opts.proxy,
+    noProxy: gyp.opts.noproxy
+  }
+
+  const cafile = gyp.opts.cafile
+  if (cafile) {
+    requestOpts.ca = await readCAFile(cafile)
+  }
+
+  const res = await fetch(url, requestOpts)
+  log.http(res.status, res.url)
+
+  return res
+}
+
+async function readCAFile (filename) {
+  // The CA file can contain multiple certificates so split on certificate
+  // boundaries.  [\S\s]*? is used to match everything including newlines.
+  const ca = await fs.promises.readFile(filename, 'utf8')
+  const re = /(-----BEGIN CERTIFICATE-----[\S\s]*?-----END CERTIFICATE-----)/g
+  return ca.match(re)
+}
+
+module.exports = function (gyp, argv, callback) {
+  install(fs, gyp, argv).then(callback.bind(undefined, null), callback)
+}
+module.exports.test = {
+  download,
+  install,
+  readCAFile
+}
+module.exports.usage = 'Install node development files for the specified node version.'
Index: node_modules/node-gyp/lib/list.js
===================================================================
--- node_modules/node-gyp/lib/list.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/node-gyp/lib/list.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,27 @@
+'use strict'
+
+const fs = require('graceful-fs')
+const log = require('npmlog')
+
+function list (gyp, args, callback) {
+  var devDir = gyp.devDir
+  log.verbose('list', 'using node-gyp dir:', devDir)
+
+  fs.readdir(devDir, onreaddir)
+
+  function onreaddir (err, versions) {
+    if (err && err.code !== 'ENOENT') {
+      return callback(err)
+    }
+
+    if (Array.isArray(versions)) {
+      versions = versions.filter(function (v) { return v !== 'current' })
+    } else {
+      versions = []
+    }
+    callback(null, versions)
+  }
+}
+
+module.exports = list
+module.exports.usage = 'Prints a listing of the currently installed node development files'
Index: node_modules/node-gyp/lib/node-gyp.js
===================================================================
--- node_modules/node-gyp/lib/node-gyp.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/node-gyp/lib/node-gyp.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,211 @@
+'use strict'
+
+const path = require('path')
+const nopt = require('nopt')
+const log = require('npmlog')
+const childProcess = require('child_process')
+const EE = require('events').EventEmitter
+const inherits = require('util').inherits
+const commands = [
+  // Module build commands
+  'build',
+  'clean',
+  'configure',
+  'rebuild',
+  // Development Header File management commands
+  'install',
+  'list',
+  'remove'
+]
+const aliases = {
+  ls: 'list',
+  rm: 'remove'
+}
+
+// differentiate node-gyp's logs from npm's
+log.heading = 'gyp'
+
+function gyp () {
+  return new Gyp()
+}
+
+function Gyp () {
+  var self = this
+
+  this.devDir = ''
+  this.commands = {}
+
+  commands.forEach(function (command) {
+    self.commands[command] = function (argv, callback) {
+      log.verbose('command', command, argv)
+      return require('./' + command)(self, argv, callback)
+    }
+  })
+}
+inherits(Gyp, EE)
+exports.Gyp = Gyp
+var proto = Gyp.prototype
+
+/**
+ * Export the contents of the package.json.
+ */
+
+proto.package = require('../package.json')
+
+/**
+ * nopt configuration definitions
+ */
+
+proto.configDefs = {
+  help: Boolean, // everywhere
+  arch: String, // 'configure'
+  cafile: String, // 'install'
+  debug: Boolean, // 'build'
+  directory: String, // bin
+  make: String, // 'build'
+  msvs_version: String, // 'configure'
+  ensure: Boolean, // 'install'
+  solution: String, // 'build' (windows only)
+  proxy: String, // 'install'
+  noproxy: String, // 'install'
+  devdir: String, // everywhere
+  nodedir: String, // 'configure'
+  loglevel: String, // everywhere
+  python: String, // 'configure'
+  'dist-url': String, // 'install'
+  tarball: String, // 'install'
+  jobs: String, // 'build'
+  thin: String, // 'configure'
+  'force-process-config': Boolean // 'configure'
+}
+
+/**
+ * nopt shorthands
+ */
+
+proto.shorthands = {
+  release: '--no-debug',
+  C: '--directory',
+  debug: '--debug',
+  j: '--jobs',
+  silly: '--loglevel=silly',
+  verbose: '--loglevel=verbose',
+  silent: '--loglevel=silent'
+}
+
+/**
+ * expose the command aliases for the bin file to use.
+ */
+
+proto.aliases = aliases
+
+/**
+ * Parses the given argv array and sets the 'opts',
+ * 'argv' and 'command' properties.
+ */
+
+proto.parseArgv = function parseOpts (argv) {
+  this.opts = nopt(this.configDefs, this.shorthands, argv)
+  this.argv = this.opts.argv.remain.slice()
+
+  var commands = this.todo = []
+
+  // create a copy of the argv array with aliases mapped
+  argv = this.argv.map(function (arg) {
+    // is this an alias?
+    if (arg in this.aliases) {
+      arg = this.aliases[arg]
+    }
+    return arg
+  }, this)
+
+  // process the mapped args into "command" objects ("name" and "args" props)
+  argv.slice().forEach(function (arg) {
+    if (arg in this.commands) {
+      var args = argv.splice(0, argv.indexOf(arg))
+      argv.shift()
+      if (commands.length > 0) {
+        commands[commands.length - 1].args = args
+      }
+      commands.push({ name: arg, args: [] })
+    }
+  }, this)
+  if (commands.length > 0) {
+    commands[commands.length - 1].args = argv.splice(0)
+  }
+
+  // support for inheriting config env variables from npm
+  var npmConfigPrefix = 'npm_config_'
+  Object.keys(process.env).forEach(function (name) {
+    if (name.indexOf(npmConfigPrefix) !== 0) {
+      return
+    }
+    var val = process.env[name]
+    if (name === npmConfigPrefix + 'loglevel') {
+      log.level = val
+    } else {
+      // add the user-defined options to the config
+      name = name.substring(npmConfigPrefix.length)
+      // gyp@741b7f1 enters an infinite loop when it encounters
+      // zero-length options so ensure those don't get through.
+      if (name) {
+        this.opts[name] = val
+      }
+    }
+  }, this)
+
+  if (this.opts.loglevel) {
+    log.level = this.opts.loglevel
+  }
+  log.resume()
+}
+
+/**
+ * Spawns a child process and emits a 'spawn' event.
+ */
+
+proto.spawn = function spawn (command, args, opts) {
+  if (!opts) {
+    opts = {}
+  }
+  if (!opts.silent && !opts.stdio) {
+    opts.stdio = [0, 1, 2]
+  }
+  var cp = childProcess.spawn(command, args, opts)
+  log.info('spawn', command)
+  log.info('spawn args', args)
+  return cp
+}
+
+/**
+ * Returns the usage instructions for node-gyp.
+ */
+
+proto.usage = function usage () {
+  var str = [
+    '',
+    '  Usage: node-gyp <command> [options]',
+    '',
+    '  where <command> is one of:',
+    commands.map(function (c) {
+      return '    - ' + c + ' - ' + require('./' + c).usage
+    }).join('\n'),
+    '',
+    'node-gyp@' + this.version + '  ' + path.resolve(__dirname, '..'),
+    'node@' + process.versions.node
+  ].join('\n')
+  return str
+}
+
+/**
+ * Version number getter.
+ */
+
+Object.defineProperty(proto, 'version', {
+  get: function () {
+    return this.package.version
+  },
+  enumerable: true
+})
+
+module.exports = exports = gyp
Index: node_modules/node-gyp/lib/process-release.js
===================================================================
--- node_modules/node-gyp/lib/process-release.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/node-gyp/lib/process-release.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,147 @@
+/* eslint-disable node/no-deprecated-api */
+
+'use strict'
+
+const semver = require('semver')
+const url = require('url')
+const path = require('path')
+const log = require('npmlog')
+
+// versions where -headers.tar.gz started shipping
+const headersTarballRange = '>= 3.0.0 || ~0.12.10 || ~0.10.42'
+const bitsre = /\/win-(x86|x64|arm64)\//
+const bitsreV3 = /\/win-(x86|ia32|x64)\// // io.js v3.x.x shipped with "ia32" but should
+// have been "x86"
+
+// Captures all the logic required to determine download URLs, local directory and
+// file names. Inputs come from command-line switches (--target, --dist-url),
+// `process.version` and `process.release` where it exists.
+function processRelease (argv, gyp, defaultVersion, defaultRelease) {
+  var version = (semver.valid(argv[0]) && argv[0]) || gyp.opts.target || defaultVersion
+  var versionSemver = semver.parse(version)
+  var overrideDistUrl = gyp.opts['dist-url'] || gyp.opts.disturl
+  var isDefaultVersion
+  var isNamedForLegacyIojs
+  var name
+  var distBaseUrl
+  var baseUrl
+  var libUrl32
+  var libUrl64
+  var libUrlArm64
+  var tarballUrl
+  var canGetHeaders
+
+  if (!versionSemver) {
+    // not a valid semver string, nothing we can do
+    return { version: version }
+  }
+  // flatten version into String
+  version = versionSemver.version
+
+  // defaultVersion should come from process.version so ought to be valid semver
+  isDefaultVersion = version === semver.parse(defaultVersion).version
+
+  // can't use process.release if we're using --target=x.y.z
+  if (!isDefaultVersion) {
+    defaultRelease = null
+  }
+
+  if (defaultRelease) {
+    // v3 onward, has process.release
+    name = defaultRelease.name.replace(/io\.js/, 'iojs') // remove the '.' for directory naming purposes
+  } else {
+    // old node or alternative --target=
+    // semver.satisfies() doesn't like prerelease tags so test major directly
+    isNamedForLegacyIojs = versionSemver.major >= 1 && versionSemver.major < 4
+    // isNamedForLegacyIojs is required to support Electron < 4 (in particular Electron 3)
+    // as previously this logic was used to ensure "iojs" was used to download iojs releases
+    // and "node" for node releases.  Unfortunately the logic was broad enough that electron@3
+    // published release assets as "iojs" so that the node-gyp logic worked.  Once Electron@3 has
+    // been EOL for a while (late 2019) we should remove this hack.
+    name = isNamedForLegacyIojs ? 'iojs' : 'node'
+  }
+
+  // check for the nvm.sh standard mirror env variables
+  if (!overrideDistUrl && process.env.NODEJS_ORG_MIRROR) {
+    overrideDistUrl = process.env.NODEJS_ORG_MIRROR
+  }
+
+  if (overrideDistUrl) {
+    log.verbose('download', 'using dist-url', overrideDistUrl)
+  }
+
+  if (overrideDistUrl) {
+    distBaseUrl = overrideDistUrl.replace(/\/+$/, '')
+  } else {
+    distBaseUrl = 'https://nodejs.org/dist'
+  }
+  distBaseUrl += '/v' + version + '/'
+
+  // new style, based on process.release so we have a lot of the data we need
+  if (defaultRelease && defaultRelease.headersUrl && !overrideDistUrl) {
+    baseUrl = url.resolve(defaultRelease.headersUrl, './')
+    libUrl32 = resolveLibUrl(name, defaultRelease.libUrl || baseUrl || distBaseUrl, 'x86', versionSemver.major)
+    libUrl64 = resolveLibUrl(name, defaultRelease.libUrl || baseUrl || distBaseUrl, 'x64', versionSemver.major)
+    libUrlArm64 = resolveLibUrl(name, defaultRelease.libUrl || baseUrl || distBaseUrl, 'arm64', versionSemver.major)
+    tarballUrl = defaultRelease.headersUrl
+  } else {
+    // older versions without process.release are captured here and we have to make
+    // a lot of assumptions, additionally if you --target=x.y.z then we can't use the
+    // current process.release
+    baseUrl = distBaseUrl
+    libUrl32 = resolveLibUrl(name, baseUrl, 'x86', versionSemver.major)
+    libUrl64 = resolveLibUrl(name, baseUrl, 'x64', versionSemver.major)
+    libUrlArm64 = resolveLibUrl(name, baseUrl, 'arm64', versionSemver.major)
+
+    // making the bold assumption that anything with a version number >3.0.0 will
+    // have a *-headers.tar.gz file in its dist location, even some frankenstein
+    // custom version
+    canGetHeaders = semver.satisfies(versionSemver, headersTarballRange)
+    tarballUrl = url.resolve(baseUrl, name + '-v' + version + (canGetHeaders ? '-headers' : '') + '.tar.gz')
+  }
+
+  return {
+    version: version,
+    semver: versionSemver,
+    name: name,
+    baseUrl: baseUrl,
+    tarballUrl: tarballUrl,
+    shasumsUrl: url.resolve(baseUrl, 'SHASUMS256.txt'),
+    versionDir: (name !== 'node' ? name + '-' : '') + version,
+    ia32: {
+      libUrl: libUrl32,
+      libPath: normalizePath(path.relative(url.parse(baseUrl).path, url.parse(libUrl32).path))
+    },
+    x64: {
+      libUrl: libUrl64,
+      libPath: normalizePath(path.relative(url.parse(baseUrl).path, url.parse(libUrl64).path))
+    },
+    arm64: {
+      libUrl: libUrlArm64,
+      libPath: normalizePath(path.relative(url.parse(baseUrl).path, url.parse(libUrlArm64).path))
+    }
+  }
+}
+
+function normalizePath (p) {
+  return path.normalize(p).replace(/\\/g, '/')
+}
+
+function resolveLibUrl (name, defaultUrl, arch, versionMajor) {
+  var base = url.resolve(defaultUrl, './')
+  var hasLibUrl = bitsre.test(defaultUrl) || (versionMajor === 3 && bitsreV3.test(defaultUrl))
+
+  if (!hasLibUrl) {
+    // let's assume it's a baseUrl then
+    if (versionMajor >= 1) {
+      return url.resolve(base, 'win-' + arch + '/' + name + '.lib')
+    }
+    // prior to io.js@1.0.0 32-bit node.lib lives in /, 64-bit lives in /x64/
+    return url.resolve(base, (arch === 'x86' ? '' : arch + '/') + name + '.lib')
+  }
+
+  // else we have a proper url to a .lib, just make sure it's the right arch
+  return defaultUrl.replace(versionMajor === 3 ? bitsreV3 : bitsre, '/win-' + arch + '/')
+}
+
+module.exports = processRelease
Index: node_modules/node-gyp/lib/rebuild.js
===================================================================
--- node_modules/node-gyp/lib/rebuild.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/node-gyp/lib/rebuild.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,13 @@
+'use strict'
+
+function rebuild (gyp, argv, callback) {
+  gyp.todo.push(
+    { name: 'clean', args: [] }
+    , { name: 'configure', args: argv }
+    , { name: 'build', args: [] }
+  )
+  process.nextTick(callback)
+}
+
+module.exports = rebuild
+module.exports.usage = 'Runs "clean", "configure" and "build" all at once'
Index: node_modules/node-gyp/lib/remove.js
===================================================================
--- node_modules/node-gyp/lib/remove.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/node-gyp/lib/remove.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,46 @@
+'use strict'
+
+const fs = require('fs')
+const rm = require('rimraf')
+const path = require('path')
+const log = require('npmlog')
+const semver = require('semver')
+
+function remove (gyp, argv, callback) {
+  var devDir = gyp.devDir
+  log.verbose('remove', 'using node-gyp dir:', devDir)
+
+  // get the user-specified version to remove
+  var version = argv[0] || gyp.opts.target
+  log.verbose('remove', 'removing target version:', version)
+
+  if (!version) {
+    return callback(new Error('You must specify a version number to remove. Ex: "' + process.version + '"'))
+  }
+
+  var versionSemver = semver.parse(version)
+  if (versionSemver) {
+    // flatten the version Array into a String
+    version = versionSemver.version
+  }
+
+  var versionPath = path.resolve(gyp.devDir, version)
+  log.verbose('remove', 'removing development files for version:', version)
+
+  // first check if its even installed
+  fs.stat(versionPath, function (err) {
+    if (err) {
+      if (err.code === 'ENOENT') {
+        callback(null, 'version was already uninstalled: ' + version)
+      } else {
+        callback(err)
+      }
+      return
+    }
+    // Go ahead and delete the dir
+    rm(versionPath, callback)
+  })
+}
+
+module.exports = exports = remove
+module.exports.usage = 'Removes the node development files for the specified version'
Index: node_modules/node-gyp/lib/util.js
===================================================================
--- node_modules/node-gyp/lib/util.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/node-gyp/lib/util.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,64 @@
+'use strict'
+
+const log = require('npmlog')
+const execFile = require('child_process').execFile
+const path = require('path')
+
+function logWithPrefix (log, prefix) {
+  function setPrefix (logFunction) {
+    return (...args) => logFunction.apply(null, [ prefix, ...args ]) // eslint-disable-line
+  }
+  return {
+    silly: setPrefix(log.silly),
+    verbose: setPrefix(log.verbose),
+    info: setPrefix(log.info),
+    warn: setPrefix(log.warn),
+    error: setPrefix(log.error)
+  }
+}
+
+function regGetValue (key, value, addOpts, cb) {
+  const outReValue = value.replace(/\W/g, '.')
+  const outRe = new RegExp(`^\\s+${outReValue}\\s+REG_\\w+\\s+(\\S.*)$`, 'im')
+  const reg = path.join(process.env.SystemRoot, 'System32', 'reg.exe')
+  const regArgs = ['query', key, '/v', value].concat(addOpts)
+
+  log.silly('reg', 'running', reg, regArgs)
+  const child = execFile(reg, regArgs, { encoding: 'utf8' },
+    function (err, stdout, stderr) {
+      log.silly('reg', 'reg.exe stdout = %j', stdout)
+      if (err || stderr.trim() !== '') {
+        log.silly('reg', 'reg.exe err = %j', err && (err.stack || err))
+        log.silly('reg', 'reg.exe stderr = %j', stderr)
+        return cb(err, stderr)
+      }
+
+      const result = outRe.exec(stdout)
+      if (!result) {
+        log.silly('reg', 'error parsing stdout')
+        return cb(new Error('Could not parse output of reg.exe'))
+      }
+      log.silly('reg', 'found: %j', result[1])
+      cb(null, result[1])
+    })
+  child.stdin.end()
+}
+
+function regSearchKeys (keys, value, addOpts, cb) {
+  var i = 0
+  const search = () => {
+    log.silly('reg-search', 'looking for %j in %j', value, keys[i])
+    regGetValue(keys[i], value, addOpts, (err, res) => {
+      ++i
+      if (err && i < keys.length) { return search() }
+      cb(err, res)
+    })
+  }
+  search()
+}
+
+module.exports = {
+  logWithPrefix: logWithPrefix,
+  regGetValue: regGetValue,
+  regSearchKeys: regSearchKeys
+}
