diff --git a/README.md b/README.md index a11d987..14b3a5f 100644 --- a/README.md +++ b/README.md @@ -1,73 +1,128 @@ -# repl-auth +# replace-replit -Use Replit's Repl Auth in your project without hosting on Replit. +Use some of Replit's features in your project without hosting on Replit. ## Usage -### Replit +### ReplAuth -Use this exactly how you'd use [`@replit/repl-auth`](https://npm.im/@replit/repl-auth): +The ReplAuth module only supports express and socket.io currently. ```js -import { getUserInfo } from "repl-auth"; +import { auth } from "replace-replit"; import express from "express"; +import { createServer } from 'node:http'; +import { Server } from 'socket.io'; const app = express(); +const server = createServer(app); +const io = new Server(server); +app.use(auth.express()); app.get('/', (req, res) => { - const user = getUserInfo(req); + const username = req.get("X-Replit-User-Name"); - if (user) - res.send(`Hello, ${user.name}!`); + if (username) + res.send(`Hello, ${username}!`); else res.send(`Hello, World!`); }); -app.listen(8000, () => { +io.use(auth.socketIo({ exposeAs: "user" })) + +io.on('connection', (socket) => { + console.log('connection from', socket.user.name) +}) + +server.listen(8000, () => { console.log("App is running on port 8000"); }); ``` -### Anywhere else +### ReplDB -The module only supports express currently. +The ReplDB module only supports express and socket.io currently. ```js -import { express as replAuth } from "repl-auth"; +// server.js +import { db } from "replace-replit"; import express from "express"; const app = express(); -app.use(replAuth()); - -app.get('/', (req, res) => { - const username = req.get("X-Replit-User-Name"); - - if (username) - res.send(`Hello, ${username}!`); - else - res.send(`Hello, World!`); -}); +app.use(db.express({ + file: "database.json", + fileType: "json" +})); app.listen(8000, () => { console.log("App is running on port 8000"); }); + +// test.js +import Database from "@replit/database"; + +const db = new Database("localhost:8000"); + +await db.set("hello", "world") + +await db.get("hello") // world ``` ## Options -Currently there is only one option passable to the `replAuth` middleware: +### ReplAuth +Currently there is only one option passable to the `auth` middleware: `exposeAs` will allow you to control what an object containing the user data will be set to: ```js -app.use(replAuth({ exposeAs: "user" })) +app.use(auth.express({ exposeAs: "user" })) // In a route handler... req.user.name // contains the user's username ``` +### ReplDB +There are 4 options passable to the `db` middleware: + +`file`: Controls what file your database will be saved to. +`fileType`: Controls what type your file will use. Values can either be `json`, `toml`, `ini`, or `custom` (see below): + +`parse`: Function that takes two arguments, data (the file contents) and fileType (the fileType passed to the middleware). + +```js +db.express({ + // ... + parse(data, fileType) { + if (fileType == "...") { + // do stuff + return TheResultingDataInAnObject + } else { + throw new Error('i dunno what this file type is') + } + } +}) +``` + +`stringify`: Function that takes two arguments, data (the current db object) and fileType (the fileType passed to the middleware). + +```js +db.express({ + // ... + stringify(data, fileType) { + if (fileType == "...") { + // do stuff + return TheResultingDataInAString + } else { + throw new Error('i dunno what this file type is') + } + } +}) +``` + # Acknowledgements [PotentialStyx](https://replit.com/@PotentialStyx) - Helped me with verifying the JWT -[PikachuB2005](https://replit.com/@PikachuB2005) - Donated the package name to me +[PikachuB2005](https://replit.com/@PikachuB2005) - Donated the package name to me [coding398](https://replit.com/@codingMASTER398) - Cool tester + has great ideas + bug fixer +[DillonB07](https://replit.com/@DillonB07) - Helped on the README diff --git a/package.json b/package.json index f78d5b4..8a6e30a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "repl-auth", - "version": "1.0.10", - "description": "Use Replit's Repl Auth in your project without hosting on Replit.", + "name": "replace-replit", + "version": "1.0.0", + "description": "Use some of Replit's features in your project without hosting on Replit.", "type": "module", "main": "./dist/index.cjs", "module": "./dist/index.mjs", @@ -38,6 +38,7 @@ "@babel/preset-env": "^7.16.0", "@rollup/plugin-babel": "^5.3.0", "@rollup/plugin-commonjs": "^21.0.1", + "@rollup/plugin-json": "^6.0.1", "@rollup/plugin-node-resolve": "^13.0.6", "@rollup/plugin-typescript": "^8.3.3", "@types/express": "^4.17.17", @@ -61,9 +62,12 @@ "typescript": "^4.7.3" }, "dependencies": { + "@iarna/toml": "^2.2.5", "@replit/repl-auth": "^1.0.0", "express": "^4.18.2", - "jsonwebtoken": "^9.0.1" + "ini": "^4.1.1", + "jsonwebtoken": "^9.0.1", + "socket.io": "^4.7.2" }, "directories": { "test": "tests" diff --git a/rollup.config.cjs b/rollup.config.cjs index 327c136..638c297 100644 --- a/rollup.config.cjs +++ b/rollup.config.cjs @@ -2,6 +2,7 @@ const typescript = require('@rollup/plugin-typescript'); const { babel } = require('@rollup/plugin-babel'); const { nodeResolve: resolve } = require('@rollup/plugin-node-resolve'); const commonjs = require('@rollup/plugin-commonjs'); +const json = require('@rollup/plugin-json'); const { terser } = require('rollup-plugin-terser'); const dts = require('rollup-plugin-dts').default; const del = require('rollup-plugin-delete'); @@ -32,6 +33,7 @@ module.exports = [ }), resolve(), commonjs(), + json(), /* Optionally uncomment the line below to minify the final bundle: */ diff --git a/src/index.ts b/src/index.ts index 1666b60..ffd7f26 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,113 +1,2 @@ -import type { Request, Response, NextFunction } from 'express'; -import { verify } from 'jsonwebtoken'; - -const PUBKEY = `-----BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEv+0QT2+9KdAHZMXROxnLmfE9qkry -1W4bieh/LIyXyl9v2aexV8hef2iMaYmjz9yji2Iae1/sgiywvwflRD5O9Q== ------END PUBLIC KEY----- -`; - -export type Options = { - exposeAs?: string; -}; - -export function express( - opts?: Options, -): (req: Request, res: Response, next: NextFunction) => void { - return function middleware( - req: Request, - res: Response, - next: NextFunction, - ) { - if (req.path == '/__replauth') { - const REPL_AUTH = req.query.token as string; - - let user; - - try { - user = verify(REPL_AUTH, PUBKEY); - } catch (err) { - return res.status(400).send('bad jwt'); - } - - return res - .cookie('REPL_AUTH', REPL_AUTH) - .status(304) - .redirect(req.query.redirect); - } else if (req.path == '/__replauthuser') { - const cookies: { [key: string]: string } = Object.fromEntries( - req.headers.cookie.split(';').map((x) => { - const a = x.trim().split('='); - return [a.shift(), a.join('=')]; - }), - ); - - const REPL_AUTH = cookies.REPL_AUTH; - - let user; - - try { - user = verify(REPL_AUTH, PUBKEY); - } catch (err) { - return res.send('User is not logged in'); - } - - return res.json({ - id: user.sub, - name: user.name, - bio: user.bio, - url: user.url, - profileImage: user.profile_image, - roles: user.roles.split(','), - teams: user.teams.split(','), - }); - } - - if(!req.headers.cookie){ - return next(); - } - - const cookies: { [key: string]: string } = Object.fromEntries( - req.headers.cookie.split(';').map((x) => { - const a = x.trim().split('='); - return [a.shift(), a.join('=')]; - }), - ); - - if(!cookies.REPL_AUTH) return next(); - - const REPL_AUTH = cookies.REPL_AUTH; - - let user; - - try { - user = verify(REPL_AUTH, PUBKEY); - } catch (err) { - return next(err); - } - - req.headers['x-replit-user-name'] = user.name; - req.headers['x-replit-user-id'] = user.sub; - req.headers['x-replit-user-bio'] = user.bio; - req.headers['x-replit-user-url'] = user.url; - req.headers['x-replit-user-profile-image'] = user.profile_image; - req.headers['x-replit-user-teams'] = user.teams; - req.headers['x-replit-user-roles'] = user.roles; - - if (opts.exposeAs) { - req[opts.exposeAs] = { - id: user.sub, - name: user.name, - bio: user.bio, - url: user.url, - profileImage: user.profile_image, - roles: user.roles.split(','), - teams: user.teams.split(','), - }; - } - - next(); - }; -} - -export { getUserInfo } from '@replit/repl-auth'; +export * as auth from "./replauth"; +export * as db from "./repldb"; \ No newline at end of file diff --git a/src/replauth.ts b/src/replauth.ts new file mode 100644 index 0000000..cec1553 --- /dev/null +++ b/src/replauth.ts @@ -0,0 +1,157 @@ +import type { Request, Response, NextFunction } from 'express'; +import type { Socket } from 'socket.io'; +import type { ExtendedError } from 'socket.io/dist/namespace'; +import { verify } from 'jsonwebtoken'; + +const PUBKEY = `-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEv+0QT2+9KdAHZMXROxnLmfE9qkry +1W4bieh/LIyXyl9v2aexV8hef2iMaYmjz9yji2Iae1/sgiywvwflRD5O9Q== +-----END PUBLIC KEY----- +`; + +export type ReplAuthOptions = { + exposeAs?: string; +}; + +export function express( + opts?: ReplAuthOptions, +): (req: Request, res: Response, next: NextFunction) => void { + return function middleware( + req: Request, + res: Response, + next: NextFunction, + ) { + if (req.path == '/__replauth') { + const REPL_AUTH = req.query.token as string; + + try { + verify(REPL_AUTH, PUBKEY); + } catch (err) { + return res.status(400).send('bad jwt'); + } + + return res + .cookie('REPL_AUTH', REPL_AUTH) + .status(304) + .redirect(req.query.redirect); + } else if (req.path == '/__replauthuser') { + const cookies: { [key: string]: string } = Object.fromEntries( + req.headers.cookie.split(';').map((x) => { + const a = x.trim().split('='); + return [a.shift(), a.join('=')]; + }), + ); + + const REPL_AUTH = cookies.REPL_AUTH; + + let user; + + try { + user = verify(REPL_AUTH, PUBKEY); + } catch (err) { + return res.send('User is not logged in'); + } + + return res.json({ + id: user.sub, + name: user.name, + bio: user.bio, + url: user.url, + profileImage: user.profile_image, + roles: user.roles.split(','), + teams: user.teams.split(','), + }); + } + + if (!req.headers.cookie) { + return next(); + } + + const cookies: { [key: string]: string } = Object.fromEntries( + req.headers.cookie.split(';').map((x) => { + const a = x.trim().split('='); + return [a.shift(), a.join('=')]; + }), + ); + + if (!cookies.REPL_AUTH) return next(); + + const REPL_AUTH = cookies.REPL_AUTH; + + let user; + + try { + user = verify(REPL_AUTH, PUBKEY); + } catch (err) { + return next(); + } + + req.headers['x-replit-user-name'] = user.name; + req.headers['x-replit-user-id'] = user.sub; + req.headers['x-replit-user-bio'] = user.bio; + req.headers['x-replit-user-url'] = user.url; + req.headers['x-replit-user-profile-image'] = user.profile_image; + req.headers['x-replit-user-teams'] = user.teams; + req.headers['x-replit-user-roles'] = user.roles; + + if (opts.exposeAs) { + req[opts.exposeAs] = { + id: user.sub, + name: user.name, + bio: user.bio, + url: user.url, + profileImage: user.profile_image, + roles: user.roles.split(','), + teams: user.teams.split(','), + }; + } + + next(); + }; +} + +export function socketIo( + opts?: ReplAuthOptions, +): (socket: Socket, next: (err?: ExtendedError) => void) => void { + return function middleware(socket, next) { + const cookies: { [key: string]: string } = Object.fromEntries( + socket.handshake.headers.cookie.split(';').map((x) => { + const a = x.trim().split('='); + return [a.shift(), a.join('=')]; + }), + ); + + const REPL_AUTH = cookies.REPL_AUTH; + + let user; + + try { + user = verify(REPL_AUTH, PUBKEY); + } catch (err) { + return next(); + } + + socket.handshake.headers['x-replit-user-name'] = user.name; + socket.handshake.headers['x-replit-user-id'] = user.sub; + socket.handshake.headers['x-replit-user-bio'] = user.bio; + socket.handshake.headers['x-replit-user-url'] = user.url; + socket.handshake.headers['x-replit-user-profile-image'] = + user.profile_image; + socket.handshake.headers['x-replit-user-teams'] = user.teams; + socket.handshake.headers['x-replit-user-roles'] = user.roles; + + if (opts.exposeAs) { + socket[opts.exposeAs] = { + id: user.sub, + name: user.name, + bio: user.bio, + url: user.url, + profileImage: user.profile_image, + roles: user.roles.split(','), + teams: user.teams.split(','), + }; + } + + next() + }; +} diff --git a/src/repldb.ts b/src/repldb.ts new file mode 100644 index 0000000..628c8a8 --- /dev/null +++ b/src/repldb.ts @@ -0,0 +1,107 @@ +import { Router, Request } from 'express'; +import fs from 'fs/promises'; +import type { PathLike } from "fs"; +import bodyParser from 'body-parser'; + +import toml from '@iarna/toml'; +import ini from 'ini'; + +function defaultParse(data: string, fileType: "json" | "toml" | "ini"): { [key: string]: string | number | boolean } { + if (fileType == "json") { + return JSON.parse(data) + } else if (fileType == "toml") { + return Object.fromEntries(Object.entries(toml.parse(data))) as { [key: string]: string | number | boolean } + } else if (fileType == "ini") { + return ini.parse(data) + } else { + throw new Error("unknown fileType type: must be either \"json\", \"toml\" or \"ini\"") + } +} + +function defaultStringify(data: { [key: string]: string | number | boolean }, fileType: "json" | "toml" | "ini"): string { + if (fileType == "json") { + return JSON.stringify(data) + } else if (fileType == "toml") { + return toml.stringify(data) + } else if (fileType == "ini") { + return ini.stringify(data) + } else { + throw new Error("unknown fileType type: must be either \"json\", \"toml\" or \"ini\"") + } +} + +export type KVOptions = { + file: PathLike, + fileType: "json" | "toml" | "ini", + parse?: (data: string, fileType: "json" | "toml" | "ini") => { [key: string]: string | number | boolean }, + stringify?: (data: { [key: string]: string | number | boolean }, fileType: "json" | "toml" | "ini") => string +} | { + file: PathLike, + fileType: "custom", + parse: (data: string, fileType: "custom") => { [key: string]: string | number | boolean }, + stringify: (data: { [key: string]: string | number | boolean }, fileType: "custom") => string +} + +export async function express({ + file = "database.json", + fileType = "json", + parse, + stringify +}: KVOptions) { + parse = parse || defaultParse + stringify = stringify || defaultStringify + + const app = Router() + + fileType = fileType.toLowerCase() as "json" | "toml" | "ini" | "custom" + + try { + await fs.readFile(file, 'utf-8') + } catch (err) { + console.log(err) + // @ts-ignore weird error? + await fs.writeFile(file, stringify({}, fileType)) + } + + app.use(bodyParser.json()) + app.use(bodyParser.urlencoded()) + app.get('/', async (req: Request, res) => { + // @ts-ignore weird error? + const db = parse(await fs.readFile(file, 'utf-8'), fileType) + + res.send( + Object.keys(db).filter(key => key.startsWith(req.query.prefix)).join('\n') + ) + }); + app.post('/', async (req, res) => { + // @ts-ignore weird error? + const db = parse(await fs.readFile(file, 'utf-8'), fileType) + + for (const key in req.body) { + db[key] = req.body[key] + } + // @ts-ignore weird error? + await fs.writeFile(file, stringify(db, fileType)) + + res.send("") + }) + app.get('/:key', async (req, res) => { + // @ts-ignore weird error? + const db = parse(await fs.readFile(file, 'utf-8'), fileType) + + res.send(db[req.params.key] || "") + }) + app.delete('/:key', async (req, res) => { + // @ts-ignore weird error? + const db = parse(await fs.readFile(file, 'utf-8'), fileType) + + delete db[req.params.key] + + // @ts-ignore weird error? + await fs.writeFile(file, stringify(db, fileType)) + + res.send("") + }) + + return app +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 41a7d47..2352a04 100644 --- a/yarn.lock +++ b/yarn.lock @@ -958,6 +958,11 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@iarna/toml@^2.2.5": + version "2.2.5" + resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c" + integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg== + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1264,6 +1269,13 @@ magic-string "^0.25.7" resolve "^1.17.0" +"@rollup/plugin-json@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-6.0.1.tgz#7e2efcf5ed549963f1444e010611d22f463931c0" + integrity sha512-RgVfl5hWMkxN1h/uZj8FVESvPuBJ/uf6ly6GTj0GONnkfoBN5KC0MSz+PN2OLDgYXMhtG0mWpTrkiOjoxAIevw== + dependencies: + "@rollup/pluginutils" "^5.0.1" + "@rollup/plugin-node-resolve@^13.0.6": version "13.3.0" resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.3.0.tgz#da1c5c5ce8316cef96a2f823d111c1e4e498801c" @@ -1293,6 +1305,15 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@rollup/pluginutils@^5.0.1": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.5.tgz#bbb4c175e19ebfeeb8c132c2eea0ecb89941a66c" + integrity sha512-6aEYR910NyP73oHiJglti74iRyOwgFU4x3meH/H8OJx6Ry0j6cOVZ5X/wTvub7G7Ao6qaHBEaNsV3GLJkSsF+Q== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^2.3.1" + "@sinclair/typebox@^0.23.3": version "0.23.5" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.23.5.tgz#93f7b9f4e3285a7a9ade7557d9a8d36809cbc47d" @@ -1312,6 +1333,11 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@socket.io/component-emitter@~3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" + integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== + "@types/babel__core@^7.1.14": version "7.1.19" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.19.tgz#7b497495b7d1b4812bdb9d02804d0576f43ee460" @@ -1360,6 +1386,18 @@ dependencies: "@types/node" "*" +"@types/cookie@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" + integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== + +"@types/cors@^2.8.12": + version "2.8.14" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.14.tgz#94eeb1c95eda6a8ab54870a3bf88854512f43a92" + integrity sha512-RXHUvNWYICtbP6s18PnOCaqToK8y14DnLd75c6HfyKf228dxy7pHNOQkxPtvXKp/hINFMDjbYzsj63nnpPMSRQ== + dependencies: + "@types/node" "*" + "@types/estree@*": version "0.0.51" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" @@ -1370,6 +1408,11 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== +"@types/estree@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.2.tgz#ff02bc3dc8317cd668dfec247b750ba1f1d62453" + integrity sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA== + "@types/express-serve-static-core@^4.17.33": version "4.17.35" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz#c95dd4424f0d32e525d23812aa8ab8e4d3906c4f" @@ -1477,6 +1520,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.42.tgz#d7e8f22700efc94d125103075c074396b5f41f9b" integrity sha512-Q5BPGyGKcvQgAMbsr7qEGN/kIPN6zZecYYABeTDBizOsau+2NMdSVTar9UQw21A2+JyA2KRNDYaYrPB0Rpk2oQ== +"@types/node@>=10.0.0": + version "20.8.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.3.tgz#c4ae2bb1cfab2999ed441a95c122bbbe1567a66d" + integrity sha512-jxiZQFpb+NlH5kjW49vXxvxTjeeqlbsnTAdBTKpzEdPs9itay7MscYXz3Fo9VYFEsfQ6LJFitHad3faerLAjCw== + "@types/prettier@^2.1.5": version "2.6.3" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.6.3.tgz#68ada76827b0010d0db071f739314fa429943d0a" @@ -1620,7 +1668,7 @@ "@typescript-eslint/types" "5.28.0" eslint-visitor-keys "^3.3.0" -accepts@~1.3.8: +accepts@~1.3.4, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== @@ -1833,6 +1881,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64id@2.0.0, base64id@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" + integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== + body-parser@1.20.1: version "1.20.1" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" @@ -2063,6 +2116,11 @@ cookie@0.5.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== +cookie@~0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + core-js-compat@^3.21.0, core-js-compat@^3.22.1: version "3.22.8" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.22.8.tgz#46fa34ce1ddf742acd7f95f575f66bbb21e05d62" @@ -2071,6 +2129,14 @@ core-js-compat@^3.21.0, core-js-compat@^3.22.1: browserslist "^4.20.3" semver "7.0.0" +cors@~2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + cross-env@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" @@ -2094,7 +2160,7 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.4: +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -2209,6 +2275,27 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== +engine.io-parser@~5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.1.tgz#9f213c77512ff1a6cc0c7a86108a7ffceb16fcfb" + integrity sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ== + +engine.io@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.5.3.tgz#80b0692912cef3a417e1b7433301d6397bf0374b" + integrity sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw== + 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.2.1" + ws "~8.11.0" + enquirer@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" @@ -2379,7 +2466,7 @@ estree-walker@^1.0.1: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== -estree-walker@^2.0.1: +estree-walker@^2.0.1, estree-walker@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== @@ -2777,6 +2864,11 @@ inherits@2, inherits@2.0.4: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ini@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.1.tgz#d95b3d843b1e906e56d6747d5447904ff50ce7a1" + integrity sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g== + ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" @@ -3573,6 +3665,11 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" +object-assign@^4: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + object-inspect@^1.9.0: version "1.12.3" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" @@ -4103,6 +4200,34 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" +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-parser@~4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.4.tgz#c806966cf7270601e47469ddeec30fbdfda44c83" + integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" + +socket.io@^4.7.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.7.2.tgz#22557d76c3f3ca48f82e73d68b7add36a22df002" + integrity sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw== + dependencies: + accepts "~1.3.4" + base64id "~2.0.0" + cors "~2.8.5" + debug "~4.3.2" + engine.io "~6.5.2" + socket.io-adapter "~2.5.2" + socket.io-parser "~4.2.4" + source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -4409,7 +4534,7 @@ v8-to-istanbul@^9.0.0: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" -vary@~1.1.2: +vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== @@ -4455,6 +4580,11 @@ write-file-atomic@^4.0.1: imurmurhash "^0.1.4" signal-exit "^3.0.7" +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== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"