0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-04-01 02:41:39 -05:00

Added alpha feature to demonstrate websockets

refs https://github.com/TryGhost/Team/issues/2561

- added simple socket-io implementation to Ghost server
- added alpha flag for websockets
- added route in admin to test websockets using a simple counter stored in server local memory (refreshes on reboot)
This commit is contained in:
Steve Larson 2023-02-17 11:25:51 +01:00 committed by Daniel Lockyer
parent e52efb31b8
commit 034a230365
16 changed files with 359 additions and 5 deletions

View file

@ -0,0 +1,8 @@
<div class="gh-expandable-header">
<div>
<h4 class="gh-expandable-title">Counter</h4>
<p class="gh-expandable-description">Current counter value: <strong>{{this.counter}}</strong></p>
<p class="gh-expandable-description">This counter will reset when Ghost reboots.</p>
</div>
<button type="button" class="gh-btn" {{on "click" this.handleClick}} data-test-button="delete-all"><span>Add One</span></button>
</div>

View file

@ -0,0 +1,31 @@
import Component from '@glimmer/component';
import {action} from '@ember/object';
import {inject as service} from '@ember/service';
import {tracked} from '@glimmer/tracking';
export default class Websockets extends Component {
@service('socket-io') socketIOService;
constructor(...args) {
super(...args);
// initialize connection
// TODO: ensure this works with subdirectories
let origin = window.location.origin; // this gives us host:port
let socket = this.socketIOService.socketFor(origin);
// add listener
socket.on('addCount', (value) => {
this.counter = value;
});
}
// button counter
@tracked counter = 0;
// handle button/event
@action handleClick() {
let socket = this.socketIOService.socketFor(origin);
this.counter = 1 + this.counter;
socket.emit('addCount', this.counter);
}
}

View file

@ -0,0 +1,13 @@
import Controller from '@ember/controller';
/* eslint-disable ghost/ember/alias-model-in-controller */
import classic from 'ember-classic-decorator';
import {inject as service} from '@ember/service';
@classic
export default class WebsocketsController extends Controller {
@service feature;
init() {
super.init(...arguments);
}
}

View file

