Index: node_modules/undefsafe/.github/workflows/release.yml
===================================================================
--- node_modules/undefsafe/.github/workflows/release.yml	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/undefsafe/.github/workflows/release.yml	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,25 @@
+name: Release
+on:
+  push:
+    branches:
+      - master
+jobs:
+  release:
+    name: Release
+    runs-on: ubuntu-18.04
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v1
+      - name: Setup Node.js
+        uses: actions/setup-node@v1
+        with:
+          node-version: 16
+      - name: Install dependencies
+        run: npm ci
+      - name: Test
+        run: npm run test
+      - name: Release
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+        run: npx semantic-release
Index: node_modules/undefsafe/.jscsrc
===================================================================
--- node_modules/undefsafe/.jscsrc	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/undefsafe/.jscsrc	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,13 @@
+{
+  "preset": "node-style-guide",
+  "requireCapitalizedComments": null,
+  "requireSpacesInAnonymousFunctionExpression": {
+    "beforeOpeningCurlyBrace": true,
+    "beforeOpeningRoundBrace": true
+  },
+  "disallowSpacesInNamedFunctionExpression": {
+    "beforeOpeningRoundBrace": true
+  },
+  "excludeFiles": ["node_modules/**"],
+  "disallowSpacesInFunction": null
+}
Index: node_modules/undefsafe/.jshintrc
===================================================================
--- node_modules/undefsafe/.jshintrc	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/undefsafe/.jshintrc	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,16 @@
+{
+  "browser": false,
+  "camelcase": true,
+  "curly": true,
+  "devel": true,
+  "eqeqeq": true,
+  "forin": true,
+  "indent": 2,
+  "noarg": true,
+  "node": true,
+  "quotmark": "single",
+  "undef": true,
+  "strict": false,
+  "unused": true
+}
+
Index: node_modules/undefsafe/.travis.yml
===================================================================
--- node_modules/undefsafe/.travis.yml	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/undefsafe/.travis.yml	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,18 @@
+sudo: false
+language: node_js
+cache:
+  directories:
+    - node_modules
+notifications:
+  email: false
+node_js:
+  - '4'
+before_install:
+  - npm i -g npm@^2.0.0
+before_script:
+  - npm prune
+after_success:
+  - npm run semantic-release
+branches:
+  except:
+    - "/^v\\d+\\.\\d+\\.\\d+$/"
Index: node_modules/undefsafe/LICENSE
===================================================================
--- node_modules/undefsafe/LICENSE	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/undefsafe/LICENSE	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright © 2016 Remy Sharp, http://remysharp.com <remy@remysharp.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Index: node_modules/undefsafe/README.md
===================================================================
--- node_modules/undefsafe/README.md	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/undefsafe/README.md	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,63 @@
+# undefsafe
+
+Simple *function* for retrieving deep object properties without getting "Cannot read property 'X' of undefined"
+
+Can also be used to safely set deep values.
+
+## Usage
+
+```js
+var object = {
+  a: {
+    b: {
+      c: 1,
+      d: [1,2,3],
+      e: 'remy'
+    }
+  }
+};
+
+console.log(undefsafe(object, 'a.b.e')); // "remy"
+console.log(undefsafe(object, 'a.b.not.found')); // undefined
+```
+
+Demo: [https://jsbin.com/eroqame/3/edit?js,console](https://jsbin.com/eroqame/3/edit?js,console)
+
+## Setting
+
+```js
+var object = {
+  a: {
+    b: [1,2,3]
+  }
+};
+
+// modified object
+var res = undefsafe(object, 'a.b.0', 10);
+
+console.log(object); // { a: { b: [10, 2, 3] } }
+console.log(res); // 1 - previous value
+```
+
+## Star rules in paths
+
+As of 1.2.0, `undefsafe` supports a `*` in the path if you want to search all of the properties (or array elements) for a particular element.
+
+The function will only return a single result, either the 3rd argument validation value, or the first positive match. For example, the following github data:
+
+```js
+const githubData = {
+        commits: [{
+          modified: [
+            "one",
+            "two"
+          ]
+        }, /* ... */ ]
+      };
+
+// first modified file found in the first commit
+console.log(undefsafe(githubData, 'commits.*.modified.0'));
+
+// returns `two` or undefined if not found
+console.log(undefsafe(githubData, 'commits.*.modified.*', 'two'));
+```
Index: node_modules/undefsafe/example.js
===================================================================
--- node_modules/undefsafe/example.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/undefsafe/example.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,14 @@
+var undefsafe = require('undefsafe');
+
+var object = {
+  a: {
+    b: {
+      c: 1,
+      d: [1, 2, 3],
+      e: 'remy'
+    }
+  }
+};
+
+console.log(undefsafe(object, 'a.b.e')); // "remy"
+console.log(undefsafe(object, 'a.b.not.found')); // undefined
Index: node_modules/undefsafe/lib/undefsafe.js
===================================================================
--- node_modules/undefsafe/lib/undefsafe.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/undefsafe/lib/undefsafe.js	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,125 @@
+'use strict';
+
+function undefsafe(obj, path, value, __res) {
+  // I'm not super keen on this private function, but it's because
+  // it'll also be use in the browser and I wont *one* function exposed
+  function split(path) {
+    var res = [];
+    var level = 0;
+    var key = '';
+
+    for (var i = 0; i < path.length; i++) {
+      var c = path.substr(i, 1);
+
+      if (level === 0 && (c === '.' || c === '[')) {
+        if (c === '[') {
+          level++;
+          i++;
+          c = path.substr(i, 1);
+        }
+
+        if (key) {
+          // the first value could be a string
+          res.push(key);
+        }
+        key = '';
+        continue;
+      }
+
+      if (c === ']') {
+        level--;
+        key = key.slice(0, -1);
+        continue;
+      }
+
+      key += c;
+    }
+
+    res.push(key);
+
+    return res;
+  }
+
+  // bail if there's nothing
+  if (obj === undefined || obj === null) {
+    return undefined;
+  }
+
+  var parts = split(path);
+  var key = null;
+  var type = typeof obj;
+  var root = obj;
+  var parent = obj;
+
+  var star =
+    parts.filter(function(_) {
+      return _ === '*';
+    }).length > 0;
+
+  // we're dealing with a primitive
+  if (type !== 'object' && type !== 'function') {
+    return obj;
+  } else if (path.trim() === '') {
+    return obj;
+  }
+
+  key = parts[0];
+  var i = 0;
+  for (; i < parts.length; i++) {
+    key = parts[i];
+    parent = obj;
+
+    if (key === '*') {
+      // loop through each property
+      var prop = '';
+      var res = __res || [];
+
+      for (prop in parent) {
+        var shallowObj = undefsafe(
+          obj[prop],
+          parts.slice(i + 1).join('.'),
+          value,
+          res
+        );
+        if (shallowObj && shallowObj !== res) {
+          if ((value && shallowObj === value) || value === undefined) {
+            if (value !== undefined) {
+              return shallowObj;
+            }
+
+            res.push(shallowObj);
+          }
+        }
+      }
+
+      if (res.length === 0) {
+        return undefined;
+      }
+
+      return res;
+    }
+
+    if (Object.getOwnPropertyNames(obj).indexOf(key) == -1) {
+      return undefined;
+    }
+
+    obj = obj[key];
+    if (obj === undefined || obj === null) {
+      break;
+    }
+  }
+
+  // if we have a null object, make sure it's the one the user was after,
+  // if it's not (i.e. parts has a length) then give undefined back.
+  if (obj === null && i !== parts.length - 1) {
+    obj = undefined;
+  } else if (!star && value) {
+    key = path.split('.').pop();
+    parent[key] = value;
+  }
+  return obj;
+}
+
+if (typeof module !== 'undefined') {
+  module.exports = undefsafe;
+}
Index: node_modules/undefsafe/package.json
===================================================================
--- node_modules/undefsafe/package.json	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/undefsafe/package.json	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,34 @@
+{
+  "name": "undefsafe",
+  "description": "Undefined safe way of extracting object properties",
+  "main": "lib/undefsafe.js",
+  "tonicExampleFilename": "example.js",
+  "directories": {
+    "test": "test"
+  },
+  "scripts": {
+    "test": "tap test/**/*.test.js -R spec",
+    "cover": "tap test/*.test.js --cov --coverage-report=lcov",
+    "semantic-release": "semantic-release"
+  },
+  "prettier": {
+    "trailingComma": "none",
+    "singleQuote": true
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/remy/undefsafe.git"
+  },
+  "keywords": [
+    "undefined"
+  ],
+  "author": "Remy Sharp",
+  "license": "MIT",
+  "devDependencies": {
+    "semantic-release": "^18.0.0",
+    "tap": "^5.7.1",
+    "tap-only": "0.0.5"
+  },
+  "dependencies": {},
+  "version": "2.0.5"
+}
