From 3775654fd4f606b4f75b680551eea85fd12482b5 Mon Sep 17 00:00:00 2001 From: Luke Hagar Date: Tue, 19 Jul 2022 07:59:25 -0500 Subject: [PATCH] Attempting login --- package-lock.json | 133 +++++++++++++++++++++++++++++++++++++++++++ package.json | 4 ++ src/main/main.ts | 5 +- src/main/preload.ts | 4 ++ src/renderer/App.jsx | 53 ++++++++++++++++- yarn.lock | 53 ++++++++++++++++- 6 files changed, 246 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 735d586..24c4a97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,16 +22,20 @@ "electron-debug": "^3.2.0", "electron-log": "^4.4.7", "electron-updater": "^5.0.3", + "fs": "^0.0.1-security", "http-browserify": "^1.7.0", "https-browserify": "^1.0.0", "login-with-plex": "^1.1.1", + "path": "^0.12.7", "plex-api": "^5.3.2", "plex-api-credentials": "^4.0.1", + "plex-oauth": "^2.0.2", "react": "^18.2.0", "react-dom": "^18.1.0", "react-intl": "^6.0.5", "react-jinke-music-player": "^4.24.2", "react-router-dom": "^6.3.0", + "stream": "^0.0.2", "uuid": "^8.3.2" }, "devDependencies": { @@ -7362,6 +7366,11 @@ "node": ">=8" } }, + "node_modules/emitter-component": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/emitter-component/-/emitter-component-1.1.1.tgz", + "integrity": "sha512-G+mpdiAySMuB7kesVRLuyvYRqDmshB7ReKEVuyBPkzQlmiDiLrt7hHHIy4Aff552bgknVN7B2/d3lzhGO5dvpQ==" + }, "node_modules/emittery": { "version": "0.10.2", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", @@ -9242,6 +9251,11 @@ "node": ">= 0.6" } }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + }, "node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -13741,6 +13755,15 @@ "tslib": "^2.0.3" } }, + "node_modules/path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", + "dependencies": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -14004,6 +14027,22 @@ "node": ">=4.0" } }, + "node_modules/plex-oauth": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/plex-oauth/-/plex-oauth-2.0.2.tgz", + "integrity": "sha512-tbs/zyukFdHYi/nS/VqW1GgquPTIs1RgWXINlBZsyqfO7a3x6rfQ7av0/dRotxyKkBq6xIKLcQGdCmHn9UDnrQ==", + "dependencies": { + "axios": "^0.26.0" + } + }, + "node_modules/plex-oauth/node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, "node_modules/plist": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz", @@ -14625,6 +14664,14 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -16894,6 +16941,14 @@ "node": ">=0.10.0" } }, + "node_modules/stream": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stream/-/stream-0.0.2.tgz", + "integrity": "sha512-gCq3NDI2P35B2n6t76YJuOp7d6cN/C7Rt0577l91wllh0sY9ZBuw9KaSGqH/b0hzn3CWWJbpbW0W0WvQ1H/Q7g==", + "dependencies": { + "emitter-component": "^1.1.1" + } + }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -17988,12 +18043,25 @@ "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", "dev": true }, + "node_modules/util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dependencies": { + "inherits": "2.0.3" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "node_modules/util/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, "node_modules/utila": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", @@ -24501,6 +24569,11 @@ } } }, + "emitter-component": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/emitter-component/-/emitter-component-1.1.1.tgz", + "integrity": "sha512-G+mpdiAySMuB7kesVRLuyvYRqDmshB7ReKEVuyBPkzQlmiDiLrt7hHHIy4Aff552bgknVN7B2/d3lzhGO5dvpQ==" + }, "emittery": { "version": "0.10.2", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", @@ -25896,6 +25969,11 @@ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "dev": true }, + "fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + }, "fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -29278,6 +29356,15 @@ "tslib": "^2.0.3" } }, + "path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", + "requires": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -29479,6 +29566,24 @@ "resolved": "https://registry.npmjs.org/plex-api-headers/-/plex-api-headers-1.1.0.tgz", "integrity": "sha512-Igl37++MSa+4H8LNP3Ene9GU0e1YypmXvFVNvVUwoAx44e74jbUlJXy4Q5rLSBisn0O2lBKdE6VkFIwrDl+UnQ==" }, + "plex-oauth": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/plex-oauth/-/plex-oauth-2.0.2.tgz", + "integrity": "sha512-tbs/zyukFdHYi/nS/VqW1GgquPTIs1RgWXINlBZsyqfO7a3x6rfQ7av0/dRotxyKkBq6xIKLcQGdCmHn9UDnrQ==", + "requires": { + "axios": "^0.26.0" + }, + "dependencies": { + "axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "requires": { + "follow-redirects": "^1.14.8" + } + } + } + }, "plist": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz", @@ -29874,6 +29979,11 @@ } } }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -31582,6 +31692,14 @@ "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==" }, + "stream": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stream/-/stream-0.0.2.tgz", + "integrity": "sha512-gCq3NDI2P35B2n6t76YJuOp7d6cN/C7Rt0577l91wllh0sY9ZBuw9KaSGqH/b0hzn3CWWJbpbW0W0WvQ1H/Q7g==", + "requires": { + "emitter-component": "^1.1.1" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -32389,6 +32507,21 @@ "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", "dev": true }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + } + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index da3f79c..8589788 100644 --- a/package.json +++ b/package.json @@ -123,16 +123,20 @@ "electron-debug": "^3.2.0", "electron-log": "^4.4.7", "electron-updater": "^5.0.3", + "fs": "^0.0.1-security", "http-browserify": "^1.7.0", "https-browserify": "^1.0.0", "login-with-plex": "^1.1.1", + "path": "^0.12.7", "plex-api": "^5.3.2", "plex-api-credentials": "^4.0.1", + "plex-oauth": "^2.0.2", "react": "^18.2.0", "react-dom": "^18.1.0", "react-intl": "^6.0.5", "react-jinke-music-player": "^4.24.2", "react-router-dom": "^6.3.0", + "stream": "^0.0.2", "uuid": "^8.3.2" }, "devDependencies": { diff --git a/src/main/main.ts b/src/main/main.ts index 9df9b96..f293c62 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -15,7 +15,6 @@ import { shell, ipcMain, nativeTheme, - protocol, dialog, } from 'electron'; import { autoUpdater } from 'electron-updater'; @@ -116,8 +115,8 @@ const createWindow = async () => { nativeTheme.themeSource = 'system'; }); - ipcMain.handle('plex:login', (authData) => { - window.open(authData); + ipcMain.handle('plex:login', () => { + window.open('https://github.com', '_blank', 'top=500,left=200,frame=false,nodeIntegration=no') }); mainWindow.on('ready-to-show', () => { diff --git a/src/main/preload.ts b/src/main/preload.ts index 1badfed..80ec66f 100644 --- a/src/main/preload.ts +++ b/src/main/preload.ts @@ -24,3 +24,7 @@ contextBridge.exposeInMainWorld('darkMode', { toggle: () => ipcRenderer.invoke('dark-mode:toggle'), system: () => ipcRenderer.invoke('dark-mode:system'), }); + +contextBridge.exposeInMainWorld('plex', { + login: () => ipcRenderer.invoke('plex:login'), +}); \ No newline at end of file diff --git a/src/renderer/App.jsx b/src/renderer/App.jsx index 2f21c08..d1edb78 100644 --- a/src/renderer/App.jsx +++ b/src/renderer/App.jsx @@ -24,11 +24,13 @@ import KeyIcon from '@mui/icons-material/Key'; import LockOpenIcon from '@mui/icons-material/LockOpen'; import DarkModeIcon from '@mui/icons-material/DarkMode'; import FormatColorResetIcon from '@mui/icons-material/FormatColorReset'; -import { Grid, IconButton, TextField } from '@mui/material'; +import { Button, Grid, IconButton, TextField } from '@mui/material'; import { v4 as uuidv4 } from 'uuid'; import axios from 'axios'; import ReactJkMusicPlayer from 'react-jinke-music-player'; +import { PlexOauth, IPlexClientDetails } from 'plex-oauth'; +import { shell } from 'electron'; const drawerWidth = 240; @@ -77,6 +79,49 @@ function App() { const redirectURL = 'warden-ap://'; + let clientInformation = { + clientIdentifier: clientId, // This is a unique identifier used to identify your app with Plex. + product: 'Warden', // Name of your application + device: 'darwin', // The type of device your application is running on + version: '1', // Version of your application + forwardUrl: 'http://127.0.0.1:1212', // Url to forward back to after signing in. + platform: 'Web', // Optional - Platform your application runs on - Defaults to 'Web' + }; + + let plexOauth = new PlexOauth(clientInformation); + + // Get hosted UI URL and Pin Id + plexOauth + .requestHostedLoginURL() + .then((data) => { + let [hostedUILink, pinId] = data; + + console.log(hostedUILink); // UI URL used to log into Plex + + shell.openExternal(hostedUILink); + /* + * You can now navigate the user's browser to the 'hostedUILink'. This will include the forward URL + * for your application, so when they have finished signing into Plex, they will be redirected back + * to the specified URL. From there, you just need to perform a query to check for the auth token. + * (See Below) + */ + + // Check for the auth token, once returning to the application + plexOauth + .checkForAuthToken(pinId) + .then((authToken) => { + console.log(authToken); // Returns the auth token if set, otherwise returns null + + // An auth token will only be null if the user never signs into the hosted UI, or you stop checking for a new one before they can log in + }) + .catch((err) => { + throw err; + }); + }) + .catch((err) => { + throw err; + }); + function isHidden(id) { if (activePage === id) { return false; @@ -195,10 +240,14 @@ function App() { type="password" > + + + - ); diff --git a/yarn.lock b/yarn.lock index 5a8a155..81bdf18 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2498,6 +2498,13 @@ "resolved" "https://registry.npmjs.org/axe-core/-/axe-core-4.4.1.tgz" "version" "4.4.1" +"axios@^0.26.0": + "integrity" "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==" + "resolved" "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz" + "version" "0.26.1" + dependencies: + "follow-redirects" "^1.14.8" + "axios@^0.27.2": "integrity" "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==" "resolved" "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz" @@ -4122,6 +4129,11 @@ "runtime-required" "^1.1.0" "watchboy" "^0.4.3" +"emitter-component@^1.1.1": + "integrity" "sha512-G+mpdiAySMuB7kesVRLuyvYRqDmshB7ReKEVuyBPkzQlmiDiLrt7hHHIy4Aff552bgknVN7B2/d3lzhGO5dvpQ==" + "resolved" "https://registry.npmjs.org/emitter-component/-/emitter-component-1.1.1.tgz" + "version" "1.1.1" + "emittery@^0.10.2": "integrity" "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==" "resolved" "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz" @@ -4931,7 +4943,7 @@ "resolved" "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz" "version" "3.2.5" -"follow-redirects@^1.0.0", "follow-redirects@^1.14.9": +"follow-redirects@^1.0.0", "follow-redirects@^1.14.8", "follow-redirects@^1.14.9": "integrity" "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" "resolved" "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz" "version" "1.14.9" @@ -5024,6 +5036,11 @@ "resolved" "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" "version" "1.0.0" +"fs@^0.0.1-security": + "integrity" "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + "resolved" "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz" + "version" "0.0.1-security" + "fsevents@^2.3.2", "fsevents@~2.3.2": "integrity" "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==" "resolved" "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" @@ -7656,6 +7673,14 @@ "resolved" "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" "version" "4.0.0" +"path@^0.12.7": + "integrity" "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==" + "resolved" "https://registry.npmjs.org/path/-/path-0.12.7.tgz" + "version" "0.12.7" + dependencies: + "process" "^0.11.1" + "util" "^0.10.3" + "pend@~1.2.0": "integrity" "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" "resolved" "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz" @@ -7739,6 +7764,13 @@ "uuid" "^3.0.0" "xml2js" "0.4.16" +"plex-oauth@^2.0.2": + "integrity" "sha512-tbs/zyukFdHYi/nS/VqW1GgquPTIs1RgWXINlBZsyqfO7a3x6rfQ7av0/dRotxyKkBq6xIKLcQGdCmHn9UDnrQ==" + "resolved" "https://registry.npmjs.org/plex-oauth/-/plex-oauth-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "axios" "^0.26.0" + "plist@^3.0.1", "plist@^3.0.4": "integrity" "sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA==" "resolved" "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz" @@ -8052,6 +8084,11 @@ "resolved" "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" "version" "2.0.1" +"process@^0.11.1": + "integrity" "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" + "resolved" "https://registry.npmjs.org/process/-/process-0.11.10.tgz" + "version" "0.11.10" + "progress@^2.0.3": "integrity" "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" "resolved" "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" @@ -9526,6 +9563,13 @@ "resolved" "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz" "version" "1.1.1" +"stream@^0.0.2": + "integrity" "sha512-gCq3NDI2P35B2n6t76YJuOp7d6cN/C7Rt0577l91wllh0sY9ZBuw9KaSGqH/b0hzn3CWWJbpbW0W0WvQ1H/Q7g==" + "resolved" "https://registry.npmjs.org/stream/-/stream-0.0.2.tgz" + "version" "0.0.2" + dependencies: + "emitter-component" "^1.1.1" + "string_decoder@^1.1.1", "string_decoder@~1.1.1": "integrity" "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==" "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" @@ -10188,6 +10232,13 @@ "resolved" "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" "version" "1.0.2" +"util@^0.10.3": + "integrity" "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==" + "resolved" "https://registry.npmjs.org/util/-/util-0.10.4.tgz" + "version" "0.10.4" + dependencies: + "inherits" "2.0.3" + "utila@~0.4": "integrity" "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=" "resolved" "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz"