diff options
author | Luke "Jared" Bennett <lbennett@gitlab.com> | 2017-05-20 20:05:31 +0100 |
---|---|---|
committer | Luke "Jared" Bennett <lbennett@gitlab.com> | 2017-05-20 20:56:10 +0100 |
commit | 71c859616524a5af903d3c736e93d7655e8a144d (patch) | |
tree | b09dbfcf20fe8230fb5e9b38e206ce0a5abb7623 | |
parent | f5f99c9037e52392ca388b6e839d93df88421c31 (diff) | |
download | gitlab-ce-sockets-frontend.tar.gz |
Added SocketManager, SubscriptionStore, Subscription, VisibilitySocketManager and refactored currently instances of Pollsockets-frontend
-rw-r--r-- | app/assets/javascripts/commit/pipelines/pipelines_table.js | 29 | ||||
-rw-r--r-- | app/assets/javascripts/issue_show/components/app.vue | 29 | ||||
-rw-r--r-- | app/assets/javascripts/issue_show/services/index.js | 16 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/poll.js | 105 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/socket/socket_manager.js | 108 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/socket/subscription.js | 68 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/socket/subscription_store.js | 27 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/socket/visibility_socket_manager.js | 24 | ||||
-rw-r--r-- | app/assets/javascripts/pipelines/components/graph/graph_component.vue | 22 | ||||
-rw-r--r-- | app/assets/javascripts/pipelines/pipelines.js | 28 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | spec/javascripts/lib/utils/poll_spec.js | 175 | ||||
-rw-r--r-- | yarn.lock | 90 |
13 files changed, 329 insertions, 394 deletions
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.js b/app/assets/javascripts/commit/pipelines/pipelines_table.js index 98698143d22..1a9ceb5a102 100644 --- a/app/assets/javascripts/commit/pipelines/pipelines_table.js +++ b/app/assets/javascripts/commit/pipelines/pipelines_table.js @@ -1,5 +1,4 @@ import Vue from 'vue'; -import Visibility from 'visibilityjs'; import pipelinesTableComponent from '../../vue_shared/components/pipelines_table'; import PipelinesService from '../../pipelines/services/pipelines_service'; import PipelineStore from '../../pipelines/stores/pipelines_store'; @@ -9,7 +8,7 @@ import errorState from '../../pipelines/components/error_state.vue'; import loadingIcon from '../../vue_shared/components/loading_icon.vue'; import '../../lib/utils/common_utils'; import '../../vue_shared/vue_resource_interceptor'; -import Poll from '../../lib/utils/poll'; +import VisibilitySocketManager from '../../lib/utils/socket/visibility_socket_manager'; /** * @@ -90,29 +89,9 @@ export default Vue.component('pipelines-table', { this.helpPagePath = element.dataset.helpPagePath; this.service = new PipelinesService(this.endpoint); - this.poll = new Poll({ - resource: this.service, - method: 'getPipelines', - successCallback: this.successCallback, + this.subscription = VisibilitySocketManager.subscribe(this.endpoint, null, { + updateCallback: this.successCallback, errorCallback: this.errorCallback, - notificationCallback: this.setIsMakingRequest, - }); - - if (!Visibility.hidden()) { - this.isLoading = true; - this.poll.makeRequest(); - } else { - // If tab is not visible we need to make the first request so we don't show the empty - // state without knowing if there are any pipelines - this.fetchPipelines(); - } - - Visibility.change(() => { - if (!Visibility.hidden()) { - this.poll.restart(); - } else { - this.poll.stop(); - } }); eventHub.$on('refreshPipelines', this.fetchPipelines); @@ -123,7 +102,7 @@ export default Vue.component('pipelines-table', { }, destroyed() { - this.poll.stop(); + VisibilitySocketManager.remove(this.subscription); }, methods: { diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue index 770a0dcd27e..50853c79afd 100644 --- a/app/assets/javascripts/issue_show/components/app.vue +++ b/app/assets/javascripts/issue_show/components/app.vue @@ -1,7 +1,5 @@ <script> -import Visibility from 'visibilityjs'; -import Poll from '../../lib/utils/poll'; -import Service from '../services/index'; +import VisibilitySocketManager from '../../lib/utils/socket/visibility_socket_manager'; import Store from '../stores'; import titleComponent from './title.vue'; import descriptionComponent from './description.vue'; @@ -52,29 +50,14 @@ export default { titleComponent, }, created() { - const resource = new Service(this.endpoint); - const poll = new Poll({ - resource, - method: 'getData', - successCallback: (res) => { - this.store.updateState(res.json()); + VisibilitySocketManager.subscribe(this.endpoint, null, { + updateCallback: (response) => { + this.store.updateState(response.json()); }, - errorCallback(err) { - throw new Error(err); + errorCallback(error) { + throw new Error(error); }, }); - - if (!Visibility.hidden()) { - poll.makeRequest(); - } - - Visibility.change(() => { - if (!Visibility.hidden()) { - poll.restart(); - } else { - poll.stop(); - } - }); }, }; </script> diff --git a/app/assets/javascripts/issue_show/services/index.js b/app/assets/javascripts/issue_show/services/index.js deleted file mode 100644 index 348ad8d6813..00000000000 --- a/app/assets/javascripts/issue_show/services/index.js +++ /dev/null @@ -1,16 +0,0 @@ -import Vue from 'vue'; -import VueResource from 'vue-resource'; - -Vue.use(VueResource); - -export default class Service { - constructor(endpoint) { - this.endpoint = endpoint; - - this.resource = Vue.resource(this.endpoint); - } - - getData() { - return this.resource.get(); - } -} diff --git a/app/assets/javascripts/lib/utils/poll.js b/app/assets/javascripts/lib/utils/poll.js deleted file mode 100644 index e31cc5fbabe..00000000000 --- a/app/assets/javascripts/lib/utils/poll.js +++ /dev/null @@ -1,105 +0,0 @@ -import httpStatusCodes from './http_status'; - -/** - * Polling utility for handling realtime updates. - * Service for vue resouce and method need to be provided as props - * - * @example - * new Poll({ - * resource: resource, - * method: 'name', - * data: {page: 1, scope: 'all'}, // optional - * successCallback: () => {}, - * errorCallback: () => {}, - * notificationCallback: () => {}, // optional - * }).makeRequest(); - * - * Usage in pipelines table with visibility lib: - * - * const poll = new Poll({ - * resource: this.service, - * method: 'getPipelines', - * data: { page: pageNumber, scope }, - * successCallback: this.successCallback, - * errorCallback: this.errorCallback, - * notificationCallback: this.updateLoading, - * }); - * - * if (!Visibility.hidden()) { - * poll.makeRequest(); - * } - * - * Visibility.change(() => { - * if (!Visibility.hidden()) { - * poll.restart(); - * } else { - * poll.stop(); - * } -* }); - * - * 1. Checks for response and headers before start polling - * 2. Interval is provided by `Poll-Interval` header. - * 3. If `Poll-Interval` is -1, we stop polling - * 4. If HTTP response is 200, we poll. - * 5. If HTTP response is different from 200, we stop polling. - * - */ -export default class Poll { - constructor(options = {}) { - this.options = options; - this.options.data = options.data || {}; - this.options.notificationCallback = options.notificationCallback || - function notificationCallback() {}; - - this.intervalHeader = 'POLL-INTERVAL'; - this.timeoutID = null; - this.canPoll = true; - } - - checkConditions(response) { - const headers = gl.utils.normalizeHeaders(response.headers); - const pollInterval = parseInt(headers[this.intervalHeader], 10); - - if (pollInterval > 0 && response.status === httpStatusCodes.OK && this.canPoll) { - this.timeoutID = setTimeout(() => { - this.makeRequest(); - }, pollInterval); - } - this.options.successCallback(response); - } - - makeRequest() { - const { resource, method, data, errorCallback, notificationCallback } = this.options; - - // It's called everytime a new request is made. Useful to update the status. - notificationCallback(true); - - return resource[method](data) - .then((response) => { - this.checkConditions(response); - notificationCallback(false); - }) - .catch((error) => { - notificationCallback(false); - errorCallback(error); - }); - } - - /** - * Stops the polling recursive chain - * and guarantees if the timeout is already running it won't make another request by - * cancelling the previously established timeout. - */ - stop() { - this.canPoll = false; - clearTimeout(this.timeoutID); - } - - /** - * Restarts polling after it has been stoped - */ - restart() { - this.canPoll = true; - this.makeRequest(); - } -} diff --git a/app/assets/javascripts/lib/utils/socket/socket_manager.js b/app/assets/javascripts/lib/utils/socket/socket_manager.js new file mode 100644 index 00000000000..2f4f428ebee --- /dev/null +++ b/app/assets/javascripts/lib/utils/socket/socket_manager.js @@ -0,0 +1,108 @@ +import socketIO from 'socket.io-client'; +import Socket from 'socket.io-client/lib/socket'; +import Subscription from './subscription'; +import SubscriptionStore from './subscription_store'; + +const SocketManager = { + socketPath: '', + socket: {}, + store: SubscriptionStore, + subscriptionsCount: 0, + + init(socketPath) { + this.socketPath = socketPath; + + this.removeAll(); + }, + + connect() { + if (this.socket instanceof Socket) return Promise.resolve(); + + return new Promise((resolve, reject) => { + this.socket = socketIO(this.socketPath); + + this.socket.on('connect', resolve); + this.socket.on('connect_error', reject); + this.socket.on('connect_timeout', reject); + }); + }, + + subscribe(endpointOrSubscription, data, callbacks) { + this.connect().then(() => { + const subscription = this.getSubscription(endpointOrSubscription, data, callbacks); + + subscription.subscribe(); + + return subscription; + }).catch((error) => { + // temporary + // eslint-disable-next-line no-console + console.log('connect error', error); + }); + }, + + remove(subscription) { + subscription.unsubscribe(); + + this.store.remove(subscription); + }, + + unsubscribeAll() { + const subscriptions = this.store.getAll(); + + if (!subscriptions) return; + + subscriptions.forEach(subscription => subscription.unsubscribe()); + }, + + subscribeAll() { + const subscriptions = this.store.getAll(); + + if (!subscriptions) return; + + subscriptions.forEach(subscription => subscription.subscribe()); + }, + + removeAll() { + this.unsubscribeAll(); + this.store.removeAll(); + }, + + getSubscription(endpointOrSubscription, data, callbacks) { + let subscription; + + if (endpointOrSubscription instanceof Subscription) { + subscription = endpointOrSubscription; + } else { + subscription = this.createSubscription({ + endpoint: endpointOrSubscription, + data, + callbacks, + }); + } + + return subscription; + }, + + createSubscription({ + endpoint, + data, + callbacks, + }) { + this.subscriptionsCount += 1; + + const subscription = new Subscription({ + endpoint, + data, + callbacks, + socket: this.socket, + id: this.subscriptionsCount, + }); + + this.store.add(subscription); + + return subscription; + }, +}; + +export default SocketManager; diff --git a/app/assets/javascripts/lib/utils/socket/subscription.js b/app/assets/javascripts/lib/utils/socket/subscription.js new file mode 100644 index 00000000000..46373a78acb --- /dev/null +++ b/app/assets/javascripts/lib/utils/socket/subscription.js @@ -0,0 +1,68 @@ +class Subscription { + constructor({ + id, + endpoint, + data, + socket, + callbacks, + }) { + this.id = id; + this.endpoint = endpoint; + this.data = data; + this.socket = socket; + this.updateCallback = callbacks.updateCallback; + this.errorCallback = callbacks.errorCallback; + + this.setPayload(); + this.setEventNames(); + } + + subscribe() { + this.socket.emit(this.eventNames.subscribe, this.payload, this.acknowledge); + + this.bindListeners(); + } + + unsubscribe() { + this.socket.emit(this.eventNames.unsubscribe, this.payload, this.acknowledge); + + this.unbindListeners(); + } + + bindListeners() { + this.socket.on(this.eventNames.update, this.updateCallback); + this.socket.on(this.eventNames.error, this.errorCallback); + } + + unbindListeners() { + this.socket.removeListener(this.eventNames.update, this.updateCallback); + this.socket.removeListener(this.eventNames.error, this.errorCallback); + } + + setPayload() { + this.payload = { + id: this.id, + endpoint: this.endpoint, + data: this.data, + }; + } + + setEventNames() { + this.eventNames = { + subscribe: `subscribe:${this.endpoint}`, + unsubscribe: `unsubscribe:${this.endpoint}`, + update: `update:${this.id}`, + error: `error:${this.id}`, + }; + } + + acknowledge(response, ...args) { + if (response.error) this.errorCallback(response.error, ...args); + + // temporary + // eslint-disable-next-line no-console + console.log('ACK', ...args); + } +} + +export default Subscription; diff --git a/app/assets/javascripts/lib/utils/socket/subscription_store.js b/app/assets/javascripts/lib/utils/socket/subscription_store.js new file mode 100644 index 00000000000..06b43da1360 --- /dev/null +++ b/app/assets/javascripts/lib/utils/socket/subscription_store.js @@ -0,0 +1,27 @@ +const SocketStore = { + subscriptions: {}, + + add(subscription) { + this.subscriptions[subscription.id] = subscription; + + return subscription; + }, + + remove(subscription) { + delete this.subscriptions[subscription.id]; + }, + + get(subscriptionID) { + return this.subscriptions[subscriptionID]; + }, + + getAll() { + Object.values(this.subscriptions); + }, + + removeAll() { + this.subscriptions = {}; + }, +}; + +export default SocketStore; diff --git a/app/assets/javascripts/lib/utils/socket/visibility_socket_manager.js b/app/assets/javascripts/lib/utils/socket/visibility_socket_manager.js new file mode 100644 index 00000000000..d363ae4bd44 --- /dev/null +++ b/app/assets/javascripts/lib/utils/socket/visibility_socket_manager.js @@ -0,0 +1,24 @@ +import SocketManager from './socket_manager'; + +const VisibilitySocketManager = { + init(socketPath) { + super.init(socketPath); + + document.addEventListener('visibilitychange', () => this.toggleAllSockets()); + }, + + toggleAllSockets() { + if (document.hidden) { + super.unsubscribeAll(); + } else { + super.subscribeAll(); + } + }, +}; + +Object.setPrototypeOf(VisibilitySocketManager, SocketManager); + +// temporary +VisibilitySocketManager.init('/broker'); + +export default VisibilitySocketManager; diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue index 14c98847d93..f04eeae71ea 100644 --- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue @@ -1,11 +1,10 @@ <script> /* global Flash */ - import Visibility from 'visibilityjs'; - import Poll from '../../../lib/utils/poll'; import PipelineService from '../../services/pipeline_service'; import PipelineStore from '../../stores/pipeline_store'; import stageColumnComponent from './stage_column_component.vue'; import loadingIcon from '../../../vue_shared/components/loading_icon.vue'; + import VisibilitySocketManager from '../../../lib/utils/socket/visibility_socket_manager'; import '../../../flash'; export default { @@ -29,25 +28,10 @@ created() { this.service = new PipelineService(this.endpoint); - const poll = new Poll({ - resource: this.service, - method: 'getPipeline', - successCallback: this.successCallback, + VisibilitySocketManager.subscribe(this.endpoint, null, { + updateCallback: this.successCallback, errorCallback: this.errorCallback, }); - - if (!Visibility.hidden()) { - this.isLoading = true; - poll.makeRequest(); - } - - Visibility.change(() => { - if (!Visibility.hidden()) { - poll.restart(); - } else { - poll.stop(); - } - }); }, methods: { diff --git a/app/assets/javascripts/pipelines/pipelines.js b/app/assets/javascripts/pipelines/pipelines.js index d6952d1ee5f..18b91556e83 100644 --- a/app/assets/javascripts/pipelines/pipelines.js +++ b/app/assets/javascripts/pipelines/pipelines.js @@ -1,4 +1,3 @@ -import Visibility from 'visibilityjs'; import PipelinesService from './services/pipelines_service'; import eventHub from './event_hub'; import pipelinesTableComponent from '../vue_shared/components/pipelines_table'; @@ -8,7 +7,7 @@ import errorState from './components/error_state.vue'; import navigationTabs from './components/navigation_tabs'; import navigationControls from './components/nav_controls'; import loadingIcon from '../vue_shared/components/loading_icon.vue'; -import Poll from '../lib/utils/poll'; +import VisibilitySocketManager from '../lib/utils/socket/visibility_socket_manager'; export default { props: { @@ -140,30 +139,9 @@ export default { created() { this.service = new PipelinesService(this.endpoint); - const poll = new Poll({ - resource: this.service, - method: 'getPipelines', - data: { page: this.pageParameter, scope: this.scopeParameter }, - successCallback: this.successCallback, + VisibilitySocketManager.subscribe(this.endpoint, null, { + updateCallback: this.successCallback, errorCallback: this.errorCallback, - notificationCallback: this.setIsMakingRequest, - }); - - if (!Visibility.hidden()) { - this.isLoading = true; - poll.makeRequest(); - } else { - // If tab is not visible we need to make the first request so we don't show the empty - // state without knowing if there are any pipelines - this.fetchPipelines(); - } - - Visibility.change(() => { - if (!Visibility.hidden()) { - poll.restart(); - } else { - poll.stop(); - } }); eventHub.$on('refreshPipelines', this.fetchPipelines); diff --git a/package.json b/package.json index 800327d8a08..44527eae584 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "raw-loader": "^0.5.1", "react-dev-utils": "^0.5.2", "select2": "3.5.2-browserify", + "socket.io-client": "^2.0.1", "sql.js": "^0.4.0", "stats-webpack-plugin": "^0.4.3", "three": "^0.84.0", @@ -52,7 +53,6 @@ "timeago.js": "^2.0.5", "underscore": "^1.8.3", "url-loader": "^0.5.8", - "visibilityjs": "^1.2.4", "vue": "^2.2.6", "vue-loader": "^11.3.4", "vue-resource": "^0.9.3", diff --git a/spec/javascripts/lib/utils/poll_spec.js b/spec/javascripts/lib/utils/poll_spec.js deleted file mode 100644 index 22f30191ab9..00000000000 --- a/spec/javascripts/lib/utils/poll_spec.js +++ /dev/null @@ -1,175 +0,0 @@ -import Poll from '~/lib/utils/poll'; - -const waitForAllCallsToFinish = (service, waitForCount, successCallback) => { - const timer = () => { - setTimeout(() => { - if (service.fetch.calls.count() === waitForCount) { - successCallback(); - } else { - timer(); - } - }, 0); - }; - - timer(); -}; - -function mockServiceCall(service, response, shouldFail = false) { - const action = shouldFail ? Promise.reject : Promise.resolve; - const responseObject = response; - - if (!responseObject.headers) responseObject.headers = {}; - - service.fetch.and.callFake(action.bind(Promise, responseObject)); -} - -describe('Poll', () => { - const service = jasmine.createSpyObj('service', ['fetch']); - const callbacks = jasmine.createSpyObj('callbacks', ['success', 'error']); - - afterEach(() => { - callbacks.success.calls.reset(); - callbacks.error.calls.reset(); - service.fetch.calls.reset(); - }); - - it('calls the success callback when no header for interval is provided', (done) => { - mockServiceCall(service, { status: 200 }); - - new Poll({ - resource: service, - method: 'fetch', - successCallback: callbacks.success, - errorCallback: callbacks.error, - }).makeRequest(); - - waitForAllCallsToFinish(service, 1, () => { - expect(callbacks.success).toHaveBeenCalled(); - expect(callbacks.error).not.toHaveBeenCalled(); - - done(); - }); - }); - - it('calls the error callback whe the http request returns an error', (done) => { - mockServiceCall(service, { status: 500 }, true); - - new Poll({ - resource: service, - method: 'fetch', - successCallback: callbacks.success, - errorCallback: callbacks.error, - }).makeRequest(); - - waitForAllCallsToFinish(service, 1, () => { - expect(callbacks.success).not.toHaveBeenCalled(); - expect(callbacks.error).toHaveBeenCalled(); - - done(); - }); - }); - - it('should call the success callback when the interval header is -1', (done) => { - mockServiceCall(service, { status: 200, headers: { 'poll-interval': -1 } }); - - new Poll({ - resource: service, - method: 'fetch', - successCallback: callbacks.success, - errorCallback: callbacks.error, - }).makeRequest().then(() => { - expect(callbacks.success).toHaveBeenCalled(); - expect(callbacks.error).not.toHaveBeenCalled(); - - done(); - }).catch(done.fail); - }); - - it('starts polling when http status is 200 and interval header is provided', (done) => { - mockServiceCall(service, { status: 200, headers: { 'poll-interval': 1 } }); - - const Polling = new Poll({ - resource: service, - method: 'fetch', - data: { page: 1 }, - successCallback: callbacks.success, - errorCallback: callbacks.error, - }); - - Polling.makeRequest(); - - waitForAllCallsToFinish(service, 2, () => { - Polling.stop(); - - expect(service.fetch.calls.count()).toEqual(2); - expect(service.fetch).toHaveBeenCalledWith({ page: 1 }); - expect(callbacks.success).toHaveBeenCalled(); - expect(callbacks.error).not.toHaveBeenCalled(); - - done(); - }); - }); - - describe('stop', () => { - it('stops polling when method is called', (done) => { - mockServiceCall(service, { status: 200, headers: { 'poll-interval': 1 } }); - - const Polling = new Poll({ - resource: service, - method: 'fetch', - data: { page: 1 }, - successCallback: () => { - Polling.stop(); - }, - errorCallback: callbacks.error, - }); - - spyOn(Polling, 'stop').and.callThrough(); - - Polling.makeRequest(); - - waitForAllCallsToFinish(service, 1, () => { - expect(service.fetch.calls.count()).toEqual(1); - expect(service.fetch).toHaveBeenCalledWith({ page: 1 }); - expect(Polling.stop).toHaveBeenCalled(); - - done(); - }); - }); - }); - - describe('restart', () => { - it('should restart polling when its called', (done) => { - mockServiceCall(service, { status: 200, headers: { 'poll-interval': 1 } }); - - const Polling = new Poll({ - resource: service, - method: 'fetch', - data: { page: 1 }, - successCallback: () => { - Polling.stop(); - setTimeout(() => { - Polling.restart(); - }, 0); - }, - errorCallback: callbacks.error, - }); - - spyOn(Polling, 'stop').and.callThrough(); - spyOn(Polling, 'restart').and.callThrough(); - - Polling.makeRequest(); - - waitForAllCallsToFinish(service, 2, () => { - Polling.stop(); - - expect(service.fetch.calls.count()).toEqual(2); - expect(service.fetch).toHaveBeenCalledWith({ page: 1 }); - expect(Polling.stop).toHaveBeenCalled(); - expect(Polling.restart).toHaveBeenCalled(); - - done(); - }); - }); - }); -}); diff --git a/yarn.lock b/yarn.lock index 8aac2b1b1cd..1b922ca6e58 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1560,6 +1560,12 @@ debug@2.6.0, debug@^2.1.0, debug@^2.1.1, debug@^2.2.0: dependencies: ms "0.7.2" +debug@2.6.4, debug@~2.6.4: + version "2.6.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.4.tgz#7586a9b3c39741c0282ae33445c4e8ac74734fe0" + dependencies: + ms "0.7.3" + decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -1785,6 +1791,23 @@ engine.io-client@1.8.2: xmlhttprequest-ssl "1.5.3" yeast "0.1.2" +engine.io-client@~3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.1.1.tgz#415a9852badb14fa008fa3ef1e31608db6761325" + dependencies: + component-emitter "1.2.1" + component-inherit "0.0.3" + debug "~2.6.4" + engine.io-parser "~2.1.1" + has-cors "1.1.0" + indexof "0.0.1" + parsejson "0.0.3" + parseqs "0.0.5" + parseuri "0.0.5" + ws "~2.3.1" + xmlhttprequest-ssl "1.5.3" + yeast "0.1.2" + engine.io-parser@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-1.3.2.tgz#937b079f0007d0893ec56d46cb220b8cb435220a" @@ -1796,6 +1819,16 @@ engine.io-parser@1.3.2: has-binary "0.1.7" wtf-8 "1.0.0" +engine.io-parser@~2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.1.tgz#e0fb3f0e0462f7f58bb77c1a52e9f5a7e26e4668" + dependencies: + after "0.8.2" + arraybuffer.slice "0.0.6" + base64-arraybuffer "0.1.5" + blob "0.0.4" + has-binary2 "~1.0.2" + engine.io@1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-1.8.2.tgz#6b59be730b348c0125b0a4589de1c355abcf7a7e" @@ -2580,6 +2613,12 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" +has-binary2@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.2.tgz#e83dba49f0b9be4d026d27365350d9f03f54be98" + dependencies: + isarray "2.0.1" + has-binary@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/has-binary/-/has-binary-0.1.7.tgz#68e61eb16210c9545a0a5cce06a873912fe1e68c" @@ -3000,6 +3039,10 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" +isarray@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" + isbinaryfile@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621" @@ -3699,6 +3742,10 @@ ms@0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" +ms@0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff" + mute-stream@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" @@ -4913,7 +4960,7 @@ rx-lite@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" -safe-buffer@^5.0.1: +safe-buffer@^5.0.1, safe-buffer@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" @@ -5065,6 +5112,23 @@ socket.io-client@1.7.2: socket.io-parser "2.3.1" to-array "0.1.4" +socket.io-client@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.0.1.tgz#1d52f8c74660c68bb6695953fa119971155fad93" + dependencies: + backo2 "1.0.2" + base64-arraybuffer "0.1.5" + component-bind "1.0.0" + component-emitter "1.2.1" + debug "2.6.4" + engine.io-client "~3.1.0" + has-cors "1.1.0" + indexof "0.0.1" + object-component "0.0.3" + parseuri "0.0.5" + socket.io-parser "~3.1.1" + to-array "0.1.4" + socket.io-parser@2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-2.3.1.tgz#dd532025103ce429697326befd64005fcfe5b4a0" @@ -5074,6 +5138,15 @@ socket.io-parser@2.3.1: isarray "0.0.1" json3 "3.3.2" +socket.io-parser@~3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.1.2.tgz#dbc2282151fc4faebbe40aeedc0772eba619f7f2" + dependencies: + component-emitter "1.2.1" + debug "~2.6.4" + has-binary2 "~1.0.2" + isarray "2.0.1" + socket.io@1.7.2: version "1.7.2" resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-1.7.2.tgz#83bbbdf2e79263b378900da403e7843e05dc3b71" @@ -5528,6 +5601,10 @@ ultron@1.0.x: version "1.0.2" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" +ultron@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.0.tgz#b07a2e6a541a815fc6a34ccd4533baec307ca864" + unc-path-regex@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" @@ -5654,10 +5731,6 @@ verror@1.3.6: dependencies: extsprintf "1.0.2" -visibilityjs@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/visibilityjs/-/visibilityjs-1.2.4.tgz#bff8663da62c8c10ad4ee5ae6a1ae6fac4259d63" - vm-browserify@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" @@ -5898,6 +5971,13 @@ ws@1.1.1: options ">=0.0.5" ultron "1.0.x" +ws@~2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-2.3.1.tgz#6b94b3e447cb6a363f785eaf94af6359e8e81c80" + dependencies: + safe-buffer "~5.0.1" + ultron "~1.1.0" + wtf-8@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wtf-8/-/wtf-8-1.0.0.tgz#392d8ba2d0f1c34d1ee2d630f15d0efb68e1048a" |