aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2018-01-04 10:17:48 +0100
committerLibravatar GitHub <noreply@github.com>2018-01-04 10:17:48 +0100
commitd375d08684a457ec6a125f2a5d3a73562826ba05 (patch)
tree6322d2207545464064e24f6bdd2f9724d1e4b813
parentMerge pull request #533 from meetfranz/feature/ux-service-search (diff)
parentMerge branch 'service-cache-cleanup' of https://github.com/dannyqiu/franz int... (diff)
downloadferdium-app-d375d08684a457ec6a125f2a5d3a73562826ba05.tar.gz
ferdium-app-d375d08684a457ec6a125f2a5d3a73562826ba05.tar.zst
ferdium-app-d375d08684a457ec6a125f2a5d3a73562826ba05.zip
Merge pull request #517 from dannyqiu/service-cache-cleanup
Service cache cleanup
-rw-r--r--package.json6
-rw-r--r--src/actions/app.js1
-rw-r--r--src/actions/service.js3
-rw-r--r--src/api/LocalApi.js8
-rw-r--r--src/api/ServicesApi.js7
-rw-r--r--src/api/server/LocalApi.js34
-rw-r--r--src/api/server/ServerApi.js6
-rw-r--r--src/components/settings/settings/EditSettingsForm.js38
-rw-r--r--src/containers/settings/EditSettingsScreen.js17
-rw-r--r--src/electron/ipc-api/autoUpdate.js3
-rw-r--r--src/helpers/service-helpers.js20
-rw-r--r--src/i18n/locales/en-US.json3
-rw-r--r--src/index.js1
-rw-r--r--src/stores/AppStore.js32
-rw-r--r--src/stores/ServicesStore.js9
-rw-r--r--src/styles/button.scss12
-rw-r--r--yarn.lock133
17 files changed, 318 insertions, 15 deletions
diff --git a/package.json b/package.json
index 9c111d336..0a2bd8991 100644
--- a/package.json
+++ b/package.json
@@ -34,8 +34,9 @@
34 "babel-polyfill": "^6.23.0", 34 "babel-polyfill": "^6.23.0",
35 "babel-runtime": "^6.23.0", 35 "babel-runtime": "^6.23.0",
36 "classnames": "^2.2.5", 36 "classnames": "^2.2.5",
37 "du": "^0.1.0",
37 "electron-fetch": "^1.1.0", 38 "electron-fetch": "^1.1.0",
38 "electron-spellchecker": "^1.2.0", 39 "electron-spellchecker": "^1.1.2",
39 "electron-updater": "^2.4.3", 40 "electron-updater": "^2.4.3",
40 "electron-window-state": "^4.1.0", 41 "electron-window-state": "^4.1.0",
41 "fs-extra": "^3.0.1", 42 "fs-extra": "^3.0.1",
@@ -54,6 +55,7 @@
54 "mobx-react-router": "^3.1.2", 55 "mobx-react-router": "^3.1.2",
55 "moment": "^2.17.1", 56 "moment": "^2.17.1",
56 "normalize-url": "^1.9.1", 57 "normalize-url": "^1.9.1",
58 "pretty-bytes": "^4.0.2",
57 "prop-types": "^15.5.10", 59 "prop-types": "^15.5.10",
58 "prop-types-extended": "^0.2.1", 60 "prop-types-extended": "^0.2.1",
59 "react": "^15.4.1", 61 "react": "^15.4.1",
@@ -104,7 +106,7 @@
104 "gulp-sass": "^3.1.0", 106 "gulp-sass": "^3.1.0",
105 "gulp-sass-variables": "^1.1.1", 107 "gulp-sass-variables": "^1.1.1",
106 "gulp-server-livereload": "^1.9.2", 108 "gulp-server-livereload": "^1.9.2",
107 "node-sass": "^4.5.3" 109 "node-sass": "^4.7.2"
108 }, 110 },
109 "config": { 111 "config": {
110 "commitizen": { 112 "commitizen": {
diff --git a/src/actions/app.js b/src/actions/app.js
index e4f648fc9..e6f7f22ba 100644
--- a/src/actions/app.js
+++ b/src/actions/app.js
@@ -25,4 +25,5 @@ export default {
25 overrideSystemMute: PropTypes.bool, 25 overrideSystemMute: PropTypes.bool,
26 }, 26 },
27 toggleMuteApp: {}, 27 toggleMuteApp: {},
28 clearAllCache: {},
28}; 29};
diff --git a/src/actions/service.js b/src/actions/service.js
index e3100e986..5d483b12a 100644
--- a/src/actions/service.js
+++ b/src/actions/service.js
@@ -25,6 +25,9 @@ export default {
25 serviceId: PropTypes.string.isRequired, 25 serviceId: PropTypes.string.isRequired,
26 redirect: PropTypes.string, 26 redirect: PropTypes.string,
27 }, 27 },
28 clearCache: {
29 serviceId: PropTypes.string.isRequired,
30 },
28 setUnreadMessageCount: { 31 setUnreadMessageCount: {
29 serviceId: PropTypes.string.isRequired, 32 serviceId: PropTypes.string.isRequired,
30 count: PropTypes.object.isRequired, 33 count: PropTypes.object.isRequired,
diff --git a/src/api/LocalApi.js b/src/api/LocalApi.js
index 6f2b049d6..3f84f8a0b 100644
--- a/src/api/LocalApi.js
+++ b/src/api/LocalApi.js
@@ -15,4 +15,12 @@ export default class LocalApi {
15 removeKey(key) { 15 removeKey(key) {
16 return this.local.removeKey(key); 16 return this.local.removeKey(key);
17 } 17 }
18
19 getAppCacheSize() {
20 return this.local.getAppCacheSize();
21 }
22
23 clearAppCache() {
24 return this.local.clearAppCache();
25 }
18} 26}
diff --git a/src/api/ServicesApi.js b/src/api/ServicesApi.js
index 3cb40ba0d..36ed9482f 100644
--- a/src/api/ServicesApi.js
+++ b/src/api/ServicesApi.js
@@ -1,5 +1,6 @@
1export default class ServicesApi { 1export default class ServicesApi {
2 constructor(server) { 2 constructor(server, local) {
3 this.local = local;
3 this.server = server; 4 this.server = server;
4 } 5 }
5 6
@@ -30,4 +31,8 @@ export default class ServicesApi {
30 reorder(data) { 31 reorder(data) {
31 return this.server.reorderService(data); 32 return this.server.reorderService(data);
32 } 33 }
34
35 clearCache(serviceId) {
36 return this.local.clearCache(serviceId);
37 }
33} 38}
diff --git a/src/api/server/LocalApi.js b/src/api/server/LocalApi.js
index 79ac6e12f..e95d750ac 100644
--- a/src/api/server/LocalApi.js
+++ b/src/api/server/LocalApi.js
@@ -1,3 +1,10 @@
1import { remote } from 'electron';
2import du from 'du';
3
4import { getServicePartitionsDirectory } from '../../helpers/service-helpers.js';
5
6const { session } = remote;
7
1export default class LocalApi { 8export default class LocalApi {
2 // App 9 // App
3 async updateAppSettings(data) { 10 async updateAppSettings(data) {
@@ -30,4 +37,31 @@ export default class LocalApi {
30 localStorage.setItem('app', JSON.stringify(settings)); 37 localStorage.setItem('app', JSON.stringify(settings));
31 } 38 }
32 } 39 }
40
41 // Services
42 async getAppCacheSize() {
43 const partitionsDir = getServicePartitionsDirectory();
44 return new Promise((resolve, reject) => {
45 du(partitionsDir, (err, size) => {
46 if (err) reject(err);
47
48 console.debug('LocalApi::getAppCacheSize resolves', size);
49 resolve(size);
50 });
51 });
52 }
53
54 async clearCache(serviceId) {
55 const s = session.fromPartition(`persist:service-${serviceId}`);
56
57 console.debug('LocalApi::clearCache resolves', serviceId);
58 return new Promise(resolve => s.clearCache(resolve));
59 }
60
61 async clearAppCache() {
62 const s = session.defaultSession;
63
64 console.debug('LocalApi::clearCache clearAppCache');
65 return new Promise(resolve => s.clearCache(resolve));
66 }
33} 67}
diff --git a/src/api/server/ServerApi.js b/src/api/server/ServerApi.js
index 8b3136d27..d75d2e559 100644
--- a/src/api/server/ServerApi.js
+++ b/src/api/server/ServerApi.js
@@ -22,6 +22,10 @@ import {
22 loadRecipeConfig, 22 loadRecipeConfig,
23} from '../../helpers/recipe-helpers'; 23} from '../../helpers/recipe-helpers';
24 24
25import {
26 removeServicePartitionDirectory,
27} from '../../helpers/service-helpers.js';
28
25module.paths.unshift( 29module.paths.unshift(
26 getDevRecipeDirectory(), 30 getDevRecipeDirectory(),
27 getRecipeDirectory(), 31 getRecipeDirectory(),
@@ -210,6 +214,8 @@ export default class ServerApi {
210 } 214 }
211 const data = await request.json(); 215 const data = await request.json();
212 216
217 removeServicePartitionDirectory(id, true);
218
213 console.debug('ServerApi::deleteService resolves', data); 219 console.debug('ServerApi::deleteService resolves', data);
214 return data; 220 return data;
215 } 221 }
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js
index ff398aa33..72aa5a8af 100644
--- a/src/components/settings/settings/EditSettingsForm.js
+++ b/src/components/settings/settings/EditSettingsForm.js
@@ -40,6 +40,18 @@ const messages = defineMessages({
40 id: 'settings.app.translationHelp', 40 id: 'settings.app.translationHelp',
41 defaultMessage: '!!!Help us to translate Franz into your language.', 41 defaultMessage: '!!!Help us to translate Franz into your language.',
42 }, 42 },
43 subheadlineCache: {
44 id: 'settings.app.subheadlineCache',
45 defaultMessage: '!!!Cache',
46 },
47 cacheInfo: {
48 id: 'settings.app.cacheInfo',
49 defaultMessage: '!!!Franz cache is currently using {size} of disk space.',
50 },
51 buttonClearAllCache: {
52 id: 'settings.app.buttonClearAllCache',
53 defaultMessage: '!!!Clear cache',
54 },
43 buttonSearchForUpdate: { 55 buttonSearchForUpdate: {
44 id: 'settings.app.buttonSearchForUpdate', 56 id: 'settings.app.buttonSearchForUpdate',
45 defaultMessage: '!!!Check for updates', 57 defaultMessage: '!!!Check for updates',
@@ -77,6 +89,9 @@ export default class EditSettingsForm extends Component {
77 isUpdateAvailable: PropTypes.bool.isRequired, 89 isUpdateAvailable: PropTypes.bool.isRequired,
78 noUpdateAvailable: PropTypes.bool.isRequired, 90 noUpdateAvailable: PropTypes.bool.isRequired,
79 updateIsReadyToInstall: PropTypes.bool.isRequired, 91 updateIsReadyToInstall: PropTypes.bool.isRequired,
92 isClearingAllCache: PropTypes.bool.isRequired,
93 onClearAllCache: PropTypes.func.isRequired,
94 cacheSize: PropTypes.string.isRequired,
80 }; 95 };
81 96
82 static contextTypes = { 97 static contextTypes = {
@@ -103,6 +118,9 @@ export default class EditSettingsForm extends Component {
103 isUpdateAvailable, 118 isUpdateAvailable,
104 noUpdateAvailable, 119 noUpdateAvailable,
105 updateIsReadyToInstall, 120 updateIsReadyToInstall,
121 isClearingAllCache,
122 onClearAllCache,
123 cacheSize,
106 } = this.props; 124 } = this.props;
107 const { intl } = this.context; 125 const { intl } = this.context;
108 126
@@ -155,6 +173,25 @@ export default class EditSettingsForm extends Component {
155 <h2 id="advanced">{intl.formatMessage(messages.headlineAdvanced)}</h2> 173 <h2 id="advanced">{intl.formatMessage(messages.headlineAdvanced)}</h2>
156 <Toggle field={form.$('enableSpellchecking')} /> 174 <Toggle field={form.$('enableSpellchecking')} />
157 {/* <Select field={form.$('spellcheckingLanguage')} /> */} 175 {/* <Select field={form.$('spellcheckingLanguage')} /> */}
176 <div className="settings__settings-group">
177 <h3>
178 {intl.formatMessage(messages.subheadlineCache)}
179 </h3>
180 <p>
181 {intl.formatMessage(messages.cacheInfo, {
182 size: cacheSize,
183 })}
184 </p>
185 <p>
186 <Button
187 buttonType="secondary"
188 label={intl.formatMessage(messages.buttonClearAllCache)}
189 onClick={onClearAllCache}
190 disabled={isClearingAllCache}
191 loaded={!isClearingAllCache}
192 />
193 </p>
194 </div>
158 195
159 {/* Updates */} 196 {/* Updates */}
160 <h2 id="updates">{intl.formatMessage(messages.headlineUpdates)}</h2> 197 <h2 id="updates">{intl.formatMessage(messages.headlineUpdates)}</h2>
@@ -165,6 +202,7 @@ export default class EditSettingsForm extends Component {
165 /> 202 />
166 ) : ( 203 ) : (
167 <Button 204 <Button
205 buttonType="secondary"
168 label={intl.formatMessage(updateButtonLabelMessage)} 206 label={intl.formatMessage(updateButtonLabelMessage)}
169 onClick={checkForUpdates} 207 onClick={checkForUpdates}
170 disabled={isCheckingForUpdates || isUpdateAvailable} 208 disabled={isCheckingForUpdates || isUpdateAvailable}
diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js
index 45ded9e5c..9fa815a0a 100644
--- a/src/containers/settings/EditSettingsScreen.js
+++ b/src/containers/settings/EditSettingsScreen.js
@@ -193,8 +193,17 @@ export default class EditSettingsScreen extends Component {
193 } 193 }
194 194
195 render() { 195 render() {
196 const { updateStatus, updateStatusTypes } = this.props.stores.app; 196 const {
197 const { checkForUpdates, installUpdate } = this.props.actions.app; 197 updateStatus,
198 cacheSize,
199 updateStatusTypes,
200 isClearingAllCache,
201 } = this.props.stores.app;
202 const {
203 checkForUpdates,
204 installUpdate,
205 clearAllCache,
206 } = this.props.actions.app;
198 const form = this.prepareForm(); 207 const form = this.prepareForm();
199 208
200 return ( 209 return (
@@ -207,6 +216,9 @@ export default class EditSettingsScreen extends Component {
207 noUpdateAvailable={updateStatus === updateStatusTypes.NOT_AVAILABLE} 216 noUpdateAvailable={updateStatus === updateStatusTypes.NOT_AVAILABLE}
208 updateIsReadyToInstall={updateStatus === updateStatusTypes.DOWNLOADED} 217 updateIsReadyToInstall={updateStatus === updateStatusTypes.DOWNLOADED}
209 onSubmit={d => this.onSubmit(d)} 218 onSubmit={d => this.onSubmit(d)}
219 cacheSize={cacheSize}
220 isClearingAllCache={isClearingAllCache}
221 onClearAllCache={clearAllCache}
210 /> 222 />
211 ); 223 );
212 } 224 }
@@ -223,6 +235,7 @@ EditSettingsScreen.wrappedComponent.propTypes = {
223 launchOnStartup: PropTypes.func.isRequired, 235 launchOnStartup: PropTypes.func.isRequired,
224 checkForUpdates: PropTypes.func.isRequired, 236 checkForUpdates: PropTypes.func.isRequired,
225 installUpdate: PropTypes.func.isRequired, 237 installUpdate: PropTypes.func.isRequired,
238 clearAllCache: PropTypes.func.isRequired,
226 }).isRequired, 239 }).isRequired,
227 settings: PropTypes.shape({ 240 settings: PropTypes.shape({
228 update: PropTypes.func.isRequired, 241 update: PropTypes.func.isRequired,
diff --git a/src/electron/ipc-api/autoUpdate.js b/src/electron/ipc-api/autoUpdate.js
index 7bc193e2d..ba49a2f97 100644
--- a/src/electron/ipc-api/autoUpdate.js
+++ b/src/electron/ipc-api/autoUpdate.js
@@ -1,8 +1,9 @@
1import { app, ipcMain } from 'electron'; 1import { app, ipcMain } from 'electron';
2import { autoUpdater } from 'electron-updater'; 2import { autoUpdater } from 'electron-updater';
3import { isDevMode } from '../../environment.js';
3 4
4export default (params) => { 5export default (params) => {
5 if (process.platform === 'darwin' || process.platform === 'win32') { 6 if (!isDevMode && (process.platform === 'darwin' || process.platform === 'win32')) {
6 // autoUpdater.setFeedURL(updateUrl); 7 // autoUpdater.setFeedURL(updateUrl);
7 ipcMain.on('autoUpdate', (event, args) => { 8 ipcMain.on('autoUpdate', (event, args) => {
8 try { 9 try {
diff --git a/src/helpers/service-helpers.js b/src/helpers/service-helpers.js
new file mode 100644
index 000000000..5f63f6b7c
--- /dev/null
+++ b/src/helpers/service-helpers.js
@@ -0,0 +1,20 @@
1import path from 'path';
2import { remote } from 'electron';
3import fs from 'fs-extra';
4
5const app = remote.app;
6
7export function getServicePartitionsDirectory() {
8 return path.join(app.getPath('userData'), 'Partitions');
9}
10
11export function removeServicePartitionDirectory(id = '', addServicePrefix = false) {
12 const servicePartition = path.join(getServicePartitionsDirectory(), `${addServicePrefix ? 'service-' : ''}${id}`);
13
14 return fs.remove(servicePartition);
15}
16
17export async function getServiceIdsFromPartitions() {
18 const files = await fs.readdir(getServicePartitionsDirectory());
19 return files.filter(n => n !== '__chrome_extension');
20}
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json
index da5d4a143..2bfbf2455 100644
--- a/src/i18n/locales/en-US.json
+++ b/src/i18n/locales/en-US.json
@@ -150,6 +150,9 @@
150 "settings.app.updateStatusSearching": "Is searching for update", 150 "settings.app.updateStatusSearching": "Is searching for update",
151 "settings.app.updateStatusAvailable": "Update available, downloading...", 151 "settings.app.updateStatusAvailable": "Update available, downloading...",
152 "settings.app.updateStatusUpToDate": "You are using the latest version of Franz", 152 "settings.app.updateStatusUpToDate": "You are using the latest version of Franz",
153 "settings.app.subheadlineCache": "Cache",
154 "settings.app.cacheInfo": "Franz cache is currently using {size} of disk space.",
155 "settings.app.buttonClearAllCache": "Clear cache",
153 "settings.app.form.autoLaunchOnStart": "Launch Franz on start", 156 "settings.app.form.autoLaunchOnStart": "Launch Franz on start",
154 "settings.app.form.autoLaunchInBackground": "Open in background", 157 "settings.app.form.autoLaunchInBackground": "Open in background",
155 "settings.app.form.enableSystemTray": "Show Franz in system tray", 158 "settings.app.form.enableSystemTray": "Show Franz in system tray",
diff --git a/src/index.js b/src/index.js
index a047e2bc1..f82bb3590 100644
--- a/src/index.js
+++ b/src/index.js
@@ -44,6 +44,7 @@ const isSecondInstance = app.makeSingleInstance((argv) => {
44}); 44});
45 45
46if (isSecondInstance) { 46if (isSecondInstance) {
47 console.log('An instance of Franz is already running. Exiting...');
47 app.exit(); 48 app.exit();
48} 49}
49 50
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js
index aa6e801ff..e33f50f05 100644
--- a/src/stores/AppStore.js
+++ b/src/stores/AppStore.js
@@ -1,10 +1,11 @@
1import { remote, ipcRenderer, shell } from 'electron'; 1import { remote, ipcRenderer, shell } from 'electron';
2import { action, observable } from 'mobx'; 2import { action, computed, observable } from 'mobx';
3import moment from 'moment'; 3import moment from 'moment';
4import key from 'keymaster'; 4import key from 'keymaster';
5import { getDoNotDisturb } from '@meetfranz/electron-notification-state'; 5import { getDoNotDisturb } from '@meetfranz/electron-notification-state';
6import idleTimer from '@paulcbetts/system-idle-time'; 6import idleTimer from '@paulcbetts/system-idle-time';
7import AutoLaunch from 'auto-launch'; 7import AutoLaunch from 'auto-launch';
8import prettyBytes from 'pretty-bytes';
8 9
9import Store from './lib/Store'; 10import Store from './lib/Store';
10import Request from './lib/Request'; 11import Request from './lib/Request';
@@ -14,7 +15,10 @@ import locales from '../i18n/translations';
14import { gaEvent } from '../lib/analytics'; 15import { gaEvent } from '../lib/analytics';
15import Miner from '../lib/Miner'; 16import Miner from '../lib/Miner';
16 17
18import { getServiceIdsFromPartitions, removeServicePartitionDirectory } from '../helpers/service-helpers.js';
19
17const { app } = remote; 20const { app } = remote;
21
18const defaultLocale = DEFAULT_APP_SETTINGS.locale; 22const defaultLocale = DEFAULT_APP_SETTINGS.locale;
19const autoLauncher = new AutoLaunch({ 23const autoLauncher = new AutoLaunch({
20 name: 'Franz', 24 name: 'Franz',
@@ -30,6 +34,8 @@ export default class AppStore extends Store {
30 }; 34 };
31 35
32 @observable healthCheckRequest = new Request(this.api.app, 'health'); 36 @observable healthCheckRequest = new Request(this.api.app, 'health');
37 @observable getAppCacheSizeRequest = new Request(this.api.local, 'getAppCacheSize');
38 @observable clearAppCacheRequest = new Request(this.api.local, 'clearAppCache');
33 39
34 @observable autoLaunchOnStart = true; 40 @observable autoLaunchOnStart = true;
35 41
@@ -47,6 +53,8 @@ export default class AppStore extends Store {
47 53
48 @observable isSystemMuteOverridden = false; 54 @observable isSystemMuteOverridden = false;
49 55
56 @observable isClearingAllCache = false;
57
50 constructor(...args) { 58 constructor(...args) {
51 super(...args); 59 super(...args);
52 60
@@ -61,6 +69,7 @@ export default class AppStore extends Store {
61 this.actions.app.healthCheck.listen(this._healthCheck.bind(this)); 69 this.actions.app.healthCheck.listen(this._healthCheck.bind(this));
62 this.actions.app.muteApp.listen(this._muteApp.bind(this)); 70 this.actions.app.muteApp.listen(this._muteApp.bind(this));
63 this.actions.app.toggleMuteApp.listen(this._toggleMuteApp.bind(this)); 71 this.actions.app.toggleMuteApp.listen(this._toggleMuteApp.bind(this));
72 this.actions.app.clearAllCache.listen(this._clearAllCache.bind(this));
64 73
65 this.registerReactions([ 74 this.registerReactions([
66 this._offlineCheck.bind(this), 75 this._offlineCheck.bind(this),
@@ -165,6 +174,10 @@ export default class AppStore extends Store {
165 this._healthCheck(); 174 this._healthCheck();
166 } 175 }
167 176
177 @computed get cacheSize() {
178 return prettyBytes(this.getAppCacheSizeRequest.execute().result || 0);
179 }
180
168 // Actions 181 // Actions
169 @action _notify({ title, options, notificationId, serviceId = null }) { 182 @action _notify({ title, options, notificationId, serviceId = null }) {
170 if (this.stores.settings.all.isAppMuted) return; 183 if (this.stores.settings.all.isAppMuted) return;
@@ -255,6 +268,23 @@ export default class AppStore extends Store {
255 this._muteApp({ isMuted: !this.stores.settings.all.isAppMuted }); 268 this._muteApp({ isMuted: !this.stores.settings.all.isAppMuted });
256 } 269 }
257 270
271 @action async _clearAllCache() {
272 this.isClearingAllCache = true;
273 const clearAppCache = this.clearAppCacheRequest.execute();
274 const allServiceIds = await getServiceIdsFromPartitions();
275 const allOrphanedServiceIds = allServiceIds.filter(id => !this.stores.services.all.find(s => id.replace('service-', '') === s.id));
276
277 await Promise.all(allOrphanedServiceIds.map(id => removeServicePartitionDirectory(id)));
278
279 await Promise.all(this.stores.services.all.map(s => this.actions.service.clearCache({ serviceId: s.id })));
280
281 await clearAppCache._promise;
282
283 this.getAppCacheSizeRequest.execute();
284
285 this.isClearingAllCache = false;
286 }
287
258 // Reactions 288 // Reactions
259 _offlineCheck() { 289 _offlineCheck() {
260 if (!this.isOnline) { 290 if (!this.isOnline) {
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index 3abb57d1d..87ee57a0d 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -16,6 +16,7 @@ export default class ServicesStore extends Store {
16 @observable updateServiceRequest = new Request(this.api.services, 'update'); 16 @observable updateServiceRequest = new Request(this.api.services, 'update');
17 @observable reorderServicesRequest = new Request(this.api.services, 'reorder'); 17 @observable reorderServicesRequest = new Request(this.api.services, 'reorder');
18 @observable deleteServiceRequest = new Request(this.api.services, 'delete'); 18 @observable deleteServiceRequest = new Request(this.api.services, 'delete');
19 @observable clearCacheRequest = new Request(this.api.services, 'clearCache');
19 20
20 @observable filterNeedle = null; 21 @observable filterNeedle = null;
21 22
@@ -31,6 +32,7 @@ export default class ServicesStore extends Store {
31 this.actions.service.createFromLegacyService.listen(this._createFromLegacyService.bind(this)); 32 this.actions.service.createFromLegacyService.listen(this._createFromLegacyService.bind(this));
32 this.actions.service.updateService.listen(this._updateService.bind(this)); 33 this.actions.service.updateService.listen(this._updateService.bind(this));
33 this.actions.service.deleteService.listen(this._deleteService.bind(this)); 34 this.actions.service.deleteService.listen(this._deleteService.bind(this));
35 this.actions.service.clearCache.listen(this._clearCache.bind(this));
34 this.actions.service.setWebviewReference.listen(this._setWebviewReference.bind(this)); 36 this.actions.service.setWebviewReference.listen(this._setWebviewReference.bind(this));
35 this.actions.service.focusService.listen(this._focusService.bind(this)); 37 this.actions.service.focusService.listen(this._focusService.bind(this));
36 this.actions.service.focusActiveService.listen(this._focusActiveService.bind(this)); 38 this.actions.service.focusActiveService.listen(this._focusActiveService.bind(this));
@@ -205,6 +207,13 @@ export default class ServicesStore extends Store {
205 gaEvent('Service', 'delete', service.recipe.id); 207 gaEvent('Service', 'delete', service.recipe.id);
206 } 208 }
207 209
210 @action async _clearCache({ serviceId }) {
211 this.clearCacheRequest.reset();
212 const request = this.clearCacheRequest.execute(serviceId);
213 await request._promise;
214 gaEvent('Service', 'clear cache');
215 }
216
208 @action _setActive({ serviceId }) { 217 @action _setActive({ serviceId }) {
209 const service = this.one(serviceId); 218 const service = this.one(serviceId);
210 219
diff --git a/src/styles/button.scss b/src/styles/button.scss
index 75d2cb1d4..8d2adbbcc 100644
--- a/src/styles/button.scss
+++ b/src/styles/button.scss
@@ -48,6 +48,18 @@
48 } 48 }
49 } 49 }
50 50
51 &.franz-form__button--warning {
52 background: $theme-brand-warning;
53
54 &:hover {
55 background: darken($theme-brand-warning, 5%);
56 }
57
58 &:active {
59 background: lighten($theme-brand-warning, 5%);
60 }
61 }
62
51 &.franz-form__button--inverted { 63 &.franz-form__button--inverted {
52 background: none; 64 background: none;
53 padding: 10px 20px; 65 padding: 10px 20px;
diff --git a/yarn.lock b/yarn.lock
index c662ce63f..dbcb33647 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -39,7 +39,7 @@
39 rimraf "^2.4.0" 39 rimraf "^2.4.0"
40 underscore "^1.6.0" 40 underscore "^1.6.0"
41 41
42"@paulcbetts/spellchecker@^4.0.5": 42"@paulcbetts/spellchecker@^4.0.6":
43 version "4.0.6" 43 version "4.0.6"
44 resolved "https://registry.yarnpkg.com/@paulcbetts/spellchecker/-/spellchecker-4.0.6.tgz#79ef1f9c19c5a3156921ccaa9ffdc3efbbee47e3" 44 resolved "https://registry.yarnpkg.com/@paulcbetts/spellchecker/-/spellchecker-4.0.6.tgz#79ef1f9c19c5a3156921ccaa9ffdc3efbbee47e3"
45 dependencies: 45 dependencies:
@@ -333,6 +333,10 @@ async@^0.9.0:
333 version "0.9.2" 333 version "0.9.2"
334 resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" 334 resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
335 335
336async@~0.1.22:
337 version "0.1.22"
338 resolved "https://registry.yarnpkg.com/async/-/async-0.1.22.tgz#0fc1aaa088a0e3ef0ebe2d8831bab0dcf8845061"
339
336asynckit@^0.4.0: 340asynckit@^0.4.0:
337 version "0.4.0" 341 version "0.4.0"
338 resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 342 resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
@@ -1303,6 +1307,10 @@ capture-stack-trace@^1.0.0:
1303 version "1.0.0" 1307 version "1.0.0"
1304 resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" 1308 resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d"
1305 1309
1310caseless@~0.11.0:
1311 version "0.11.0"
1312 resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7"
1313
1306caseless@~0.12.0: 1314caseless@~0.12.0:
1307 version "0.12.0" 1315 version "0.12.0"
1308 resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" 1316 resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
@@ -1779,6 +1787,12 @@ dotenv@^4.0.0:
1779 version "4.0.0" 1787 version "4.0.0"
1780 resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-4.0.0.tgz#864ef1379aced55ce6f95debecdce179f7a0cd1d" 1788 resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-4.0.0.tgz#864ef1379aced55ce6f95debecdce179f7a0cd1d"
1781 1789
1790du@^0.1.0:
1791 version "0.1.0"
1792 resolved "https://registry.yarnpkg.com/du/-/du-0.1.0.tgz#f26e340a09c7bc5b6fd69af6dbadea60fa8c6f4d"
1793 dependencies:
1794 async "~0.1.22"
1795
1782duplexer2@0.0.2, duplexer2@~0.0.2: 1796duplexer2@0.0.2, duplexer2@~0.0.2:
1783 version "0.0.2" 1797 version "0.0.2"
1784 resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" 1798 resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db"
@@ -2013,12 +2027,12 @@ electron-remote@^1.1.1:
2013 rxjs "^5.0.0-beta.12" 2027 rxjs "^5.0.0-beta.12"
2014 xmlhttprequest "^1.8.0" 2028 xmlhttprequest "^1.8.0"
2015 2029
2016electron-spellchecker@^1.2.0: 2030electron-spellchecker@^1.1.2:
2017 version "1.2.0" 2031 version "1.1.2"
2018 resolved "https://registry.yarnpkg.com/electron-spellchecker/-/electron-spellchecker-1.2.0.tgz#f6306afd4078244c1e6311370667d95b873fbcbb" 2032 resolved "https://registry.yarnpkg.com/electron-spellchecker/-/electron-spellchecker-1.1.2.tgz#5fbe1e65d246b77e6e7433ee2387d9d26010f7a8"
2019 dependencies: 2033 dependencies:
2020 "@paulcbetts/cld" "^2.4.6" 2034 "@paulcbetts/cld" "^2.4.6"
2021 "@paulcbetts/spellchecker" "^4.0.5" 2035 "@paulcbetts/spellchecker" "^4.0.6"
2022 bcp47 "^1.1.2" 2036 bcp47 "^1.1.2"
2023 debug "^2.6.3" 2037 debug "^2.6.3"
2024 electron-remote "^1.1.1" 2038 electron-remote "^1.1.1"
@@ -2724,6 +2738,16 @@ gaze@^1.0.0:
2724 dependencies: 2738 dependencies:
2725 globule "^1.0.0" 2739 globule "^1.0.0"
2726 2740
2741generate-function@^2.0.0:
2742 version "2.0.0"
2743 resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74"
2744
2745generate-object-property@^1.1.0:
2746 version "1.2.0"
2747 resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0"
2748 dependencies:
2749 is-property "^1.0.0"
2750
2727get-caller-file@^1.0.1: 2751get-caller-file@^1.0.1:
2728 version "1.0.2" 2752 version "1.0.2"
2729 resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" 2753 resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
@@ -3118,6 +3142,15 @@ har-schema@^1.0.5:
3118 version "1.0.5" 3142 version "1.0.5"
3119 resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" 3143 resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
3120 3144
3145har-validator@~2.0.6:
3146 version "2.0.6"
3147 resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d"
3148 dependencies:
3149 chalk "^1.1.1"
3150 commander "^2.9.0"
3151 is-my-json-valid "^2.12.4"
3152 pinkie-promise "^2.0.0"
3153
3121har-validator@~4.2.1: 3154har-validator@~4.2.1:
3122 version "4.2.1" 3155 version "4.2.1"
3123 resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" 3156 resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
@@ -3433,6 +3466,15 @@ is-glob@^3.1.0:
3433 dependencies: 3466 dependencies:
3434 is-extglob "^2.1.0" 3467 is-extglob "^2.1.0"
3435 3468
3469is-my-json-valid@^2.12.4:
3470 version "2.17.1"
3471 resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471"
3472 dependencies:
3473 generate-function "^2.0.0"
3474 generate-object-property "^1.1.0"
3475 jsonpointer "^4.0.0"
3476 xtend "^4.0.0"
3477
3436is-npm@^1.0.0: 3478is-npm@^1.0.0:
3437 version "1.0.0" 3479 version "1.0.0"
3438 resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" 3480 resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4"
@@ -3491,6 +3533,10 @@ is-promise@^2.1.0:
3491 version "2.1.0" 3533 version "2.1.0"
3492 resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" 3534 resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
3493 3535
3536is-property@^1.0.0:
3537 version "1.0.2"
3538 resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
3539
3494is-redirect@^1.0.0: 3540is-redirect@^1.0.0:
3495 version "1.0.0" 3541 version "1.0.0"
3496 resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" 3542 resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24"
@@ -3686,6 +3732,10 @@ jsonify@~0.0.0:
3686 version "0.0.0" 3732 version "0.0.0"
3687 resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" 3733 resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
3688 3734
3735jsonpointer@^4.0.0:
3736 version "4.0.1"
3737 resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
3738
3689jsonwebtoken@^7.4.1: 3739jsonwebtoken@^7.4.1:
3690 version "7.4.3" 3740 version "7.4.3"
3691 resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz#77f5021de058b605a1783fa1283e99812e645638" 3741 resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz#77f5021de058b605a1783fa1283e99812e645638"
@@ -4354,7 +4404,7 @@ node-pre-gyp@^0.6.36:
4354 tar "^2.2.1" 4404 tar "^2.2.1"
4355 tar-pack "^3.4.0" 4405 tar-pack "^3.4.0"
4356 4406
4357node-sass@^4.2.0, node-sass@^4.5.3: 4407node-sass@^4.2.0:
4358 version "4.5.3" 4408 version "4.5.3"
4359 resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.5.3.tgz#d09c9d1179641239d1b97ffc6231fdcec53e1568" 4409 resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.5.3.tgz#d09c9d1179641239d1b97ffc6231fdcec53e1568"
4360 dependencies: 4410 dependencies:
@@ -4377,6 +4427,30 @@ node-sass@^4.2.0, node-sass@^4.5.3:
4377 sass-graph "^2.1.1" 4427 sass-graph "^2.1.1"
4378 stdout-stream "^1.4.0" 4428 stdout-stream "^1.4.0"
4379 4429
4430node-sass@^4.7.2:
4431 version "4.7.2"
4432 resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.7.2.tgz#9366778ba1469eb01438a9e8592f4262bcb6794e"
4433 dependencies:
4434 async-foreach "^0.1.3"
4435 chalk "^1.1.1"
4436 cross-spawn "^3.0.0"
4437 gaze "^1.0.0"
4438 get-stdin "^4.0.1"
4439 glob "^7.0.3"
4440 in-publish "^2.0.0"
4441 lodash.assign "^4.2.0"
4442 lodash.clonedeep "^4.3.2"
4443 lodash.mergewith "^4.6.0"
4444 meow "^3.7.0"
4445 mkdirp "^0.5.1"
4446 nan "^2.3.2"
4447 node-gyp "^3.3.1"
4448 npmlog "^4.0.0"
4449 request "~2.79.0"
4450 sass-graph "^2.2.4"
4451 stdout-stream "^1.4.0"
4452 "true-case-path" "^1.0.2"
4453
4380node-watch@^0.3.4: 4454node-watch@^0.3.4:
4381 version "0.3.5" 4455 version "0.3.5"
4382 resolved "https://registry.yarnpkg.com/node-watch/-/node-watch-0.3.5.tgz#a07f253a4f538de9d4ca522dd7f1996eeec0d97e" 4456 resolved "https://registry.yarnpkg.com/node-watch/-/node-watch-0.3.5.tgz#a07f253a4f538de9d4ca522dd7f1996eeec0d97e"
@@ -4831,6 +4905,10 @@ pretty-bytes@^1.0.2, pretty-bytes@^1.0.4:
4831 get-stdin "^4.0.1" 4905 get-stdin "^4.0.1"
4832 meow "^3.1.0" 4906 meow "^3.1.0"
4833 4907
4908pretty-bytes@^4.0.2:
4909 version "4.0.2"
4910 resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9"
4911
4834pretty-hrtime@^1.0.0: 4912pretty-hrtime@^1.0.0:
4835 version "1.0.3" 4913 version "1.0.3"
4836 resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" 4914 resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
@@ -4907,6 +4985,10 @@ q@^1.1.2:
4907 version "1.5.0" 4985 version "1.5.0"
4908 resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1" 4986 resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1"
4909 4987
4988qs@~6.3.0:
4989 version "6.3.2"
4990 resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c"
4991
4910qs@~6.4.0: 4992qs@~6.4.0:
4911 version "6.4.0" 4993 version "6.4.0"
4912 resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" 4994 resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
@@ -5251,6 +5333,31 @@ request@2, request@^2.45.0, request@^2.54.0, request@^2.79.0, request@^2.81.0:
5251 tunnel-agent "^0.6.0" 5333 tunnel-agent "^0.6.0"
5252 uuid "^3.0.0" 5334 uuid "^3.0.0"
5253 5335
5336request@~2.79.0:
5337 version "2.79.0"
5338 resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de"
5339 dependencies:
5340 aws-sign2 "~0.6.0"
5341 aws4 "^1.2.1"
5342 caseless "~0.11.0"
5343 combined-stream "~1.0.5"
5344 extend "~3.0.0"
5345 forever-agent "~0.6.1"
5346 form-data "~2.1.1"
5347 har-validator "~2.0.6"
5348 hawk "~3.1.3"
5349 http-signature "~1.1.0"
5350 is-typedarray "~1.0.0"
5351 isstream "~0.1.2"
5352 json-stringify-safe "~5.0.1"
5353 mime-types "~2.1.7"
5354 oauth-sign "~0.8.1"
5355 qs "~6.3.0"
5356 stringstream "~0.0.4"
5357 tough-cookie "~2.3.0"
5358 tunnel-agent "~0.4.1"
5359 uuid "^3.0.0"
5360
5254require-directory@^2.1.1: 5361require-directory@^2.1.1:
5255 version "2.1.1" 5362 version "2.1.1"
5256 resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 5363 resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
@@ -5354,7 +5461,7 @@ sanitize-filename@^1.6.0, sanitize-filename@^1.6.1:
5354 dependencies: 5461 dependencies:
5355 truncate-utf8-bytes "^1.0.0" 5462 truncate-utf8-bytes "^1.0.0"
5356 5463
5357sass-graph@^2.1.1: 5464sass-graph@^2.1.1, sass-graph@^2.2.4:
5358 version "2.2.4" 5465 version "2.2.4"
5359 resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" 5466 resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49"
5360 dependencies: 5467 dependencies:
@@ -5924,6 +6031,12 @@ trim-right@^1.0.1:
5924 version "1.0.1" 6031 version "1.0.1"
5925 resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" 6032 resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
5926 6033
6034"true-case-path@^1.0.2":
6035 version "1.0.2"
6036 resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.2.tgz#7ec91130924766c7f573be3020c34f8fdfd00d62"
6037 dependencies:
6038 glob "^6.0.4"
6039
5927truncate-utf8-bytes@^1.0.0: 6040truncate-utf8-bytes@^1.0.0:
5928 version "1.0.2" 6041 version "1.0.2"
5929 resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b" 6042 resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b"
@@ -5940,6 +6053,10 @@ tunnel-agent@^0.6.0:
5940 dependencies: 6053 dependencies:
5941 safe-buffer "^5.0.1" 6054 safe-buffer "^5.0.1"
5942 6055
6056tunnel-agent@~0.4.1:
6057 version "0.4.3"
6058 resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb"
6059
5943tweetnacl@^0.14.3, tweetnacl@~0.14.0: 6060tweetnacl@^0.14.3, tweetnacl@~0.14.0:
5944 version "0.14.5" 6061 version "0.14.5"
5945 resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" 6062 resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
@@ -6299,7 +6416,7 @@ xmlhttprequest@^1.8.0:
6299 version "1.8.0" 6416 version "1.8.0"
6300 resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" 6417 resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"
6301 6418
6302"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: 6419"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1:
6303 version "4.0.1" 6420 version "4.0.1"
6304 resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" 6421 resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
6305 6422