@ -55,6 +55,9 @@ Router.map(function () {
this.route('settings.code-injection', {path: '/settings/code-injection'});
this.route('settings.history', {path: '/settings/history'});
this.route('settings.analytics', {path: '/settings/analytics'});
// testing websockets
this.route('websockets');
// redirect from old /settings/members-email to /settings/newsletters
this.route('settings.members-email', {path: '/settings/members-email'});

View file

@ -0,0 +1,17 @@
import AuthenticatedRoute from './authenticated';
import {inject as service} from '@ember/service';
// need this to be authenticated
export default class WebsocketRoute extends AuthenticatedRoute {
@service session;
beforeModel() {
super.beforeModel(...arguments);
const user = this.session.user;
if (!user.isAdmin) {
return this.transitionTo('settings.staff.user', user);
}
}
}

View file

@ -71,6 +71,7 @@ export default class FeatureService extends Service {
@feature('outboundLinkTagging') outboundLinkTagging;
@feature('emailErrors') emailErrors;
@feature('milestoneEmails') milestoneEmails;
@feature('websockets') websockets;
_user = null;

View file

@ -252,6 +252,19 @@
</div>
</div>
</div>
<div class="gh-expandable-block">
<div class="gh-expandable-header">
<div>
<h4 class="gh-expandable-title">Websockets</h4>
<p class="gh-expandable-description">
Test out Websockets functionality at <code>/ghost/#/websockets</code>.
</p>
</div>
<div class="for-switch">
<GhFeatureFlag @flag="websockets" />
</div>
</div>
</div>
</div>
</div>
{{/if}}

View file

@ -0,0 +1,29 @@
<section class="gh-canvas">
<GhCanvasHeader class="gh-canvas-header">
<div class="flex flex-column">
<h2 class="gh-canvas-title" data-test-screen-title>
Testing Websockets
</h2>
</div>
</GhCanvasHeader>
{{#if (feature 'websockets')}}
<section class="view-container settings-debug">
<p class="gh-box gh-box-tip">{{svg-jar "idea"}}This is a testing ground for new or experimental features. They
may change, break or inexplicably disappear at any time.</p>
<div class="gh-main-section">
<h4 class="gh-main-section-header small bn">Secrets</h4>
<div class="gh-expandable">
<div class="gh-expandable-block">
<Websockets />
</div>
</div>
</div>
</section>
{{else}}
<section class="view-container settings-debug">
<p class="gh-box gh-box-alert">{{svg-jar "warning-stroke"}}This is a testing ground for new or experimental features. You need developer experiments
enabled to see the content here.
</p>
</section>
{{/if}}
</section>

View file

@ -33,6 +33,10 @@ module.exports = function (environment) {
'ember-simple-auth': { },
'ember-websockets': {
socketIO: true
},
'@sentry/ember': {
disablePerformance: true,
sentry: {}

View file

@ -119,6 +119,7 @@
"ember-test-selectors": "6.0.0",
"ember-tooltips": "3.6.0",
"ember-truth-helpers": "3.1.1",
"ember-websockets": "10.2.1",
"eslint": "8.34.0",
"eslint-plugin-babel": "5.3.1",
"eslint-plugin-react": "7.32.2",
@ -181,4 +182,4 @@
"path-browserify": "1.0.1",
"webpack": "5.75.0"
}
}
}

View file

@ -473,6 +473,13 @@ async function bootGhost({backend = true, frontend = true, server = true} = {})
await initDynamicRouting();
}
// TODO: move this to the correct place once we figure out where that is
if (ghostServer) {
// NOTE: changes in this labs setting requires server reboot since we don't re-init services after changes a labs flag
const websockets = require('./server/services/websockets');
await websockets.init(ghostServer);
}
await initServices({config});
debug('End: Load Ghost Services & Apps');

View file

@ -0,0 +1 @@
module.exports = require('./service');

View file

@ -0,0 +1,37 @@
const {Server} = require('socket.io');
const debug = require('@tryghost/debug')('websockets');
const logging = require('@tryghost/logging');
const labs = require('../../../shared/labs');
module.exports = {
async init(ghostServer) {
debug(`[Websockets] Is labs set? ${labs.isSet('websockets')}`);
if (labs.isSet('websockets')) {
logging.info(`Starting websockets service`);
const io = new Server(ghostServer.httpServer);
let count = 0;
io.on(`connection`, (socket) => {
debug(`[Websockets] Client connected`);
// on connect, send current value
socket.emit('addCount', count);
// listen to to changes in value from client
socket.on('addCount', () => {
count = count + 1;
debug(`[Websockets] received addCount from client, count is now ${count}`);
socket.broadcast.emit('addCount', count);
});
});
ghostServer.registerCleanupTask(async () => {
logging.warn(`Stopping websockets service`);
await new Promise((resolve) => {
io.close(resolve);
});
});
}
}
};

View file

@ -36,7 +36,8 @@ const ALPHA_FEATURES = [
'urlCache',
'beforeAfterCard',
'lexicalEditor',
'outboundLinkTagging'
'outboundLinkTagging',
'websockets'
];
module.exports.GA_KEYS = [...GA_FEATURES];

View file

@ -196,6 +196,7 @@
"rss": "1.2.2",
"sanitize-html": "2.9.0",
"semver": "7.3.8",
"socket.io": "4.6.0",
"stoppable": "1.1.0",
"uuid": "9.0.0",
"xml": "1.0.1"

193
yarn.lock
View file

@ -4993,6 +4993,11 @@
resolved "https://registry.yarnpkg.com/@types/common-tags/-/common-tags-1.8.1.tgz#a5a49ca5ebbb58e0f8947f3ec98950c8970a68a9"
integrity sha512-20R/mDpKSPWdJs5TOpz3e7zqbeCNuMCPhV7Yndk9KU2Rbij2r5W4RzwDPkzC+2lzUqXYu9rFzTktCBnDjHuNQg==
"@types/component-emitter@^1.2.10":
version "1.2.11"
resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.11.tgz#50d47d42b347253817a39709fef03ce66a108506"
integrity sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==
"@types/connect-history-api-fallback@^1.3.5":
version "1.3.5"
resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae"
@ -7450,6 +7455,11 @@ backbone@^1.1.2:
dependencies:
underscore ">=1.8.3"
backo2@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
integrity sha512-zj6Z6M7Eq+PBZ7PQxl5NT665MvJdAkzp0f60nAJ+sLaSCBPMwVak5ZegFbgVCzFcCJTKFoMizvM5Ld7+JrRJHA==
bail@^1.0.0:
version "1.0.5"
resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776"
@ -7470,6 +7480,11 @@ base-64@^1.0.0:
resolved "https://registry.yarnpkg.com/base-64/-/base-64-1.0.0.tgz#09d0f2084e32a3fd08c2475b973788eee6ae8f4a"
integrity sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==
base64-arraybuffer@0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz#9818c79e059b1355f97e0428a017c838e90ba812"
integrity sha512-a1eIFi4R9ySrbiMuyTGx5e92uRH5tQY6kArNcFaKBUleIoLjdjBg7Zxm3Mqm3Kmkf27HLR/1fnxX9q8GQ7Iavg==
base64-js@^1.0.2, base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
@ -9604,7 +9619,7 @@ compare-ver@2.0.2:
resolved "https://registry.yarnpkg.com/compare-ver/-/compare-ver-2.0.2.tgz#8ecb8eb9dbf23ff2d87c56e74cbbb2cb7ffd9d7a"
integrity sha512-VeznF8KOp4C6rSg22tvnk8vgAveEMxVVgOVuCzqYIzGyzD2hQ4Zm/O5RKfOECcTqmn0BAAkyJKAN0eqkgUvsEA==
component-emitter@^1.2.1, component-emitter@^1.3.0:
component-emitter@^1.2.1, component-emitter@^1.3.0, component-emitter@~1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
@ -11303,6 +11318,42 @@ ember-auto-import@^1.11.2, ember-auto-import@^1.11.3, ember-auto-import@^1.12.0:
walk-sync "^0.3.3"
webpack "^4.43.0"
ember-auto-import@^2.4.1:
version "2.6.0"
resolved "https://registry.yarnpkg.com/ember-auto-import/-/ember-auto-import-2.6.0.tgz#c7a2f799c9b700d74648cb02e35cf7bc1b44ac02"
integrity sha512-xUyypxlaqWvrx2KSseLus0H8K7Dt+sXNCvcxtquT2EmIM6r67NuQUT9woiEMa9UBvqcaX2k9hNLeubDl78saig==
dependencies:
"@babel/core" "^7.16.7"
"@babel/plugin-proposal-class-properties" "^7.16.7"
"@babel/plugin-proposal-decorators" "^7.16.7"
"@babel/preset-env" "^7.16.7"
"@embroider/macros" "^1.0.0"
"@embroider/shared-internals" "^2.0.0"
babel-loader "^8.0.6"
babel-plugin-ember-modules-api-polyfill "^3.5.0"
babel-plugin-htmlbars-inline-precompile "^5.2.1"
babel-plugin-syntax-dynamic-import "^6.18.0"
broccoli-debug "^0.6.4"
broccoli-funnel "^3.0.8"
broccoli-merge-trees "^4.2.0"
broccoli-plugin "^4.0.0"
broccoli-source "^3.0.0"
css-loader "^5.2.0"
debug "^4.3.1"
fs-extra "^10.0.0"
fs-tree-diff "^2.0.0"
handlebars "^4.3.1"
js-string-escape "^1.0.1"
lodash "^4.17.19"
mini-css-extract-plugin "^2.5.2"
parse5 "^6.0.1"
resolve "^1.20.0"
resolve-package-path "^4.0.3"
semver "^7.3.4"
style-loader "^2.0.0"
typescript-memoize "^1.0.0-alpha.3"
walk-sync "^3.0.0"
ember-basic-dropdown@^3.0.11:
version "3.1.0"
resolved "https://registry.yarnpkg.com/ember-basic-dropdown/-/ember-basic-dropdown-3.1.0.tgz#47c292de890d1958057736c00b8eb2b8017d530b"
@ -12605,6 +12656,19 @@ ember-truth-helpers@3.1.1, "ember-truth-helpers@^2.1.0 || ^3.0.0", ember-truth-h
dependencies:
ember-cli-babel "^7.22.1"
ember-websockets@10.2.1:
version "10.2.1"
resolved "https://registry.yarnpkg.com/ember-websockets/-/ember-websockets-10.2.1.tgz#172637ee572edf74557a813ca6c35eb7ecb0215a"
integrity sha512-Iy99U60Y+DWcrELjxdaQ5SP5YyI2MtAtSaESyrhfyXT/bDJDll5vYtCD3d8LZi4vhmcSRqGL4Ej18UOBxYiUOw==
dependencies:
ember-auto-import "^2.4.1"
ember-cli-babel "^7.26.11"
ember-cli-htmlbars "^6.0.1"
glob "^8.0.3"
morgan "^1.9.0"
socket.io-client "^3.1.3"
urijs "^1.19.11"
emits@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/emits/-/emits-3.0.0.tgz#32752bba95e1707b219562384ab9bb8b1fd62f70"
@ -12654,6 +12718,29 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
dependencies:
once "^1.4.0"
engine.io-client@~4.1.0:
version "4.1.4"
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-4.1.4.tgz#0bda5ba4bd87bced2ad00b93c67e133d0fb981ba"
integrity sha512-843fqAdKeUMFqKi1sSjnR11tJ4wi8sIefu6+JC1OzkkJBmjtc/gM/rZ53tJfu5Iae/3gApm5veoS+v+gtT0+Fg==
dependencies:
base64-arraybuffer "0.1.4"
component-emitter "~1.3.0"
debug "~4.3.1"
engine.io-parser "~4.0.1"
has-cors "1.1.0"
parseqs "0.0.6"
parseuri "0.0.6"
ws "~7.4.2"
xmlhttprequest-ssl "~1.6.2"
yeast "0.1.2"
engine.io-parser@~4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-4.0.3.tgz#83d3a17acfd4226f19e721bb22a1ee8f7662d2f6"
integrity sha512-xEAAY0msNnESNPc00e19y5heTPX4y/TJ36gr8t1voOaNmTojP9b3oK3BbJLFufW2XFPQaaijpFewm2g2Um3uqA==
dependencies:
base64-arraybuffer "0.1.4"
engine.io-parser@~5.0.3:
version "5.0.4"
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.4.tgz#0b13f704fa9271b3ec4f33112410d8f3f41d0fc0"
@ -12675,6 +12762,22 @@ engine.io@~6.2.0:
engine.io-parser "~5.0.3"
ws "~8.2.3"
engine.io@~6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.4.0.tgz#de27f79ecb58301171aea7956f3f6f4fa578490a"
integrity sha512-OgxY1c/RuCSeO/rTr8DIFXx76IzUUft86R7/P7MMbbkuzeqJoTNw2lmeD91IyGz41QYleIIjWeMJGgug043sfQ==
dependencies:
"@types/cookie" "^0.4.1"
"@types/cors" "^2.8.12"
"@types/node" ">=10.0.0"
accepts "~1.3.4"
base64id "2.0.0"
cookie "~0.4.1"
cors "~2.8.5"
debug "~4.3.1"
engine.io-parser "~5.0.3"
ws "~8.11.0"
enhanced-resolve@^4.0.0, enhanced-resolve@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec"
@ -15126,6 +15229,11 @@ has-bigints@^1.0.1, has-bigints@^1.0.2:
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
has-cors@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
integrity sha512-g5VNKdkFuUuVCP9gYfDJHjK2nqdQJ7aDLTnycnc2+RvsOQbuLdF5pm7vuE5J76SEBIQjs4kQY/BWq74JUmjbXA==
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@ -19750,7 +19858,7 @@ moo@^0.5.0, moo@^0.5.1:
resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.2.tgz#f9fe82473bc7c184b0d32e2215d3f6e67278733c"
integrity sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==
morgan@^1.10.0:
morgan@^1.10.0, morgan@^1.9.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7"
integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==
@ -21005,6 +21113,16 @@ parseley@^0.7.0:
moo "^0.5.1"
nearley "^2.20.1"
parseqs@0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.6.tgz#8e4bb5a19d1cdc844a08ac974d34e273afa670d5"
integrity sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==
parseuri@0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.6.tgz#e1496e829e3ac2ff47f39a4dd044b32823c4a25a"
integrity sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==
parseurl@~1.3.2, parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
@ -24384,6 +24502,35 @@ socket.io-adapter@~2.4.0:
resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz#b50a4a9ecdd00c34d4c8c808224daa1a786152a6"
integrity sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==
socket.io-adapter@~2.5.2:
version "2.5.2"
resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz#5de9477c9182fdc171cd8c8364b9a8894ec75d12"
integrity sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==
dependencies:
ws "~8.11.0"
socket.io-client@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-3.1.3.tgz#57ddcefea58cfab71f0e94c21124de8e3c5aa3e2"
integrity sha512-4sIGOGOmCg3AOgGi7EEr6ZkTZRkrXwub70bBB/F0JSkMOUFpA77WsL87o34DffQQ31PkbMUIadGOk+3tx1KGbw==
dependencies:
"@types/component-emitter" "^1.2.10"
backo2 "~1.0.2"
component-emitter "~1.3.0"
debug "~4.3.1"
engine.io-client "~4.1.0"
parseuri "0.0.6"
socket.io-parser "~4.0.4"
socket.io-parser@~4.0.4:
version "4.0.5"
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.5.tgz#cb404382c32324cc962f27f3a44058cf6e0552df"
integrity sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig==
dependencies:
"@types/component-emitter" "^1.2.10"
component-emitter "~1.3.0"
debug "~4.3.1"
socket.io-parser@~4.2.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.1.tgz#01c96efa11ded938dcb21cbe590c26af5eff65e5"
@ -24392,6 +24539,26 @@ socket.io-parser@~4.2.0:
"@socket.io/component-emitter" "~3.1.0"
debug "~4.3.1"
socket.io-parser@~4.2.1:
version "4.2.2"
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.2.tgz#1dd384019e25b7a3d374877f492ab34f2ad0d206"
integrity sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==
dependencies:
"@socket.io/component-emitter" "~3.1.0"
debug "~4.3.1"
socket.io@4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.6.0.tgz#82ebfd7652572872e10dbb19533fc7cb930d0bc3"
integrity sha512-b65bp6INPk/BMMrIgVvX12x3Q+NqlGqSlTuvKQWt0BUJ3Hyy3JangBl7fEoWZTXbOKlCqNPbQ6MbWgok/km28w==
dependencies:
accepts "~1.3.4"
base64id "~2.0.0"
debug "~4.3.2"
engine.io "~6.4.0"
socket.io-adapter "~2.5.2"
socket.io-parser "~4.2.1"
socket.io@^4.1.2:
version "4.5.3"
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.5.3.tgz#44dffea48d7f5aa41df4a66377c386b953bc521c"
@ -26345,6 +26512,11 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
urijs@^1.19.11:
version "1.19.11"
resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc"
integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==
urix@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
@ -27391,11 +27563,16 @@ ws@^7.4.6:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591"
integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==
ws@^8.11.0, ws@^8.4.2:
ws@^8.11.0, ws@^8.4.2, ws@~8.11.0:
version "8.11.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143"
integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==
ws@~7.4.2:
version "7.4.6"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
ws@~8.2.3:
version "8.2.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba"
@ -27426,6 +27603,11 @@ xmlchars@^2.2.0:
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
xmlhttprequest-ssl@~1.6.2:
version "1.6.3"
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz#03b713873b01659dfa2c1c5d056065b27ddc2de6"
integrity sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q==
xregexp@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943"
@ -27538,6 +27720,11 @@ yauzl@^2.10.0:
buffer-crc32 "~0.2.3"
fd-slicer "~1.1.0"
yeast@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
integrity sha512-8HFIh676uyGYP6wP13R/j6OJ/1HwJ46snpvzE7aHAN3Ryqh2yX6Xox2B4CUmTwwOIzlG3Bs7ocsP5dZH/R1Qbg==
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"