diff --git a/.github/workflows/build-and-release-desktop.yml b/.github/workflows/build-and-release-desktop.yml index cc0d4d48..99d4e4d8 100644 --- a/.github/workflows/build-and-release-desktop.yml +++ b/.github/workflows/build-and-release-desktop.yml @@ -60,6 +60,10 @@ jobs: run: yarn build working-directory: "desktop/local-app" + - name: "Set desktop app version" + run: node helpers/set-version.js + working-directory: "desktop/electron" + - name: "Install dependencies" run: yarn install --froze-lockfile working-directory: "desktop/electron" @@ -68,15 +72,19 @@ jobs: run: yarn build working-directory: "desktop/electron" - - name: "Build app" - run: yarn bundle --publish never + - name: "Install electron tools" + run: yarn electron-builder install-app-deps + working-directory: "desktop/electron" + + - name: "Build app for testing" + run: yarn electron-builder --publish never env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} working-directory: "desktop/electron" if: ${{ github.event_name != 'release' }} - - name: "Build & publish App" - run: yarn release + - name: "Build & release app" + run: yarn electron-builder --publish always env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} working-directory: "desktop/electron" diff --git a/back/.eslintrc.json b/back/.eslintrc.json index 27927fea..82ee1e79 100644 --- a/back/.eslintrc.json +++ b/back/.eslintrc.json @@ -27,8 +27,8 @@ "no-unused-vars": "off", "@typescript-eslint/no-explicit-any": "error", "@typescript-eslint/no-unused-vars": [ - "error" + "error", { "args": "none", "caughtErrors": "all", "varsIgnorePattern": "_exhaustiveCheck" } ], "no-throw-literal": "error" } -} \ No newline at end of file +} diff --git a/back/src/Model/GameRoom.ts b/back/src/Model/GameRoom.ts index f0c6e627..efe7f86a 100644 --- a/back/src/Model/GameRoom.ts +++ b/back/src/Model/GameRoom.ts @@ -559,11 +559,7 @@ export class GameRoom { return { mapUrl, - policy_type: 1, - tags: [], authenticationMandatory: null, - roomSlug: null, - contactPage: null, group: null, }; } diff --git a/back/src/Model/Zone.ts b/back/src/Model/Zone.ts index b333316a..c595447e 100644 --- a/back/src/Model/Zone.ts +++ b/back/src/Model/Zone.ts @@ -71,7 +71,6 @@ export class Zone { /** * Notify listeners of this zone that this user entered */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars private notifyEnter(thing: Movable, oldZone: Zone | null, position: PositionInterface) { for (const listener of this.listeners) { this.onEnters(thing, oldZone, listener); diff --git a/back/src/Services/Repository/VoidVariablesRepository.ts b/back/src/Services/Repository/VoidVariablesRepository.ts index f69a9976..0a2664e8 100644 --- a/back/src/Services/Repository/VoidVariablesRepository.ts +++ b/back/src/Services/Repository/VoidVariablesRepository.ts @@ -4,12 +4,10 @@ import { VariablesRepositoryInterface } from "./VariablesRepositoryInterface"; * Mock class in charge of NOT saving/loading variables from the data store */ export class VoidVariablesRepository implements VariablesRepositoryInterface { - // eslint-disable-next-line @typescript-eslint/no-unused-vars loadVariables(roomUrl: string): Promise<{ [key: string]: string }> { return Promise.resolve({}); } - // eslint-disable-next-line @typescript-eslint/no-unused-vars saveVariable(roomUrl: string, key: string, value: string): Promise { return Promise.resolve(0); } diff --git a/contrib/docker/.env.prod.template b/contrib/docker/.env.prod.template index a6317078..ed40f6e3 100644 --- a/contrib/docker/.env.prod.template +++ b/contrib/docker/.env.prod.template @@ -30,7 +30,7 @@ ADMIN_API_URL= DATA_DIR=./wa # The URL used by default, in the form: "/_/global/map/url.json" -START_ROOM_URL=/_/global/maps.workadventu.re/Floor0/floor0.json +START_ROOM_URL=/_/global/thecodingmachine.github.io/workadventure-map-starter-kit/map.json # If you want to have a contact page in your menu, # you MUST set CONTACT_URL to the URL of the page that you want diff --git a/contrib/docker/README.md b/contrib/docker/README.md new file mode 100644 index 00000000..2de72b41 --- /dev/null +++ b/contrib/docker/README.md @@ -0,0 +1,34 @@ +# Deploying WorkAdventure in production + +This directory contains a sample production deployment of WorkAdventure using docker-compose. + +Every production environment is different and this docker-compose file will not +fit all use cases. But it is intended to be a good starting point for you +to build your own deployment. + +In this docker-compose file, you will find: + +- A reverse-proxy (Traefik) that dispatches requests to the WorkAdventure containers and handles HTTPS certificates using LetsEncrypt +- A front container (nginx) that servers static files (HTML/JS/CSS) +- A pusher container (NodeJS) that is the point of entry for users (you can start many if you want to increase performance) +- A back container (NodeJS) that shares your rooms information +- An icon container to fetch the favicon of sites imported in iframes +- A Redis server to store values from variables originating from the Scripting API + +```mermaid +graph LR + A[Browser] --> B(Traefik) + subgraph docker-compose + B --> C(Front) + B --> D(Pusher) + B --> E(Icon) + D --> F(Back) + F --> G(Redis) + end + A .-> H(Map) + F .-> H +``` + +**Important**: the default docker-compose file does **not** contain a container dedicated to hosting maps. The documentation and +tutorials are relying on GitHub Pages to host the maps. If you want to self-host your maps, you will need to add a simple +HTTP server (nginx / Apache, ...) and properly configure the [CORS settings as explained in the documentation](../../docs/maps/hosting.md). diff --git a/contrib/docker/docker-compose.prod.yaml b/contrib/docker/docker-compose.prod.yaml index 097e0bc8..2346a640 100644 --- a/contrib/docker/docker-compose.prod.yaml +++ b/contrib/docker/docker-compose.prod.yaml @@ -95,6 +95,7 @@ services: - JITSI_ISS - MAX_PER_GROUP - STORE_VARIABLES_FOR_LOCAL_MAPS + - REDIS_HOST=redis labels: - "traefik.http.routers.back.rule=Host(`${BACK_HOST}`)" - "traefik.http.routers.back.entryPoints=web" @@ -117,3 +118,11 @@ services: - "traefik.http.routers.icon-ssl.service=icon" - "traefik.http.routers.icon-ssl.tls=true" - "traefik.http.routers.icon-ssl.tls.certresolver=myresolver" + + redis: + image: redis:6 + volumes: + - redisdata:/data + +volumes: + redisdata: diff --git a/desktop/electron/electron-builder.yml b/desktop/electron/electron-builder.yml index faca3d73..d9fd4eb1 100644 --- a/desktop/electron/electron-builder.yml +++ b/desktop/electron/electron-builder.yml @@ -28,5 +28,4 @@ publish: provider: github owner: thecodingmachine repo: workadventure - vPrefixedTagName: false - releaseType: draft + releaseType: release diff --git a/desktop/electron/helpers/set-version.js b/desktop/electron/helpers/set-version.js new file mode 100644 index 00000000..52c5e8c8 --- /dev/null +++ b/desktop/electron/helpers/set-version.js @@ -0,0 +1,18 @@ +const path = require('path'); +const fs = require('fs'); + +let version = '0.0.0'; + +if (process.env.GITHUB_REF.startsWith('refs/tags/v')) { + version = process.env.GITHUB_REF.replace('refs/tags/v', ''); +} + +console.log('Version:', version); + +const packageJsonPath = path.resolve(__dirname, '..', 'package.json'); + +let data = fs.readFileSync(packageJsonPath, 'utf8'); + +data = data.replace('managedbyci', version); + +fs.writeFileSync(packageJsonPath, data); diff --git a/desktop/electron/package.json b/desktop/electron/package.json index 26a3929c..2998919f 100644 --- a/desktop/electron/package.json +++ b/desktop/electron/package.json @@ -1,6 +1,6 @@ { "name": "workadventure-desktop", - "version": "1.0.0", + "version": "managedbyci", "description": "Desktop application for WorkAdventure", "author": "thecodingmachine", "main": "dist/main.js", @@ -11,7 +11,6 @@ "dev": "yarn build --watch --onSuccess 'yarn electron dist/main.js'", "dev:local-app": "cd ../local-app && yarn && yarn dev", "bundle": "yarn build:local-app && yarn build && electron-builder install-app-deps && electron-builder", - "release": "yarn bundle", "typecheck": "tsc --noEmit", "test": "exit 0", "lint": "yarn eslint src/ . --ext .ts", @@ -32,13 +31,13 @@ }, "devDependencies": { "@types/auto-launch": "^5.0.2", - "@typescript-eslint/eslint-plugin": "^2.26.0", - "@typescript-eslint/parser": "^2.26.0", - "electron": "^17.0.1", + "@typescript-eslint/eslint-plugin": "^5.18.0", + "@typescript-eslint/parser": "^5.18.0", + "electron": "^18.0.3", "electron-builder": "^22.14.13", - "eslint": "^6.8.0", - "prettier": "^2.5.1", - "tsup": "^5.11.13", - "typescript": "^3.8.3" + "eslint": "^8.12.0", + "prettier": "^2.6.2", + "tsup": "^5.12.4", + "typescript": "^4.6.3" } } diff --git a/desktop/electron/src/app.ts b/desktop/electron/src/app.ts index b37f13b5..8ef135c5 100644 --- a/desktop/electron/src/app.ts +++ b/desktop/electron/src/app.ts @@ -10,7 +10,7 @@ import { setLogLevel } from "./log"; import "./serve"; // prepare custom url scheme import { loadShortcuts } from "./shortcuts"; -function init() { +async function init() { const appLock = app.requestSingleInstanceLock(); if (!appLock) { @@ -21,7 +21,7 @@ function init() { app.on("second-instance", () => { // re-create window if closed - createWindow(); + void createWindow(); const mainWindow = getWindow(); @@ -36,15 +36,15 @@ function init() { }); // This method will be called when Electron has finished loading - app.whenReady().then(async () => { + await app.whenReady().then(async () => { await settings.init(); setLogLevel(settings.get("log_level") || "info"); - autoUpdater.init(); + await autoUpdater.init(); // enable auto launch - updateAutoLaunch(); + await updateAutoLaunch(); // load ipc handler ipc(); @@ -72,7 +72,7 @@ function init() { // On macOS it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (BrowserWindow.getAllWindows().length === 0) { - createWindow(); + void createWindow(); } }); diff --git a/desktop/electron/src/auto-updater.ts b/desktop/electron/src/auto-updater.ts index 5c4af88e..69bc1050 100644 --- a/desktop/electron/src/auto-updater.ts +++ b/desktop/electron/src/auto-updater.ts @@ -38,32 +38,35 @@ export async function manualRequestUpdateCheck() { isManualRequestedUpdate = false; } -function init() { +async function init() { autoUpdater.logger = log; - autoUpdater.on("update-downloaded", ({ releaseNotes, releaseName }) => { - (async () => { - const dialogOpts = { - type: "question", - buttons: ["Install and Restart", "Install Later"], - defaultId: 0, - title: "WorkAdventure - Update", - message: process.platform === "win32" ? releaseNotes : releaseName, - detail: "A new version has been downloaded. Restart the application to apply the updates.", - }; + autoUpdater.on( + "update-downloaded", + ({ releaseNotes, releaseName }: { releaseNotes: string; releaseName: string }) => { + void (async () => { + const dialogOpts = { + type: "question", + buttons: ["Install and Restart", "Install Later"], + defaultId: 0, + title: "WorkAdventure - Update", + message: process.platform === "win32" ? releaseNotes : releaseName, + detail: "A new version has been downloaded. Restart the application to apply the updates.", + }; - const { response } = await dialog.showMessageBox(dialogOpts); - if (response === 0) { - await sleep(1000); + const { response } = await dialog.showMessageBox(dialogOpts); + if (response === 0) { + await sleep(1000); - autoUpdater.quitAndInstall(); + autoUpdater.quitAndInstall(); - // Force app to quit. This is just a workaround, ideally autoUpdater.quitAndInstall() should relaunch the app. - // app.confirmedExitPrompt = true; - app.quit(); - } - })(); - }); + // Force app to quit. This is just a workaround, ideally autoUpdater.quitAndInstall() should relaunch the app. + // app.confirmedExitPrompt = true; + app.quit(); + } + })(); + } + ); if (process.platform === "linux" && !process.env.APPIMAGE) { autoUpdater.autoDownload = false; @@ -85,7 +88,7 @@ function init() { } }); - checkForUpdates(); + await checkForUpdates(); // run update check every hour again setInterval(() => checkForUpdates, 1000 * 60 * 1); diff --git a/desktop/electron/src/ipc.ts b/desktop/electron/src/ipc.ts index f8083c3f..7a36d4ed 100644 --- a/desktop/electron/src/ipc.ts +++ b/desktop/electron/src/ipc.ts @@ -1,4 +1,4 @@ -import { ipcMain, app } from "electron"; +import { ipcMain, app, desktopCapturer } from "electron"; import electronIsDev from "electron-is-dev"; import { createAndShowNotification } from "./notification"; import { Server } from "./preload-local-app/types"; @@ -30,10 +30,18 @@ export default () => { ipcMain.handle("get-version", () => (electronIsDev ? "dev" : app.getVersion())); // app ipc - ipcMain.on("app:notify", (event, txt) => { + ipcMain.on("app:notify", (event, txt: string) => { createAndShowNotification({ body: txt }); }); + ipcMain.handle("app:getDesktopCapturerSources", async (event, options: Electron.SourcesOptions) => { + return (await desktopCapturer.getSources(options)).map((source) => ({ + id: source.id, + name: source.name, + thumbnailURL: source.thumbnail.toDataURL(), + })); + }); + // local-app ipc ipcMain.handle("local-app:showLocalApp", () => { hideAppView(); @@ -43,7 +51,7 @@ export default () => { return settings.get("servers"); }); - ipcMain.handle("local-app:selectServer", (event, serverId: string) => { + ipcMain.handle("local-app:selectServer", async (event, serverId: string) => { const servers = settings.get("servers") || []; const selectedServer = servers.find((s) => s._id === serverId); @@ -51,7 +59,7 @@ export default () => { return new Error("Server not found"); } - showAppView(selectedServer.url); + await showAppView(selectedServer.url); return true; }); diff --git a/desktop/electron/src/log.ts b/desktop/electron/src/log.ts index 2c9d6e6c..8aadbbd6 100644 --- a/desktop/electron/src/log.ts +++ b/desktop/electron/src/log.ts @@ -15,6 +15,7 @@ function onError(e: Error) { function onRejection(reason: Error) { if (reason instanceof Error) { let _reason = reason; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const errPrototype = Object.getPrototypeOf(reason); const nameProperty = Object.getOwnPropertyDescriptor(errPrototype, "name"); diff --git a/desktop/electron/src/main.ts b/desktop/electron/src/main.ts index 6d4bcb6a..1089a76c 100644 --- a/desktop/electron/src/main.ts +++ b/desktop/electron/src/main.ts @@ -2,4 +2,4 @@ import app from "./app"; import log from "./log"; log.init(); -app.init(); +void app.init(); diff --git a/desktop/electron/src/preload-app/preload.ts b/desktop/electron/src/preload-app/preload.ts index 702cbef5..91f3b115 100644 --- a/desktop/electron/src/preload-app/preload.ts +++ b/desktop/electron/src/preload-app/preload.ts @@ -8,6 +8,7 @@ const api: WorkAdventureDesktopApi = { notify: (txt) => ipcRenderer.send("app:notify", txt), onMuteToggle: (callback) => ipcRenderer.on("app:on-mute-toggle", callback), onCameraToggle: (callback) => ipcRenderer.on("app:on-camera-toggle", callback), + getDesktopCapturerSources: (options) => ipcRenderer.invoke("app:getDesktopCapturerSources", options), }; contextBridge.exposeInMainWorld("WAD", api); diff --git a/desktop/electron/src/preload-app/types.ts b/desktop/electron/src/preload-app/types.ts index 164153a5..4069f7de 100644 --- a/desktop/electron/src/preload-app/types.ts +++ b/desktop/electron/src/preload-app/types.ts @@ -1,3 +1,15 @@ +// copy of Electron.SourcesOptions to avoid Electron dependency in front +export interface SourcesOptions { + types: string[]; + thumbnailSize?: { height: number; width: number }; +} + +export interface DesktopCapturerSource { + id: string; + name: string; + thumbnailURL: string; +} + export type WorkAdventureDesktopApi = { desktop: boolean; isDevelopment: () => Promise; @@ -5,4 +17,5 @@ export type WorkAdventureDesktopApi = { notify: (txt: string) => void; onMuteToggle: (callback: () => void) => void; onCameraToggle: (callback: () => void) => void; + getDesktopCapturerSources: (options: SourcesOptions) => Promise; }; diff --git a/desktop/electron/src/tray.ts b/desktop/electron/src/tray.ts index cc72b1aa..c611c5ae 100644 --- a/desktop/electron/src/tray.ts +++ b/desktop/electron/src/tray.ts @@ -36,14 +36,14 @@ export function createTray() { }, { label: "Check for updates", - async click() { - await autoUpdater.manualRequestUpdateCheck(); + click() { + void autoUpdater.manualRequestUpdateCheck(); }, }, { label: "Open Logs", click() { - log.openLog(); + void log.openLog(); }, }, { diff --git a/desktop/electron/src/window.ts b/desktop/electron/src/window.ts index 02c2c240..916fcdb6 100644 --- a/desktop/electron/src/window.ts +++ b/desktop/electron/src/window.ts @@ -115,7 +115,7 @@ export async function createWindow() { } } -export function showAppView(url?: string) { +export async function showAppView(url?: string) { if (!appView) { throw new Error("App view not found"); } @@ -130,7 +130,7 @@ export function showAppView(url?: string) { mainWindow.addBrowserView(appView); if (url && url !== appViewUrl) { - appView.webContents.loadURL(url); + await appView.webContents.loadURL(url); appViewUrl = url; } diff --git a/desktop/electron/yarn.lock b/desktop/electron/yarn.lock index c856cb8c..1914c218 100644 --- a/desktop/electron/yarn.lock +++ b/desktop/electron/yarn.lock @@ -7,27 +7,6 @@ resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-5.1.1.tgz#9274ec7460652f9c632c59addf24efb1684ef876" integrity sha512-sAP4LldeWNz0lNzmTird3uWfFDWWTeg6V/MsmyyLR9X1idwKBWIgt/ZvinqQldJm3LecKEs1emkbquO6PCiLVQ== -"@babel/code-frame@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== - -"@babel/highlight@^7.16.7": - version "7.16.10" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" - integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" - js-tokens "^4.0.0" - "@develar/schema-utils@~2.6.5": version "2.6.5" resolved "https://registry.yarnpkg.com/@develar/schema-utils/-/schema-utils-2.6.5.tgz#3ece22c5838402419a6e0425f85742b961d9b6c6" @@ -63,6 +42,35 @@ dir-compare "^2.4.0" fs-extra "^9.0.1" +"@eslint/eslintrc@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.1.tgz#8b5e1c49f4077235516bc9ec7d41378c0f69b8c6" + integrity sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.3.1" + globals "^13.9.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@humanwhocodes/config-array@^0.9.2": + version "0.9.5" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7" + integrity sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + "@malept/cross-spawn-promise@^1.1.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz#504af200af6b98e198bce768bc1730c6936ae01d" @@ -130,11 +138,6 @@ dependencies: "@types/ms" "*" -"@types/eslint-visitor-keys@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" - integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== - "@types/fs-extra@^9.0.11": version "9.0.13" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.13.tgz#7594fbae04fe7f1918ce8b3d213f74ff44ac1f45" @@ -150,10 +153,10 @@ "@types/minimatch" "*" "@types/node" "*" -"@types/json-schema@^7.0.3": - version "7.0.9" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== +"@types/json-schema@^7.0.9": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== "@types/minimatch@*": version "3.0.5" @@ -170,10 +173,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.18.tgz#3b4fed5cfb58010e3a2be4b6e74615e4847f1074" integrity sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA== -"@types/node@^14.6.2": - version "14.18.12" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.12.tgz#0d4557fd3b94497d793efd4e7d92df2f83b4ef24" - integrity sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A== +"@types/node@^16.11.26": + version "16.11.26" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.26.tgz#63d204d136c9916fb4dcd1b50f9740fe86884e47" + integrity sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ== "@types/plist@^3.0.1": version "3.0.2" @@ -205,58 +208,95 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^2.26.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz#6f8ce8a46c7dea4a6f1d171d2bb8fbae6dac2be9" - integrity sha512-4zY3Z88rEE99+CNvTbXSyovv2z9PNOVffTWD2W8QF5s2prBQtwN2zadqERcrHpcR7O/+KMI3fcTAmUUhK/iQcQ== +"@typescript-eslint/eslint-plugin@^5.18.0": + version "5.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.18.0.tgz#950df411cec65f90d75d6320a03b2c98f6c3af7d" + integrity sha512-tzrmdGMJI/uii9/V6lurMo4/o+dMTKDH82LkNjhJ3adCW22YQydoRs5MwTiqxGF9CSYxPxQ7EYb4jLNlIs+E+A== dependencies: - "@typescript-eslint/experimental-utils" "2.34.0" + "@typescript-eslint/scope-manager" "5.18.0" + "@typescript-eslint/type-utils" "5.18.0" + "@typescript-eslint/utils" "5.18.0" + debug "^4.3.2" functional-red-black-tree "^1.0.1" - regexpp "^3.0.0" - tsutils "^3.17.1" + ignore "^5.1.8" + regexpp "^3.2.0" + semver "^7.3.5" + tsutils "^3.21.0" -"@typescript-eslint/experimental-utils@2.34.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz#d3524b644cdb40eebceca67f8cf3e4cc9c8f980f" - integrity sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA== +"@typescript-eslint/parser@^5.18.0": + version "5.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.18.0.tgz#2bcd4ff21df33621df33e942ccb21cb897f004c6" + integrity sha512-+08nYfurBzSSPndngnHvFw/fniWYJ5ymOrn/63oMIbgomVQOvIDhBoJmYZ9lwQOCnQV9xHGvf88ze3jFGUYooQ== dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "2.34.0" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" + "@typescript-eslint/scope-manager" "5.18.0" + "@typescript-eslint/types" "5.18.0" + "@typescript-eslint/typescript-estree" "5.18.0" + debug "^4.3.2" -"@typescript-eslint/parser@^2.26.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.34.0.tgz#50252630ca319685420e9a39ca05fe185a256bc8" - integrity sha512-03ilO0ucSD0EPTw2X4PntSIRFtDPWjrVq7C3/Z3VQHRC7+13YB55rcJI3Jt+YgeHbjUdJPcPa7b23rXCBokuyA== +"@typescript-eslint/scope-manager@5.18.0": + version "5.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.18.0.tgz#a7d7b49b973ba8cebf2a3710eefd457ef2fb5505" + integrity sha512-C0CZML6NyRDj+ZbMqh9FnPscg2PrzSaVQg3IpTmpe0NURMVBXlghGZgMYqBw07YW73i0MCqSDqv2SbywnCS8jQ== dependencies: - "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "2.34.0" - "@typescript-eslint/typescript-estree" "2.34.0" - eslint-visitor-keys "^1.1.0" + "@typescript-eslint/types" "5.18.0" + "@typescript-eslint/visitor-keys" "5.18.0" -"@typescript-eslint/typescript-estree@2.34.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz#14aeb6353b39ef0732cc7f1b8285294937cf37d5" - integrity sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg== +"@typescript-eslint/type-utils@5.18.0": + version "5.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.18.0.tgz#62dbfc8478abf36ba94a90ddf10be3cc8e471c74" + integrity sha512-vcn9/6J5D6jtHxpEJrgK8FhaM8r6J1/ZiNu70ZUJN554Y3D9t3iovi6u7JF8l/e7FcBIxeuTEidZDR70UuCIfA== dependencies: - debug "^4.1.1" - eslint-visitor-keys "^1.1.0" - glob "^7.1.6" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" + "@typescript-eslint/utils" "5.18.0" + debug "^4.3.2" + tsutils "^3.21.0" -acorn-jsx@^5.2.0: +"@typescript-eslint/types@5.18.0": + version "5.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.18.0.tgz#4f0425d85fdb863071680983853c59a62ce9566e" + integrity sha512-bhV1+XjM+9bHMTmXi46p1Led5NP6iqQcsOxgx7fvk6gGiV48c6IynY0apQb7693twJDsXiVzNXTflhplmaiJaw== + +"@typescript-eslint/typescript-estree@5.18.0": + version "5.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.18.0.tgz#6498e5ee69a32e82b6e18689e2f72e4060986474" + integrity sha512-wa+2VAhOPpZs1bVij9e5gyVu60ReMi/KuOx4LKjGx2Y3XTNUDJgQ+5f77D49pHtqef/klglf+mibuHs9TrPxdQ== + dependencies: + "@typescript-eslint/types" "5.18.0" + "@typescript-eslint/visitor-keys" "5.18.0" + debug "^4.3.2" + globby "^11.0.4" + is-glob "^4.0.3" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.18.0": + version "5.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.18.0.tgz#27fc84cf95c1a96def0aae31684cb43a37e76855" + integrity sha512-+hFGWUMMri7OFY26TsOlGa+zgjEy1ssEipxpLjtl4wSll8zy85x0GrUSju/FHdKfVorZPYJLkF3I4XPtnCTewA== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.18.0" + "@typescript-eslint/types" "5.18.0" + "@typescript-eslint/typescript-estree" "5.18.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/visitor-keys@5.18.0": + version "5.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.18.0.tgz#c7c07709823804171d569017f3b031ced7253e60" + integrity sha512-Hf+t+dJsjAKpKSkg3EHvbtEpFFb/1CiOHnvI8bjHgOD4/wAw3gKrA0i94LrbekypiZVanJu3McWJg7rWDMzRTg== + dependencies: + "@typescript-eslint/types" "5.18.0" + eslint-visitor-keys "^3.0.0" + +acorn-jsx@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^7.1.1: - version "7.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" - integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +acorn@^8.7.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" + integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== agent-base@6: version "6.0.2" @@ -270,7 +310,7 @@ ajv-keywords@^3.4.1: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0: +ajv@^6.10.0, ajv@^6.12.0, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -287,24 +327,12 @@ ansi-align@^3.0.0: dependencies: string-width "^4.1.0" -ansi-escapes@^4.2.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-regex@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^3.2.0, ansi-styles@^3.2.1: +ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -372,13 +400,6 @@ applescript@^1.0.0: resolved "https://registry.yarnpkg.com/applescript/-/applescript-1.0.0.tgz#bb87af568cad034a4e48c4bdaf6067a3a2701317" integrity sha1-u4evVoytA0pOSMS9r2Bno6JwExc= -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -406,11 +427,6 @@ assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" @@ -615,7 +631,7 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.2: +chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -624,7 +640,7 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.1.0, chalk@^4.1.1: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -632,11 +648,6 @@ chalk@^4.1.0, chalk@^4.1.1: ansi-styles "^4.1.0" supports-color "^7.1.0" -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - chokidar@^3.5.1: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" @@ -672,13 +683,6 @@ cli-boxes@^2.2.1: resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - cli-truncate@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" @@ -687,11 +691,6 @@ cli-truncate@^2.1.0: slice-ansi "^3.0.0" string-width "^4.2.0" -cli-width@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" - integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== - cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -818,18 +817,7 @@ crc@^3.8.0: dependencies: buffer "^5.1.0" -cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^7.0.1, cross-spawn@^7.0.3: +cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -848,7 +836,7 @@ data-uri-to-buffer@^4.0.0: resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b" integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA== -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: version "4.3.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== @@ -874,7 +862,7 @@ deep-extend@^0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -deep-is@~0.1.3: +deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== @@ -1087,20 +1075,15 @@ electron-window-state@^5.0.3: jsonfile "^4.0.0" mkdirp "^0.5.1" -electron@^17.0.1: - version "17.0.1" - resolved "https://registry.yarnpkg.com/electron/-/electron-17.0.1.tgz#e6c7ad2be26e7be8a5a9bac16b21920ad2671224" - integrity sha512-CBReR/QEOpgwMdt59lWCtj9wC8oHB6aAjMF1lhXcGew132xtp+C5N6EaXb/fmDceVYLouziYjbNcpeXsWrqdpA== +electron@^18.0.3: + version "18.0.3" + resolved "https://registry.yarnpkg.com/electron/-/electron-18.0.3.tgz#58713c92b44e439881540d18910d193defb0c2b4" + integrity sha512-QRUZkGL8O/8CyDmTLSjBeRsZmGTPlPVeWnnpkdNqgHYYaOc/A881FKMiNzvQ9Cj0a+rUavDdwBUfUL82U3Ay7w== dependencies: "@electron/get" "^1.13.0" - "@types/node" "^14.6.2" + "@types/node" "^16.11.26" extract-zip "^1.0.3" -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -1128,125 +1111,131 @@ es6-error@^4.1.1: resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== -esbuild-android-arm64@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.22.tgz#fb051169a63307d958aec85ad596cfc7d7770303" - integrity sha512-k1Uu4uC4UOFgrnTj2zuj75EswFSEBK+H6lT70/DdS4mTAOfs2ECv2I9ZYvr3w0WL0T4YItzJdK7fPNxcPw6YmQ== +esbuild-android-64@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.34.tgz#46bc4327dd0809937912346244eaffdb9bfc980d" + integrity sha512-XfxcfJqmMYsT/LXqrptzFxmaR3GWzXHDLdFNIhm6S00zPaQF1TBBWm+9t0RZ6LRR7iwH57DPjaOeW20vMqI4Yw== -esbuild-darwin-64@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.22.tgz#615ea0a9de67b57a293a7128d7ac83ee307a856d" - integrity sha512-d8Ceuo6Vw6HM3fW218FB6jTY6O3r2WNcTAU0SGsBkXZ3k8SDoRLd3Nrc//EqzdgYnzDNMNtrWegK2Qsss4THhw== +esbuild-android-arm64@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.34.tgz#a3f7e1ad84b8a7dcb39b5e132768b56ee7133656" + integrity sha512-T02+NXTmSRL1Mc6puz+R9CB54rSPICkXKq6+tw8B6vxZFnCPzbJxgwIX4kcluz9p8nYBjF3+lSilTGWb7+Xgew== -esbuild-darwin-arm64@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.22.tgz#82054dcfcecb15ccfd237093b8008e7745a99ad9" - integrity sha512-YAt9Tj3SkIUkswuzHxkaNlT9+sg0xvzDvE75LlBo4DI++ogSgSmKNR6B4eUhU5EUUepVXcXdRIdqMq9ppeRqfw== +esbuild-darwin-64@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.34.tgz#a0e4ab7a0cddf76761f1fb5d6bf552a376beb16e" + integrity sha512-pLRip2Bh4Ng7Bf6AMgCrSp3pPe/qZyf11h5Qo2mOfJqLWzSVjxrXW+CFRJfrOVP7TCnh/gmZSM2AFdCPB72vtw== -esbuild-freebsd-64@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.22.tgz#778a818c5b078d5cdd6bb6c0e0797217d196999b" - integrity sha512-ek1HUv7fkXMy87Qm2G4IRohN+Qux4IcnrDBPZGXNN33KAL0pEJJzdTv0hB/42+DCYWylSrSKxk3KUXfqXOoH4A== +esbuild-darwin-arm64@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.34.tgz#54c35461f82f83a7f5169d9a6a54201798977b07" + integrity sha512-vpidSJEBxx6lf1NWgXC+DCmGqesJuZ5Y8aQVVsaoO4i8tRXbXb0whChRvop/zd3nfNM4dIl5EXAky0knRX5I6w== -esbuild-freebsd-arm64@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.22.tgz#18da93b9f3db2e036f72383bfe73b28b73bb332c" - integrity sha512-zPh9SzjRvr9FwsouNYTqgqFlsMIW07O8mNXulGeQx6O5ApgGUBZBgtzSlBQXkHi18WjrosYfsvp5nzOKiWzkjQ== +esbuild-freebsd-64@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.34.tgz#aebb50248f5874d04ffeab2db8ee1ed6037e2654" + integrity sha512-m0HBjePhe0hAQJgtMRMNV9kMgIyV4/qSnzPx42kRMQBcPhgjAq1JRu4Il26czC+9FgpMbFkUktb07f/Lwnc6CA== -esbuild-linux-32@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.22.tgz#d0d5d9f5bb3536e17ac097e9512019c65b7c0234" - integrity sha512-SnpveoE4nzjb9t2hqCIzzTWBM0RzcCINDMBB67H6OXIuDa4KqFqaIgmTchNA9pJKOVLVIKd5FYxNiJStli21qg== +esbuild-freebsd-arm64@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.34.tgz#09bef288e29f18b38b0c70a9827b6ee718e36c7f" + integrity sha512-cpRc2B94L1KvMPPYB4D6G39jLqpKlD3noAMY4/e86iXXXkhUYJJEtTuyNFTa9JRpWM0xCAp4mxjHjoIiLuoCLA== -esbuild-linux-64@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.22.tgz#2773d540971999ea7f38107ef92fca753f6a8c30" - integrity sha512-Zcl9Wg7gKhOWWNqAjygyqzB+fJa19glgl2JG7GtuxHyL1uEnWlpSMytTLMqtfbmRykIHdab797IOZeKwk5g0zg== +esbuild-linux-32@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.34.tgz#67790061758e008e919e65bbc34549f55dadaca7" + integrity sha512-8nQaEaoW7MH/K/RlozJa+lE1ejHIr8fuPIHhc513UebRav7HtXgQvxHQ6VZRUkWtep23M6dd7UqhwO1tMOfzQQ== -esbuild-linux-arm64@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.22.tgz#5d4480ce6d6bffab1dd76a23158f5a5ab33e7ba4" - integrity sha512-8q/FRBJtV5IHnQChO3LHh/Jf7KLrxJ/RCTGdBvlVZhBde+dk3/qS9fFsUy+rs3dEi49aAsyVitTwlKw1SUFm+A== +esbuild-linux-64@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.34.tgz#b9b19d4ac07e37495dd2508ec843418aa71c98d6" + integrity sha512-Y3of4qQoLLlAgf042MlrY1P+7PnN9zWj8nVtw9XQG5hcLOZLz7IKpU35oeu7n4wvyaZHwvQqDJ93gRLqdJekcQ== -esbuild-linux-arm@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.22.tgz#c6391b3f7c8fa6d3b99a7e893ce0f45f3a921eef" - integrity sha512-soPDdbpt/C0XvOOK45p4EFt8HbH5g+0uHs5nUKjHVExfgR7du734kEkXR/mE5zmjrlymk5AA79I0VIvj90WZ4g== +esbuild-linux-arm64@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.34.tgz#fd84b11a6ccfe9e83e00d0c45890e9fb3a7248c1" + integrity sha512-IlWaGtj9ir7+Nrume1DGcyzBDlK8GcnJq0ANKwcI9pVw8tqr+6GD0eqyF9SF1mR8UmAp+odrx1H5NdR2cHdFHA== -esbuild-linux-mips64le@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.22.tgz#2c8dabac355c502e86c38f9f292b3517d8e181f3" - integrity sha512-SiNDfuRXhGh1JQLLA9JPprBgPVFOsGuQ0yDfSPTNxztmVJd8W2mX++c4FfLpAwxuJe183mLuKf7qKCHQs5ZnBQ== +esbuild-linux-arm@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.34.tgz#c89d4714b05265a315a97c8933508cc73950e683" + integrity sha512-9lpq1NcJqssAF7alCO6zL3gvBVVt/lKw4oetUM7OgNnRX0OWpB+ZIO9FwCrSj/dMdmgDhPLf+119zB8QxSMmAg== -esbuild-linux-ppc64le@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.22.tgz#69d71b2820d5c94306072dac6094bae38e77d1c0" - integrity sha512-6t/GI9I+3o1EFm2AyN9+TsjdgWCpg2nwniEhjm2qJWtJyJ5VzTXGUU3alCO3evopu8G0hN2Bu1Jhz2YmZD0kng== +esbuild-linux-mips64le@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.34.tgz#d60752c3fb1260dd0737532af2de2a9521656456" + integrity sha512-k3or+01Rska1AjUyNjA4buEwB51eyN/xPQAoOx1CjzAQC3l8rpjUDw55kXyL63O/1MUi4ISvtNtl8gLwdyEcxw== -esbuild-linux-riscv64@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.22.tgz#c0ec0fc3a23624deebf657781550d2329cec4213" - integrity sha512-AyJHipZKe88sc+tp5layovquw5cvz45QXw5SaDgAq2M911wLHiCvDtf/07oDx8eweCyzYzG5Y39Ih568amMTCQ== +esbuild-linux-ppc64le@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.34.tgz#f4c6229269956564f0c6f9825f5e717c2cfc22b3" + integrity sha512-+qxb8M9FfM2CJaVU7GgYpJOHM1ngQOx+/VrtBjb4C8oVqaPcESCeg2anjl+HRZy8VpYc71q/iBYausPPbJ+Keg== -esbuild-linux-s390x@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.22.tgz#ec2af4572d63336cfb27f5a5c851fb1b6617dd91" - integrity sha512-Sz1NjZewTIXSblQDZWEFZYjOK6p8tV6hrshYdXZ0NHTjWE+lwxpOpWeElUGtEmiPcMT71FiuA9ODplqzzSxkzw== +esbuild-linux-riscv64@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.34.tgz#549bd18a9eba3135b67f7b742730b5343a1be35d" + integrity sha512-Y717ltBdQ5j5sZIHdy1DV9kieo0wMip0dCmVSTceowCPYSn1Cg33Kd6981+F/3b9FDMzNWldZFOBRILViENZSA== -esbuild-netbsd-64@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.22.tgz#0e283278e9fdbaa7f0930f93ee113d7759cd865e" - integrity sha512-TBbCtx+k32xydImsHxvFgsOCuFqCTGIxhzRNbgSL1Z2CKhzxwT92kQMhxort9N/fZM2CkRCPPs5wzQSamtzEHA== +esbuild-linux-s390x@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.34.tgz#2a6b577c437f94c2b37623c755ff5215a05c12bc" + integrity sha512-bDDgYO4LhL4+zPs+WcBkXph+AQoPcQRTv18FzZS0WhjfH8TZx2QqlVPGhmhZ6WidrY+jKthUqO6UhGyIb4MpmA== -esbuild-openbsd-64@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.22.tgz#2a73bba04e16d8ef278fbe2be85248e12a2f2cc2" - integrity sha512-vK912As725haT313ANZZZN+0EysEEQXWC/+YE4rQvOQzLuxAQc2tjbzlAFREx3C8+uMuZj/q7E5gyVB7TzpcTA== +esbuild-netbsd-64@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.34.tgz#7f0b73229157975eb35597207723df52ba21722a" + integrity sha512-cfaFGXdRt0+vHsjNPyF0POM4BVSHPSbhLPe8mppDc7GDDxjIl08mV1Zou14oDWMp/XZMjYN1kWYRSfftiD0vvQ== -esbuild-sunos-64@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.22.tgz#8fe03513b8b2e682a6d79d5e3ca5849651a3c1d8" - integrity sha512-/mbJdXTW7MTcsPhtfDsDyPEOju9EOABvCjeUU2OJ7fWpX/Em/H3WYDa86tzLUbcVg++BScQDzqV/7RYw5XNY0g== +esbuild-openbsd-64@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.34.tgz#b9bc44b4f70031fb01b173b279daeffc4d4f54b7" + integrity sha512-vmy9DxXVnRiI14s8GKuYBtess+EVcDALkbpTqd5jw4XITutIzyB7n4x0Tj5utAkKsgZJB22lLWGekr0ABnSLow== -esbuild-windows-32@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.22.tgz#a75df61e3e49df292a1842be8e877a3153ee644f" - integrity sha512-1vRIkuvPTjeSVK3diVrnMLSbkuE36jxA+8zGLUOrT4bb7E/JZvDRhvtbWXWaveUc/7LbhaNFhHNvfPuSw2QOQg== +esbuild-sunos-64@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.34.tgz#512dd6085ac1a0dccc20c5f932f16a618bea409c" + integrity sha512-eNPVatNET1F7tRMhii7goL/eptfxc0ALRjrj9SPFNqp0zmxrehBFD6BaP3R4LjMn6DbMO0jOAnTLFKr8NqcJAA== -esbuild-windows-64@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.22.tgz#d06cf8bbe4945b8bf95a730d871e54a22f635941" - integrity sha512-AxjIDcOmx17vr31C5hp20HIwz1MymtMjKqX4qL6whPj0dT9lwxPexmLj6G1CpR3vFhui6m75EnBEe4QL82SYqw== +esbuild-windows-32@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.34.tgz#3ff1afd5cac08050c7c7140a59e343b06f6b037c" + integrity sha512-EFhpXyHEcnqWYe2rAHFd8dRw8wkrd9U+9oqcyoEL84GbanAYjiiIjBZsnR8kl0sCQ5w6bLpk7vCEIA2VS32Vcg== -esbuild-windows-arm64@0.14.22: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.22.tgz#f8b1b05c548073be8413a5ecb12d7c2f6e717227" - integrity sha512-5wvQ+39tHmRhNpu2Fx04l7QfeK3mQ9tKzDqqGR8n/4WUxsFxnVLfDRBGirIfk4AfWlxk60kqirlODPoT5LqMUg== +esbuild-windows-64@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.34.tgz#66f7b43d2a0b132f6748dfa3edac4fc939a99be0" + integrity sha512-a8fbl8Ky7PxNEjf1aJmtxdDZj32/hC7S1OcA2ckEpCJRTjiKslI9vAdPpSjrKIWhws4Galpaawy0nB7fjHYf5Q== -esbuild@^0.14.2: - version "0.14.22" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.22.tgz#2b55fde89d7aa5aaaad791816d58ff9dfc5ed085" - integrity sha512-CjFCFGgYtbFOPrwZNJf7wsuzesx8kqwAffOlbYcFDLFuUtP8xloK1GH+Ai13Qr0RZQf9tE7LMTHJ2iVGJ1SKZA== +esbuild-windows-arm64@0.14.34: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.34.tgz#b74a6395b7b7e53dba70b71b39542afd83352473" + integrity sha512-EYvmKbSa2B3sPnpC28UEu9jBK5atGV4BaVRE7CYGUci2Hlz4AvtV/LML+TcDMT6gBgibnN2gcltWclab3UutMg== + +esbuild@^0.14.25: + version "0.14.34" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.34.tgz#3610056f0a57bcfd0b63ddaafdb2e3bef1cf96e4" + integrity sha512-QIWdPT/gFF6hCaf4m7kP0cJ+JIuFkdHibI7vVFvu3eJS1HpVmYHWDulyN5WXwbRA0SX/7ZDaJ/1DH8SdY9xOJg== optionalDependencies: - esbuild-android-arm64 "0.14.22" - esbuild-darwin-64 "0.14.22" - esbuild-darwin-arm64 "0.14.22" - esbuild-freebsd-64 "0.14.22" - esbuild-freebsd-arm64 "0.14.22" - esbuild-linux-32 "0.14.22" - esbuild-linux-64 "0.14.22" - esbuild-linux-arm "0.14.22" - esbuild-linux-arm64 "0.14.22" - esbuild-linux-mips64le "0.14.22" - esbuild-linux-ppc64le "0.14.22" - esbuild-linux-riscv64 "0.14.22" - esbuild-linux-s390x "0.14.22" - esbuild-netbsd-64 "0.14.22" - esbuild-openbsd-64 "0.14.22" - esbuild-sunos-64 "0.14.22" - esbuild-windows-32 "0.14.22" - esbuild-windows-64 "0.14.22" - esbuild-windows-arm64 "0.14.22" + esbuild-android-64 "0.14.34" + esbuild-android-arm64 "0.14.34" + esbuild-darwin-64 "0.14.34" + esbuild-darwin-arm64 "0.14.34" + esbuild-freebsd-64 "0.14.34" + esbuild-freebsd-arm64 "0.14.34" + esbuild-linux-32 "0.14.34" + esbuild-linux-64 "0.14.34" + esbuild-linux-arm "0.14.34" + esbuild-linux-arm64 "0.14.34" + esbuild-linux-mips64le "0.14.34" + esbuild-linux-ppc64le "0.14.34" + esbuild-linux-riscv64 "0.14.34" + esbuild-linux-s390x "0.14.34" + esbuild-netbsd-64 "0.14.34" + esbuild-openbsd-64 "0.14.34" + esbuild-sunos-64 "0.14.34" + esbuild-windows-32 "0.14.34" + esbuild-windows-64 "0.14.34" + esbuild-windows-arm64 "0.14.34" escalade@^3.1.1: version "3.1.1" @@ -1268,7 +1257,7 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-scope@^5.0.0: +eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -1276,83 +1265,82 @@ eslint-scope@^5.0.0: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-utils@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== +eslint-scope@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" + integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== dependencies: - eslint-visitor-keys "^1.1.0" + esrecurse "^4.3.0" + estraverse "^5.2.0" -eslint-utils@^2.0.0: +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" - integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== - dependencies: - eslint-visitor-keys "^1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== +eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" + integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@^6.8.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" - integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== +eslint@^8.12.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.12.0.tgz#c7a5bd1cfa09079aae64c9076c07eada66a46e8e" + integrity sha512-it1oBL9alZg1S8UycLm5YDMAkIhtH6FtAzuZs6YvoGVldWjbS08BkAdb/ymP9LlAyq8koANu32U7Ib/w+UNh8Q== dependencies: - "@babel/code-frame" "^7.0.0" + "@eslint/eslintrc" "^1.2.1" + "@humanwhocodes/config-array" "^0.9.2" ajv "^6.10.0" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.3" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" - esquery "^1.0.1" + escape-string-regexp "^4.0.0" + eslint-scope "^7.1.1" + eslint-utils "^3.0.0" + eslint-visitor-keys "^3.3.0" + espree "^9.3.1" + esquery "^1.4.0" esutils "^2.0.2" - file-entry-cache "^5.0.1" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^12.1.0" - ignore "^4.0.6" + glob-parent "^6.0.1" + globals "^13.6.0" + ignore "^5.2.0" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^7.0.0" is-glob "^4.0.0" - js-yaml "^3.13.1" + js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.14" + levn "^0.4.1" + lodash.merge "^4.6.2" minimatch "^3.0.4" - mkdirp "^0.5.1" natural-compare "^1.4.0" - optionator "^0.8.3" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" - table "^5.2.3" + optionator "^0.9.1" + regexpp "^3.2.0" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^6.1.2: - version "6.2.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" - integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw== +espree@^9.3.1: + version "9.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd" + integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ== dependencies: - acorn "^7.1.1" - acorn-jsx "^5.2.0" - eslint-visitor-keys "^1.1.0" + acorn "^8.7.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^3.3.0" -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.0.1: +esquery@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== @@ -1396,15 +1384,6 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - extract-zip@^1.0.3: version "1.7.0" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" @@ -1420,7 +1399,7 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== -fast-deep-equal@^3.1.1: +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== @@ -1441,7 +1420,7 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= @@ -1468,19 +1447,12 @@ fetch-blob@^3.1.2, fetch-blob@^3.1.4: node-domexception "^1.0.0" web-streams-polyfill "^3.0.3" -figures@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" - integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" + flat-cache "^3.0.4" filelist@^1.0.1: version "1.0.2" @@ -1496,19 +1468,18 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" + flatted "^3.1.0" + rimraf "^3.0.2" -flatted@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== +flatted@^3.1.0: + version "3.2.5" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" + integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== form-data@^4.0.0: version "4.0.0" @@ -1593,13 +1564,20 @@ get-stream@^6.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -glob-parent@^5.0.0, glob-parent@^5.1.2, glob-parent@~5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" +glob-parent@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + glob@7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" @@ -1653,12 +1631,12 @@ global-tunnel-ng@^2.7.1: npm-conf "^1.1.3" tunnel "^0.0.6" -globals@^12.1.0: - version "12.4.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" - integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== +globals@^13.6.0, globals@^13.9.0: + version "13.13.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.13.0.tgz#ac32261060d8070e2719dd6998406e27d2b5727b" + integrity sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A== dependencies: - type-fest "^0.8.1" + type-fest "^0.20.2" globalthis@^1.0.1: version "1.0.2" @@ -1667,7 +1645,7 @@ globalthis@^1.0.1: dependencies: define-properties "^1.1.3" -globby@^11.0.3: +globby@^11.0.3, globby@^11.0.4: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -1763,13 +1741,6 @@ iconv-corefoundation@^1.1.7: cli-truncate "^2.1.0" node-addon-api "^1.6.3" -iconv-lite@^0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - iconv-lite@^0.6.2: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" @@ -1782,17 +1753,12 @@ ieee754@^1.1.13: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - -ignore@^5.2.0: +ignore@^5.1.8, ignore@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== -import-fresh@^3.0.0: +import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -1833,25 +1799,6 @@ ini@^1.3.4, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -inquirer@^7.0.0: - version "7.3.3" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" - integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== - dependencies: - ansi-escapes "^4.2.1" - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-width "^3.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.19" - mute-stream "0.0.8" - run-async "^2.4.0" - rxjs "^6.6.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -1878,17 +1825,12 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -1975,19 +1917,6 @@ joycon@^3.0.1: resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -2057,13 +1986,13 @@ lazy-val@^1.0.4, lazy-val@^1.0.5: resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.5.tgz#6cf3b9f5bc31cee7ee3e369c0832b7583dcd923d" integrity sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q== -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" + prelude-ls "^1.2.1" + type-check "~0.4.0" lilconfig@^2.0.4: version "2.0.4" @@ -2100,6 +2029,11 @@ lodash.isequal@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + lodash.set@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" @@ -2110,7 +2044,7 @@ lodash.unset@^4.5.2: resolved "https://registry.yarnpkg.com/lodash.unset/-/lodash.unset-4.5.2.tgz#370d1d3e85b72a7e1b0cdf2d272121306f23e4ed" integrity sha1-Nw0dPoW3Kn4bDN8tJyEhMG8j5O0= -lodash@^4.17.10, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19: +lodash@^4.17.10, lodash@^4.17.15: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -2232,11 +2166,6 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -2256,11 +2185,6 @@ new-github-issue-url@^0.2.1: resolved "https://registry.yarnpkg.com/new-github-issue-url/-/new-github-issue-url-0.2.1.tgz#e17be1f665a92de465926603e44b9f8685630c1d" integrity sha512-md4cGoxuT4T4d/HDOXbrUHkTKrp/vp+m3aOA7XXVYwNsUNMK49g3SQicTSeV5GIz/5QVGAeYRAOlyp9OvlgsYA== -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - node-addon-api@^1.6.3: version "1.7.2" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.2.tgz#3df30b95720b53c24e59948b49532b662444f54d" @@ -2322,29 +2246,24 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.0, onetime@^5.1.2: +onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" -optionator@^0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" p-cancelable@^1.0.0: version "1.1.0" @@ -2373,11 +2292,6 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" @@ -2424,27 +2338,27 @@ postcss-load-config@^3.0.1: lilconfig "^2.0.4" yaml "^1.10.2" -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== prepend-http@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= -prettier@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" - integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== +prettier@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" + integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -progress@^2.0.0, progress@^2.0.3: +progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -2520,12 +2434,7 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - -regexpp@^3.0.0: +regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== @@ -2566,27 +2475,12 @@ responselike@^1.0.2: dependencies: lowercase-keys "^1.0.0" -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -rimraf@^3.0.0: +rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -2612,11 +2506,6 @@ rollup@^2.60.0: optionalDependencies: fsevents "~2.3.2" -run-async@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== - run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -2624,19 +2513,12 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rxjs@^6.6.0: - version "6.6.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" - integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== - dependencies: - tslib "^1.9.0" - safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": +"safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -2665,12 +2547,7 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -semver@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: +semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -2689,13 +2566,6 @@ serialize-error@^7.0.1: dependencies: type-fest "^0.13.1" -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -2703,11 +2573,6 @@ shebang-command@^2.0.0: dependencies: shebang-regex "^3.0.0" -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - shebang-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" @@ -2723,15 +2588,6 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - slice-ansi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" @@ -2769,25 +2625,11 @@ sprintf-js@^1.1.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - stat-mode@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-1.0.0.tgz#68b55cb61ea639ff57136f36b216a291800d1465" integrity sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg== -string-width@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -2804,13 +2646,6 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -2823,7 +2658,7 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -strip-json-comments@^3.0.1: +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -2866,16 +2701,6 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== - dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" - temp-file@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/temp-file/-/temp-file-3.4.0.tgz#766ea28911c683996c248ef1a20eea04d51652c7" @@ -2903,11 +2728,6 @@ thenify-all@^1.0.0: dependencies: any-promise "^1.0.0" -through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - tmp-promise@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-3.0.3.tgz#60a1a1cc98c988674fcbfd23b6e3367bdeac4ce7" @@ -2915,13 +2735,6 @@ tmp-promise@^3.0.2: dependencies: tmp "^0.2.0" -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - tmp@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" @@ -2958,21 +2771,21 @@ ts-interface-checker@^0.1.9: resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== -tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tsup@^5.11.13: - version "5.11.13" - resolved "https://registry.yarnpkg.com/tsup/-/tsup-5.11.13.tgz#dd9b375513a07c1c84620b22d4164e4293d6a2bb" - integrity sha512-NVMK01gVmojZn7+iZwxRK1CzW2BIabaVMyEjs7Nm9lm4DrSf7IAqs2F3fg0vT7rH72x1cIBsW9U/TlWrCvHVQQ== +tsup@^5.12.4: + version "5.12.4" + resolved "https://registry.yarnpkg.com/tsup/-/tsup-5.12.4.tgz#5139e6d7735727cb8d0c4cdad721aaef7888f77f" + integrity sha512-uUraITfIj2h6rXAdeaVUYrZ2Is9joLFyEGZN5mGAke874JojCizb2MCUcE0wGdcERtyob5mbbFUKkMgal8SlFw== dependencies: bundle-require "^3.0.2" cac "^6.7.12" chokidar "^3.5.1" debug "^4.3.1" - esbuild "^0.14.2" + esbuild "^0.14.25" execa "^5.0.0" globby "^11.0.3" joycon "^3.0.1" @@ -2983,7 +2796,7 @@ tsup@^5.11.13: sucrase "^3.20.3" tree-kill "^1.2.2" -tsutils@^3.17.1: +tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== @@ -2995,12 +2808,12 @@ tunnel@^0.0.6: resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: - prelude-ls "~1.1.2" + prelude-ls "^1.2.1" type-fest@^0.13.1: version "0.13.1" @@ -3012,16 +2825,6 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -3034,10 +2837,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^3.8.3: - version "3.9.10" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" - integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== +typescript@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c" + integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw== unique-string@^2.0.0: version "2.0.0" @@ -3124,13 +2927,6 @@ web-streams-polyfill@^3.0.3: resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz#a6b74026b38e4885869fb5c589e90b95ccfc7965" integrity sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA== -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -3150,7 +2946,7 @@ winreg@1.2.4: resolved "https://registry.yarnpkg.com/winreg/-/winreg-1.2.4.tgz#ba065629b7a925130e15779108cf540990e98d1b" integrity sha1-ugZWKbepJRMOFXeRCM9UCZDpjRs= -word-wrap@~1.2.3: +word-wrap@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== @@ -3179,13 +2975,6 @@ write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - xdg-basedir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" diff --git a/front/.eslintrc.js b/front/.eslintrc.js index d36f5c51..e3f44ef1 100644 --- a/front/.eslintrc.js +++ b/front/.eslintrc.js @@ -36,7 +36,7 @@ module.exports = { "eol-last": ["error", "always"], "@typescript-eslint/no-explicit-any": "error", "no-throw-literal": "error", - "@typescript-eslint/no-unused-vars": ["error"], + "@typescript-eslint/no-unused-vars": ["error", { "args": "none", "caughtErrors": "all", "varsIgnorePattern": "_exhaustiveCheck" }], // TODO: remove those ignored rules and write a stronger code! "@typescript-eslint/no-unsafe-call": "off", "@typescript-eslint/restrict-plus-operands": "off", diff --git a/front/package.json b/front/package.json index 187a10f8..1dd4cb3e 100644 --- a/front/package.json +++ b/front/package.json @@ -42,8 +42,8 @@ "buffer": "^6.0.3", "cancelable-promise": "^4.2.1", "cross-env": "^7.0.3", - "deep-copy-ts": "^0.5.0", "dompurify" : "^2.3.6", + "deep-copy-ts": "^0.5.4", "easystarjs": "^0.4.4", "fast-deep-equal": "^3.1.3", "google-protobuf": "^3.13.0", diff --git a/front/src/Api/IframeListener.ts b/front/src/Api/IframeListener.ts index 0d32f5ff..4ba156ae 100644 --- a/front/src/Api/IframeListener.ts +++ b/front/src/Api/IframeListener.ts @@ -297,7 +297,6 @@ class IframeListener { handleMenuUnregisterEvent(iframeEvent.data.name); } else { // Keep the line below. It will throw an error if we forget to handle one of the possible values. - // eslint-disable-next-line @typescript-eslint/no-unused-vars const _exhaustiveCheck: never = iframeEvent; } } diff --git a/front/src/Api/desktop/index.ts b/front/src/Api/desktop/index.ts index 6e38403c..239ec8cf 100644 --- a/front/src/Api/desktop/index.ts +++ b/front/src/Api/desktop/index.ts @@ -4,7 +4,7 @@ import { WorkAdventureDesktopApi } from "@wa-preload-app"; declare global { interface Window { - WAD: WorkAdventureDesktopApi; + WAD?: WorkAdventureDesktopApi; } } diff --git a/front/src/Api/iframe/state.ts b/front/src/Api/iframe/state.ts index c6664926..82aef735 100644 --- a/front/src/Api/iframe/state.ts +++ b/front/src/Api/iframe/state.ts @@ -88,7 +88,6 @@ export function createState(target: "global" | "player"): WorkadventureStateComm } return target.loadVariable(p.toString()); }, - // eslint-disable-next-line @typescript-eslint/no-unused-vars set(target: WorkadventureStateCommands, p: PropertyKey, value: unknown, receiver: unknown): boolean { // Note: when using "set", there is no way to wait, so we ignore the return of the promise. // User must use WA.state.saveVariable to have error message. diff --git a/front/src/Components/App.svelte b/front/src/Components/App.svelte index c596c8ee..da1ca6f0 100644 --- a/front/src/Components/App.svelte +++ b/front/src/Components/App.svelte @@ -2,6 +2,7 @@ import type { Game } from "../Phaser/Game/Game"; import { chatVisibilityStore } from "../Stores/ChatStore"; import { errorStore } from "../Stores/ErrorStore"; + import { errorScreenStore } from "../Stores/ErrorScreenStore"; import { loginSceneVisibleStore } from "../Stores/LoginSceneStore"; import { enableCameraSceneVisibilityStore } from "../Stores/MediaStore"; import { selectCharacterSceneVisibleStore } from "../Stores/SelectCharacterStore"; @@ -13,11 +14,16 @@ import SelectCharacterScene from "./selectCharacter/SelectCharacterScene.svelte"; import SelectCompanionScene from "./SelectCompanion/SelectCompanionScene.svelte"; import ErrorDialog from "./UI/ErrorDialog.svelte"; + import ErrorScreen from "./UI/ErrorScreen.svelte"; export let game: Game; -{#if $errorStore.length > 0} +{#if $errorScreenStore !== undefined} +
+ +
+{:else if $errorStore.length > 0}
diff --git a/front/src/Components/MainLayout.svelte b/front/src/Components/MainLayout.svelte index 01e45322..4ddf83dd 100644 --- a/front/src/Components/MainLayout.svelte +++ b/front/src/Components/MainLayout.svelte @@ -38,6 +38,7 @@ import { actionsMenuStore } from "../Stores/ActionsMenuStore"; import ActionsMenu from "./ActionsMenu/ActionsMenu.svelte"; import Lazy from "./Lazy.svelte"; + import { showDesktopCapturerSourcePicker } from "../Stores/ScreenSharingStore"; let mainLayout: HTMLDivElement; @@ -119,6 +120,11 @@ import("./EmoteMenu/EmoteMenu.svelte")} /> + import("./Video/DesktopCapturerSourcePicker.svelte")} + /> + {#if hasEmbedScreen} {/if} diff --git a/front/src/Components/UI/ErrorScreen.svelte b/front/src/Components/UI/ErrorScreen.svelte new file mode 100644 index 00000000..bac59594 --- /dev/null +++ b/front/src/Components/UI/ErrorScreen.svelte @@ -0,0 +1,144 @@ + + +
+
+ +
+ {#if $errorScreenStore.type !== "retry"}

{$errorScreenStore.title}

{/if} +

{$errorScreenStore.subtitle}

+ {#if $errorScreenStore.type !== "retry"}

Code : {$errorScreenStore.code}

{/if} +

+ {detailsStylized}{#if $errorScreenStore.type === "retry"}

{/if} +

+ {#if $errorScreenStore.type === "retry" && $errorScreenStore.canRetryManual} + + {/if} +
+
+ + diff --git a/front/src/Components/Video/DesktopCapturerSourcePicker.svelte b/front/src/Components/Video/DesktopCapturerSourcePicker.svelte new file mode 100644 index 00000000..92eb41ae --- /dev/null +++ b/front/src/Components/Video/DesktopCapturerSourcePicker.svelte @@ -0,0 +1,171 @@ + + +
+ +

Select a Screen or Window to share!

+
+ {#each desktopCapturerSources as source} +
selectDesktopCapturerSource(source)} + > + {source.name} +
+ {source.name} +
+
+ {/each} +
+
+ + diff --git a/front/src/Components/images/logo-min-white.png b/front/src/Components/images/logo-min-white.png new file mode 100644 index 00000000..7e5796b0 Binary files /dev/null and b/front/src/Components/images/logo-min-white.png differ diff --git a/front/src/Components/images/reload.png b/front/src/Components/images/reload.png new file mode 100644 index 00000000..414af00c Binary files /dev/null and b/front/src/Components/images/reload.png differ diff --git a/front/src/Components/selectCharacter/SelectCharacterScene.svelte b/front/src/Components/selectCharacter/SelectCharacterScene.svelte index 807cf88f..ecf00828 100644 --- a/front/src/Components/selectCharacter/SelectCharacterScene.svelte +++ b/front/src/Components/selectCharacter/SelectCharacterScene.svelte @@ -2,18 +2,19 @@ import type { Game } from "../../Phaser/Game/Game"; import { SelectCharacterScene, SelectCharacterSceneName } from "../../Phaser/Login/SelectCharacterScene"; import LL from "../../i18n/i18n-svelte"; - import { customizeAvailableStore } from "../../Stores/SelectCharacterSceneStore"; + import { customizeAvailableStore, selectedCollection } from "../../Stores/SelectCharacterSceneStore"; export let game: Game; const selectCharacterScene = game.scene.getScene(SelectCharacterSceneName) as SelectCharacterScene; + const showArrows = selectCharacterScene.getCollectionKeysSize() > 1; function selectLeft() { - selectCharacterScene.moveToLeft(); + selectCharacterScene.selectPreviousCollection(); } function selectRight() { - selectCharacterScene.moveToRight(); + selectCharacterScene.selectNextCollection(); } function cameraScene() { @@ -25,83 +26,72 @@ } -
-
-

{$LL.woka.selectWoka.title()}

- - -
-
+
+

{$LL.woka.selectWoka.title()}

+
+
+ {#if showArrows} + + {$selectedCollection} + + {/if} +
+
+ + {#if $customizeAvailableStore} {$LL.woka.selectWoka.customize()} - {#if $customizeAvailableStore} - - {/if} -
- + {/if} +
diff --git a/front/src/Connexion/RoomConnection.ts b/front/src/Connexion/RoomConnection.ts index 04993226..17725bdf 100644 --- a/front/src/Connexion/RoomConnection.ts +++ b/front/src/Connexion/RoomConnection.ts @@ -25,6 +25,7 @@ import { TokenExpiredMessage, WorldConnexionMessage, ErrorMessage as ErrorMessageTsProto, + ErrorScreenMessage as ErrorScreenMessageTsProto, UserMovedMessage as UserMovedMessageTsProto, GroupUpdateMessage as GroupUpdateMessageTsProto, GroupDeleteMessage as GroupDeleteMessageTsProto, @@ -47,6 +48,7 @@ import { Subject } from "rxjs"; import { selectCharacterSceneVisibleStore } from "../Stores/SelectCharacterStore"; import { gameManager } from "../Phaser/Game/GameManager"; import { SelectCharacterScene, SelectCharacterSceneName } from "../Phaser/Login/SelectCharacterScene"; +import { errorScreenStore } from "../Stores/ErrorScreenStore"; const manualPingDelay = 20000; @@ -62,6 +64,9 @@ export class RoomConnection implements RoomConnection { private readonly _errorMessageStream = new Subject(); public readonly errorMessageStream = this._errorMessageStream.asObservable(); + private readonly _errorScreenMessageStream = new Subject(); + public readonly errorScreenMessageStream = this._errorScreenMessageStream.asObservable(); + private readonly _roomJoinedMessageStream = new Subject<{ connection: RoomConnection; room: RoomJoinedMessageInterface; @@ -298,8 +303,7 @@ export class RoomConnection implements RoomConnection { } default: { // Security check: if we forget a "case", the line below will catch the error at compile-time. - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const tmp: never = subMessage; + const _exhaustiveCheck: never = subMessage; } } } @@ -477,10 +481,16 @@ export class RoomConnection implements RoomConnection { console.error("An error occurred server side: " + message.errorMessage.message); break; } + case "errorScreenMessage": { + this._errorScreenMessageStream.next(message.errorScreenMessage); + if (message.errorScreenMessage.code !== "retry") this.closed = true; + console.error("An error occurred server side: " + message.errorScreenMessage.code); + errorScreenStore.setError(message.errorScreenMessage); + break; + } default: { // Security check: if we forget a "case", the line below will catch the error at compile-time. - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const tmp: never = message; + const _exhaustiveCheck: never = message; } } }; diff --git a/front/src/Phaser/Components/SelectWoka/WokaSlot.ts b/front/src/Phaser/Components/SelectWoka/WokaSlot.ts new file mode 100644 index 00000000..696a9db7 --- /dev/null +++ b/front/src/Phaser/Components/SelectWoka/WokaSlot.ts @@ -0,0 +1,35 @@ +import { GridItem } from "@home-based-studio/phaser3-utils"; + +export class WokaSlot extends GridItem { + private sprite: Phaser.GameObjects.Sprite; + private selection: Phaser.GameObjects.Rectangle; + + private readonly SIZE: number = 50; + + constructor(scene: Phaser.Scene, spriteKey: string, id?: string) { + super(scene, id); + + this.sprite = this.scene.add.sprite(0, 0, spriteKey); + this.selection = this.scene.add + .rectangle(0, 0, this.SIZE, this.SIZE) + .setStrokeStyle(1, 0xffffff) + .setVisible(false); + + this.add([this.selection, this.sprite]); + this.setSize(this.SIZE, this.SIZE); + this.setInteractive({ cursor: "pointer" }); + this.scene.input.setDraggable(this); + + this.bindEventHandlers(); + + this.scene.add.existing(this); + } + + public getSprite(): Phaser.GameObjects.Sprite { + return this.sprite; + } + + public select(select: boolean = true): void { + this.selection.setVisible(select); + } +} diff --git a/front/src/Phaser/Entity/PlayerTextures.ts b/front/src/Phaser/Entity/PlayerTextures.ts index e1413f6d..66e02c7b 100644 --- a/front/src/Phaser/Entity/PlayerTextures.ts +++ b/front/src/Phaser/Entity/PlayerTextures.ts @@ -36,14 +36,16 @@ export enum PlayerTexturesKey { } export class PlayerTextures { - private PLAYER_RESOURCES: BodyResourceDescriptionListInterface = {}; - private COLOR_RESOURCES: BodyResourceDescriptionListInterface = {}; - private EYES_RESOURCES: BodyResourceDescriptionListInterface = {}; - private HAIR_RESOURCES: BodyResourceDescriptionListInterface = {}; - private CLOTHES_RESOURCES: BodyResourceDescriptionListInterface = {}; - private HATS_RESOURCES: BodyResourceDescriptionListInterface = {}; - private ACCESSORIES_RESOURCES: BodyResourceDescriptionListInterface = {}; - private LAYERS: BodyResourceDescriptionListInterface[] = []; + private wokaResources: BodyResourceDescriptionListInterface = {}; + private colorResources: BodyResourceDescriptionListInterface = {}; + private eyesResources: BodyResourceDescriptionListInterface = {}; + private hairResources: BodyResourceDescriptionListInterface = {}; + private clothesResources: BodyResourceDescriptionListInterface = {}; + private hatsResources: BodyResourceDescriptionListInterface = {}; + private accessoriesResources: BodyResourceDescriptionListInterface = {}; + private layers: BodyResourceDescriptionListInterface[] = []; + + private wokaCollections = new Map(); public loadPlayerTexturesMetadata(metadata: WokaList): void { this.mapTexturesMetadataIntoResources(metadata); @@ -52,43 +54,53 @@ export class PlayerTextures { public getTexturesResources(key: PlayerTexturesKey): BodyResourceDescriptionListInterface { switch (key) { case PlayerTexturesKey.Accessory: - return this.ACCESSORIES_RESOURCES; + return this.accessoriesResources; case PlayerTexturesKey.Body: - return this.COLOR_RESOURCES; + return this.colorResources; case PlayerTexturesKey.Clothes: - return this.CLOTHES_RESOURCES; + return this.clothesResources; case PlayerTexturesKey.Eyes: - return this.EYES_RESOURCES; + return this.eyesResources; case PlayerTexturesKey.Hair: - return this.HAIR_RESOURCES; + return this.hairResources; case PlayerTexturesKey.Hat: - return this.HATS_RESOURCES; + return this.hatsResources; case PlayerTexturesKey.Woka: - return this.PLAYER_RESOURCES; + return this.wokaResources; } } public getLayers(): BodyResourceDescriptionListInterface[] { - return this.LAYERS; + return this.layers; + } + + public getCollectionsKeys(): string[] { + return Array.from(this.wokaCollections.keys()); + } + + public getWokaCollectionTextures(key: string): BodyResourceDescriptionInterface[] { + return this.wokaCollections.get(key) ?? []; } private mapTexturesMetadataIntoResources(metadata: WokaList): void { - this.PLAYER_RESOURCES = this.getMappedResources(metadata.woka); - this.COLOR_RESOURCES = this.getMappedResources(metadata.body); - this.EYES_RESOURCES = this.getMappedResources(metadata.eyes); - this.HAIR_RESOURCES = this.getMappedResources(metadata.hair); - this.CLOTHES_RESOURCES = this.getMappedResources(metadata.clothes); - this.HATS_RESOURCES = this.getMappedResources(metadata.hat); - this.ACCESSORIES_RESOURCES = this.getMappedResources(metadata.accessory); + this.wokaResources = this.getMappedResources(metadata.woka); + this.colorResources = this.getMappedResources(metadata.body); + this.eyesResources = this.getMappedResources(metadata.eyes); + this.hairResources = this.getMappedResources(metadata.hair); + this.clothesResources = this.getMappedResources(metadata.clothes); + this.hatsResources = this.getMappedResources(metadata.hat); + this.accessoriesResources = this.getMappedResources(metadata.accessory); - this.LAYERS = [ - this.COLOR_RESOURCES, - this.EYES_RESOURCES, - this.HAIR_RESOURCES, - this.CLOTHES_RESOURCES, - this.HATS_RESOURCES, - this.ACCESSORIES_RESOURCES, + this.layers = [ + this.colorResources, + this.eyesResources, + this.hairResources, + this.clothesResources, + this.hatsResources, + this.accessoriesResources, ]; + + this.mapWokaCollections(metadata.woka); } private getMappedResources(category: WokaPartType): BodyResourceDescriptionListInterface { @@ -103,6 +115,19 @@ export class PlayerTextures { } return resources; } + + private mapWokaCollections(category: WokaPartType): void { + if (!category) { + return; + } + for (const collection of category.collections) { + const textures: BodyResourceDescriptionInterface[] = []; + for (const texture of collection.textures) { + textures.push({ id: texture.id, img: texture.url }); + } + this.wokaCollections.set(collection.name, textures); + } + } } export const OBJECTS: BodyResourceDescriptionInterface[] = [ diff --git a/front/src/Phaser/Game/CameraManager.ts b/front/src/Phaser/Game/CameraManager.ts index 0049890a..3c4f6035 100644 --- a/front/src/Phaser/Game/CameraManager.ts +++ b/front/src/Phaser/Game/CameraManager.ts @@ -97,7 +97,6 @@ export class CameraManager extends Phaser.Events.EventEmitter { }); return; } - // eslint-disable-next-line @typescript-eslint/no-unused-vars this.camera.pan(setTo.x, setTo.y, duration, Easing.SineEaseOut, true, (camera, progress, x, y) => { if (this.cameraMode === CameraMode.Positioned) { this.waScaleManager.zoomModifier = currentZoomModifier + progress * zoomModifierChange; @@ -139,7 +138,6 @@ export class CameraManager extends Phaser.Events.EventEmitter { this.emit(CameraManagerEvent.CameraUpdate, this.getCameraUpdateEventData()); return; } - // eslint-disable-next-line @typescript-eslint/no-unused-vars this.camera.pan(focusOn.x, focusOn.y, duration, Easing.SineEaseOut, true, (camera, progress, x, y) => { this.waScaleManager.zoomModifier = currentZoomModifier + progress * zoomModifierChange; if (progress === 1) { diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index e7677a6a..33cacaaf 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -177,8 +177,6 @@ export class GameScene extends DirtyScene { private localVolumeStoreUnsubscriber: Unsubscriber | undefined; private followUsersColorStoreUnsubscribe!: Unsubscriber; - private currentPlayerGroupIdStoreUnsubscribe!: Unsubscriber; - private privacyShutdownStoreUnsubscribe!: Unsubscriber; private userIsJitsiDominantSpeakerStoreUnsubscriber!: Unsubscriber; private jitsiParticipantsCountStoreUnsubscriber!: Unsubscriber; @@ -1593,7 +1591,6 @@ export class GameScene extends DirtyScene { this.emoteUnsubscribe(); this.emoteMenuUnsubscribe(); this.followUsersColorStoreUnsubscribe(); - this.privacyShutdownStoreUnsubscribe(); this.biggestAvailableAreaStoreUnsubscribe(); this.userIsJitsiDominantSpeakerStoreUnsubscriber(); this.jitsiParticipantsCountStoreUnsubscriber(); @@ -1733,7 +1730,6 @@ export class GameScene extends DirtyScene { private createCollisionWithPlayer() { //add collision layer for (const phaserLayer of this.gameMap.phaserLayers) { - // eslint-disable-next-line @typescript-eslint/no-unused-vars this.physics.add.collider(this.CurrentPlayer, phaserLayer, (object1: GameObject, object2: GameObject) => { //this.CurrentPlayer.say("Collision with layer : "+ (object2 as Tile).layer.name) }); @@ -1784,11 +1780,9 @@ export class GameScene extends DirtyScene { emoteMenuStore.openEmoteMenu(); } }); - // eslint-disable-next-line @typescript-eslint/no-unused-vars this.CurrentPlayer.on(Phaser.Input.Events.POINTER_OVER, (pointer: Phaser.Input.Pointer) => { this.CurrentPlayer.pointerOverOutline(0x365dff); }); - // eslint-disable-next-line @typescript-eslint/no-unused-vars this.CurrentPlayer.on(Phaser.Input.Events.POINTER_OUT, (pointer: Phaser.Input.Pointer) => { this.CurrentPlayer.pointerOutOutline(); }); @@ -1890,8 +1884,7 @@ export class GameScene extends DirtyScene { break; } default: { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const tmp: never = event; + const _exhaustiveCheck: never = event; } } } diff --git a/front/src/Phaser/Helpers/TexturesHelper.ts b/front/src/Phaser/Helpers/TexturesHelper.ts index 4476461f..45df60c1 100644 --- a/front/src/Phaser/Helpers/TexturesHelper.ts +++ b/front/src/Phaser/Helpers/TexturesHelper.ts @@ -28,7 +28,7 @@ export class TexturesHelper { }); } catch (error) { rt.destroy(); - throw new Error("Could not get the snapshot"); + throw new Error("Could not get the snapshot: " + error); } } diff --git a/front/src/Phaser/Login/AbstractCharacterScene.ts b/front/src/Phaser/Login/AbstractCharacterScene.ts index 27a4aeab..7545e26c 100644 --- a/front/src/Phaser/Login/AbstractCharacterScene.ts +++ b/front/src/Phaser/Login/AbstractCharacterScene.ts @@ -11,4 +11,8 @@ export abstract class AbstractCharacterScene extends ResizableScene { this.playerTextures = new PlayerTextures(); this.superLoad = new SuperLoaderPlugin(this); } + + preload() { + this.input.dragDistanceThreshold = 10; + } } diff --git a/front/src/Phaser/Login/CustomizeScene.ts b/front/src/Phaser/Login/CustomizeScene.ts index e03863c0..201c4db8 100644 --- a/front/src/Phaser/Login/CustomizeScene.ts +++ b/front/src/Phaser/Login/CustomizeScene.ts @@ -54,7 +54,7 @@ export class CustomizeScene extends AbstractCharacterScene { } public preload(): void { - this.input.dragDistanceThreshold = 10; + super.preload(); this.load.image("iconClothes", "/resources/icons/icon_clothes.png"); this.load.image("iconAccessory", "/resources/icons/icon_accessory.png"); @@ -112,7 +112,6 @@ export class CustomizeScene extends AbstractCharacterScene { this.onResize(); } - // eslint-disable-next-line @typescript-eslint/no-unused-vars public update(time: number, dt: number): void { this.customWokaPreviewer.update(); } diff --git a/front/src/Phaser/Login/EmptyScene.ts b/front/src/Phaser/Login/EmptyScene.ts index 9d0b0c6d..4511a160 100644 --- a/front/src/Phaser/Login/EmptyScene.ts +++ b/front/src/Phaser/Login/EmptyScene.ts @@ -13,6 +13,5 @@ export class EmptyScene extends Scene { create() {} - // eslint-disable-next-line @typescript-eslint/no-unused-vars update(time: number, delta: number): void {} } diff --git a/front/src/Phaser/Login/EnableCameraScene.ts b/front/src/Phaser/Login/EnableCameraScene.ts index 6f576b88..5ca56b71 100644 --- a/front/src/Phaser/Login/EnableCameraScene.ts +++ b/front/src/Phaser/Login/EnableCameraScene.ts @@ -24,7 +24,6 @@ export class EnableCameraScene extends ResizableScene { public onResize(): void {} - // eslint-disable-next-line @typescript-eslint/no-unused-vars update(time: number, delta: number): void {} public login(): void { diff --git a/front/src/Phaser/Login/EntryScene.ts b/front/src/Phaser/Login/EntryScene.ts index 41910f26..dce7216d 100644 --- a/front/src/Phaser/Login/EntryScene.ts +++ b/front/src/Phaser/Login/EntryScene.ts @@ -1,12 +1,12 @@ import { gameManager } from "../Game/GameManager"; import { Scene } from "phaser"; import { ErrorScene } from "../Reconnecting/ErrorScene"; -import { WAError } from "../Reconnecting/WAError"; import { waScaleManager } from "../Services/WaScaleManager"; import { ReconnectingTextures } from "../Reconnecting/ReconnectingScene"; -import LL from "../../i18n/i18n-svelte"; -import { get } from "svelte/store"; import { localeDetector } from "../../i18n/locales"; +import { errorScreenStore } from "../../Stores/ErrorScreenStore"; +import { isErrorApiData } from "../../Messages/JsonMessages/ErrorApiData"; +import { connectionManager } from "../../Connexion/ConnectionManager"; export const EntrySceneName = "EntryScene"; @@ -47,27 +47,13 @@ export class EntryScene extends Scene { this.scene.start(nextSceneName); }) .catch((err) => { - const $LL = get(LL); - if (err.response && err.response.status == 404) { - ErrorScene.showError( - new WAError( - $LL.error.accessLink.title(), - $LL.error.accessLink.subTitle(), - $LL.error.accessLink.details() - ), - this.scene - ); - } else if (err.response && err.response.status == 403) { - ErrorScene.showError( - new WAError( - $LL.error.connectionRejected.title(), - $LL.error.connectionRejected.subTitle({ - error: err.response.data ? ". \n\r \n\r" + `${err.response.data}` : "", - }), - $LL.error.connectionRejected.details() - ), - this.scene - ); + const errorType = isErrorApiData.safeParse(err?.response?.data); + if (errorType.success) { + if (errorType.data.type === "unauthorized") { + void connectionManager.logout(); + } else if (errorType.data.type === "redirect") { + window.location.assign(errorType.data.urlToRedirect); + } else errorScreenStore.setError(err?.response?.data); } else { ErrorScene.showError(err, this.scene); } diff --git a/front/src/Phaser/Login/LoginScene.ts b/front/src/Phaser/Login/LoginScene.ts index 17bd2f04..14cee6a1 100644 --- a/front/src/Phaser/Login/LoginScene.ts +++ b/front/src/Phaser/Login/LoginScene.ts @@ -49,7 +49,6 @@ export class LoginScene extends ResizableScene { loginSceneVisibleStore.set(false); } - // eslint-disable-next-line @typescript-eslint/no-unused-vars update(time: number, delta: number): void {} public onResize(): void {} diff --git a/front/src/Phaser/Login/SelectCharacterMobileScene.ts b/front/src/Phaser/Login/SelectCharacterMobileScene.ts deleted file mode 100644 index c04d6fb3..00000000 --- a/front/src/Phaser/Login/SelectCharacterMobileScene.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { SelectCharacterScene } from "./SelectCharacterScene"; - -export class SelectCharacterMobileScene extends SelectCharacterScene { - create() { - super.create(); - this.onResize(); - this.selectedRectangle.destroy(); - } - - protected defineSetupPlayer(num: number) { - const deltaX = 30; - const deltaY = 2; - let [playerX, playerY] = this.getCharacterPosition(); - let playerVisible = true; - let playerScale = 1.5; - let playerOpacity = 1; - - if (this.currentSelectUser !== num) { - playerVisible = false; - } - if (num === this.currentSelectUser + 1) { - playerY -= deltaY; - playerX += deltaX; - playerScale = 0.8; - playerOpacity = 0.6; - playerVisible = true; - } - if (num === this.currentSelectUser + 2) { - playerY -= deltaY; - playerX += deltaX * 2; - playerScale = 0.8; - playerOpacity = 0.6; - playerVisible = true; - } - if (num === this.currentSelectUser - 1) { - playerY -= deltaY; - playerX -= deltaX; - playerScale = 0.8; - playerOpacity = 0.6; - playerVisible = true; - } - if (num === this.currentSelectUser - 2) { - playerY -= deltaY; - playerX -= deltaX * 2; - playerScale = 0.8; - playerOpacity = 0.6; - playerVisible = true; - } - return { playerX, playerY, playerScale, playerOpacity, playerVisible }; - } - - /** - * Returns pixel position by on column and row number - */ - protected getCharacterPosition(): [number, number] { - return [this.game.renderer.width / 2, this.game.renderer.height / 3]; - } -} diff --git a/front/src/Phaser/Login/SelectCharacterScene.ts b/front/src/Phaser/Login/SelectCharacterScene.ts index 13bc1e75..30323463 100644 --- a/front/src/Phaser/Login/SelectCharacterScene.ts +++ b/front/src/Phaser/Login/SelectCharacterScene.ts @@ -1,5 +1,4 @@ import { gameManager } from "../Game/GameManager"; -import Rectangle = Phaser.GameObjects.Rectangle; import { EnableCameraSceneName } from "./EnableCameraScene"; import { CustomizeSceneName } from "./CustomizeScene"; import { localUserStore } from "../../Connexion/LocalUserStore"; @@ -13,25 +12,25 @@ import { PinchManager } from "../UserInput/PinchManager"; import { selectCharacterSceneVisibleStore } from "../../Stores/SelectCharacterStore"; import { waScaleManager } from "../Services/WaScaleManager"; import { analyticsClient } from "../../Administration/AnalyticsClient"; -import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils"; import { PUSHER_URL } from "../../Enum/EnvironmentVariable"; -import { customizeAvailableStore } from "../../Stores/SelectCharacterSceneStore"; +import { customizeAvailableStore, selectedCollection } from "../../Stores/SelectCharacterSceneStore"; +import { DraggableGrid } from "@home-based-studio/phaser3-utils"; +import { WokaSlot } from "../Components/SelectWoka/WokaSlot"; +import { DraggableGridEvent } from "@home-based-studio/phaser3-utils/lib/utils/gui/containers/grids/DraggableGrid"; import { wokaList } from "../../Messages/JsonMessages/PlayerTextures"; //todo: put this constants in a dedicated file export const SelectCharacterSceneName = "SelectCharacterScene"; export class SelectCharacterScene extends AbstractCharacterScene { - protected readonly nbCharactersPerRow = 6; - protected selectedPlayer!: Phaser.Physics.Arcade.Sprite | null; // null if we are selecting the "customize" option - protected players: Array = new Array(); + protected selectedWoka!: Phaser.GameObjects.Sprite | null; // null if we are selecting the "customize" option protected playerModels!: BodyResourceDescriptionInterface[]; - protected selectedRectangle!: Rectangle; - - protected currentSelectUser = 0; - protected pointerClicked: boolean = false; - protected pointerTimer: number = 0; + private charactersDraggableGrid!: DraggableGrid; + private collectionKeys!: string[]; + private selectedCollectionIndex!: number; + private selectedGridItemIndex?: number; + private gridRowsCount: number = 1; protected lazyloadingAttempt = true; //permit to update texture loaded after renderer private loader: Loader; @@ -44,7 +43,8 @@ export class SelectCharacterScene extends AbstractCharacterScene { this.playerTextures = new PlayerTextures(); } - preload() { + public preload() { + super.preload(); const wokaMetadataKey = "woka-list" + gameManager.currentStartedRoom.href; this.cache.json.remove(wokaMetadataKey); @@ -67,228 +67,236 @@ export class SelectCharacterScene extends AbstractCharacterScene { } ) .catch((e) => console.error(e)); + this.playerModels = loadAllDefaultModels(this.load, this.playerTextures); + this.lazyloadingAttempt = false; //this function must stay at the end of preload function this.loader.addLoader(); } - create() { + public create() { + waScaleManager.zoomModifier = 1; + this.selectedWoka = null; + this.selectedCollectionIndex = 0; + this.collectionKeys = this.playerTextures.getCollectionsKeys(); + selectedCollection.set(this.getSelectedCollectionName()); + customizeAvailableStore.set(this.isCustomizationAvailable()); selectCharacterSceneVisibleStore.set(true); - this.events.addListener("wake", () => { - waScaleManager.saveZoom(); - waScaleManager.zoomModifier = isMediaBreakpointUp("md") ? 2 : 1; - selectCharacterSceneVisibleStore.set(true); - }); if (touchScreenManager.supportTouchScreen) { new PinchManager(this); } - waScaleManager.saveZoom(); - waScaleManager.zoomModifier = isMediaBreakpointUp("md") ? 2 : 1; - - const rectangleXStart = this.game.renderer.width / 2 - (this.nbCharactersPerRow / 2) * 32 + 16; - this.selectedRectangle = this.add.rectangle(rectangleXStart, 90, 32, 32).setStrokeStyle(2, 0xffffff); - this.selectedRectangle.setDepth(2); - - /*create user*/ - this.createCurrentPlayer(); - - this.input.keyboard.on("keyup-ENTER", () => { - return this.nextSceneToCameraScene(); + this.charactersDraggableGrid = new DraggableGrid(this, { + position: { x: 0, y: 0 }, + maskPosition: { x: 0, y: 0 }, + dimension: { x: 485, y: 165 }, + horizontal: true, + repositionToCenter: true, + itemsInRow: 1, + margin: { + left: ((innerWidth - 200) / waScaleManager.getActualZoom()) * 0.5, + right: ((innerWidth - 200) / waScaleManager.getActualZoom()) * 0.5, + }, + spacing: 5, + debug: { + showDraggableSpace: false, + }, }); - this.input.keyboard.on("keydown-RIGHT", () => { - this.moveToRight(); - }); - this.input.keyboard.on("keydown-LEFT", () => { - this.moveToLeft(); - }); - this.input.keyboard.on("keydown-UP", () => { - this.moveToUp(); - }); - this.input.keyboard.on("keydown-DOWN", () => { - this.moveToDown(); - }); + this.bindEventHandlers(); + + this.onResize(); } public nextSceneToCameraScene(): void { - if (this.selectedPlayer !== null && !areCharacterLayersValid([this.selectedPlayer.texture.key])) { + if (this.selectedWoka !== null && !areCharacterLayersValid([this.selectedWoka.texture.key])) { return; } - if (!this.selectedPlayer) { + if (!this.selectedWoka) { return; } analyticsClient.validationWoka("SelectWoka"); + gameManager.setCharacterLayers([this.selectedWoka.texture.key]); + this.selectedWoka = null; this.scene.stop(SelectCharacterSceneName); - waScaleManager.restoreZoom(); - gameManager.setCharacterLayers([this.selectedPlayer.texture.key]); gameManager.tryResumingGame(EnableCameraSceneName); - this.players = []; selectCharacterSceneVisibleStore.set(false); this.events.removeListener("wake"); } public nextSceneToCustomizeScene(): void { - if (this.selectedPlayer !== null && !areCharacterLayersValid([this.selectedPlayer.texture.key])) { + if (this.selectedWoka !== null && !areCharacterLayersValid([this.selectedWoka.texture.key])) { return; } + this.selectedWoka = null; this.scene.sleep(SelectCharacterSceneName); - waScaleManager.restoreZoom(); this.scene.run(CustomizeSceneName); selectCharacterSceneVisibleStore.set(false); } - createCurrentPlayer(): void { - for (let i = 0; i < this.playerModels.length; i++) { - const playerResource = this.playerModels[i]; - //check already exist texture - if (this.players.find((c) => c.texture.key === playerResource.id)) { - continue; - } - - const [middleX, middleY] = this.getCharacterPosition(); - const player = this.physics.add.sprite(middleX, middleY, playerResource.id, 0); - this.setUpPlayer(player, i); - this.anims.create({ - key: playerResource.id, - frames: this.anims.generateFrameNumbers(playerResource.id, { start: 0, end: 11 }), - frameRate: 8, - repeat: -1, - }); - player.setInteractive().on("pointerdown", () => { - if (this.pointerClicked) { - return; - } - if (this.currentSelectUser === i) { - return; - } - //To not trigger two time the pointerdown events : - // We set a boolean to true so that pointerdown events does nothing when the boolean is true - // We set a timer that we decrease in update function to not trigger the pointerdown events twice - this.pointerClicked = true; - this.pointerTimer = 250; - this.currentSelectUser = i; - this.moveUser(); - }); - this.players.push(player); - } - if (this.currentSelectUser >= this.players.length) { - this.currentSelectUser = 0; - } - this.selectedPlayer = this.players[this.currentSelectUser]; - this.selectedPlayer.play(this.playerModels[this.currentSelectUser].id); - } - - protected moveUser() { - for (let i = 0; i < this.players.length; i++) { - const player = this.players[i]; - this.setUpPlayer(player, i); - } - this.updateSelectedPlayer(); - } - - public moveToLeft() { - if (this.currentSelectUser === 0) { - return; - } - this.currentSelectUser -= 1; - this.moveUser(); - } - - public moveToRight() { - if (this.currentSelectUser === this.players.length - 1) { - return; - } - this.currentSelectUser += 1; - this.moveUser(); - } - - protected moveToUp() { - if (this.currentSelectUser < this.nbCharactersPerRow) { - return; - } - this.currentSelectUser -= this.nbCharactersPerRow; - this.moveUser(); - } - - protected moveToDown() { - if (this.currentSelectUser + this.nbCharactersPerRow > this.players.length - 1) { - return; - } - this.currentSelectUser += this.nbCharactersPerRow; - this.moveUser(); - } - - protected defineSetupPlayer(num: number) { - const deltaX = 32; - const deltaY = 32; - let [playerX, playerY] = this.getCharacterPosition(); // player X and player y are middle of the - - playerX = playerX - deltaX * 2.5 + deltaX * (num % this.nbCharactersPerRow); // calcul position on line users - playerY = playerY - deltaY * 2 + deltaY * Math.floor(num / this.nbCharactersPerRow); // calcul position on column users - - const playerVisible = true; - const playerScale = 1; - const playerOpacity = 1; - - // if selected - if (num === this.currentSelectUser) { - this.selectedRectangle.setX(playerX); - this.selectedRectangle.setY(playerY); - } - - return { playerX, playerY, playerScale, playerOpacity, playerVisible }; - } - - protected setUpPlayer(player: Phaser.Physics.Arcade.Sprite, num: number) { - const { playerX, playerY, playerScale, playerOpacity, playerVisible } = this.defineSetupPlayer(num); - player.setBounce(0.2); - player.setCollideWorldBounds(false); - player.setVisible(playerVisible); - player.setScale(playerScale, playerScale); - player.setAlpha(playerOpacity); - player.setX(playerX); - player.setY(playerY); - } - - /** - * Returns pixel position by on column and row number - */ - protected getCharacterPosition(): [number, number] { - return [this.game.renderer.width / 2, this.game.renderer.height / 2.5]; - } - - protected updateSelectedPlayer(): void { - this.selectedPlayer?.anims?.pause(this.selectedPlayer?.anims.currentAnim.frames[0]); - const player = this.players[this.currentSelectUser]; - player?.play(this.playerModels[this.currentSelectUser].id); - this.selectedPlayer = player; - localUserStore.setPlayerCharacterIndex(this.currentSelectUser); - } - - update(time: number, delta: number): void { - // pointerTimer is set to 250 when pointerdown events is trigger - // After 250ms, pointerClicked is set to false and the pointerdown events can be trigger again - this.pointerTimer -= delta; - if (this.pointerTimer <= 0) { - this.pointerClicked = false; - } - + public update(): void { if (this.lazyloadingAttempt) { - //re-render players list - this.createCurrentPlayer(); - this.moveUser(); this.lazyloadingAttempt = false; } } public onResize(): void { - //move position of user - this.moveUser(); + this.handleCharactersGridOnResize(); + } + + public getSelectedCollectionName(): string { + return this.collectionKeys[this.selectedCollectionIndex] ?? ""; + } + + public getCollectionKeysSize(): number { + return this.playerTextures.getCollectionsKeys().length; + } + + public selectPreviousCollection(): void { + this.selectedCollectionIndex = (this.selectedCollectionIndex + 1) % this.collectionKeys.length; + selectedCollection.set(this.getSelectedCollectionName()); + this.populateGrid(); + } + + public selectNextCollection(): void { + if (this.collectionKeys.length === 1) { + return; + } + this.selectedCollectionIndex = + this.selectedCollectionIndex - 1 < 0 ? this.collectionKeys.length - 1 : this.selectedCollectionIndex - 1; + selectedCollection.set(this.getSelectedCollectionName()); + this.populateGrid(); + } + + private handleCharactersGridOnResize(): void { + const ratio = innerHeight / innerWidth; + this.gridRowsCount = ratio > 1 || innerHeight > 900 ? 2 : 1; + const gridHeight = this.gridRowsCount === 2 ? 210 : 105; + const gridWidth = innerWidth / waScaleManager.getActualZoom(); + const gridPos = { + x: this.cameras.main.worldView.x + this.cameras.main.width / 2, + y: this.cameras.main.worldView.y + this.cameras.main.height * (ratio > 1 ? 0.5 : 0.575), + }; + + try { + this.charactersDraggableGrid.changeDraggableSpacePosAndSize( + gridPos, + { x: gridWidth, y: gridHeight }, + gridPos + ); + } catch (error) { + console.warn(error); + } + this.charactersDraggableGrid.setItemsInRow(this.gridRowsCount); + this.populateGrid(); + } + + private populateGrid(): void { + const wokaDimension = 100; + + this.selectedWoka = null; + this.charactersDraggableGrid.clearAllItems(); + const textures = this.playerTextures.getWokaCollectionTextures(this.getSelectedCollectionName()); + for (let i = 0; i < textures.length; i += 1) { + const slot = new WokaSlot(this, textures[i].id).setDisplaySize(wokaDimension, wokaDimension); + this.charactersDraggableGrid.addItem(slot); + } + this.charactersDraggableGrid.moveContentToBeginning(); + void this.charactersDraggableGrid.moveContentTo(0.5, textures.length * 50); + } + + private bindEventHandlers(): void { + this.bindKeyboardEventHandlers(); + this.events.addListener("wake", () => { + selectCharacterSceneVisibleStore.set(true); + }); + + this.input.keyboard.on("keyup-ENTER", () => { + return this.nextSceneToCameraScene(); + }); + + this.charactersDraggableGrid.on(DraggableGridEvent.ItemClicked, (item: WokaSlot) => { + this.selectGridItem(item); + }); + } + + private selectGridItem(item: WokaSlot): void { + this.selectedGridItemIndex = this.charactersDraggableGrid.getAllItems().indexOf(item); + if (this.charactersDraggableGrid.getDraggableSpaceWidth() < this.charactersDraggableGrid.getGridSize().x) { + void this.charactersDraggableGrid.centerOnItem(this.selectedGridItemIndex, 500); + } + this.charactersDraggableGrid.getAllItems().forEach((slot) => (slot as WokaSlot).select(false)); + this.selectedWoka?.stop()?.setFrame(0); + this.selectedWoka = item.getSprite(); + const wokaKey = this.selectedWoka.texture.key; + this.createWokaAnimation(wokaKey); + this.selectedWoka.play(wokaKey); + item.select(true); + } + + private bindKeyboardEventHandlers(): void { + this.input.keyboard.on("keyup-SPACE", () => { + this.selectNextCollection(); + }); + this.input.keyboard.on("keydown-LEFT", () => { + this.selectNextGridItem(true, true); + }); + this.input.keyboard.on("keydown-RIGHT", () => { + this.selectNextGridItem(false, true); + }); + this.input.keyboard.on("keydown-UP", () => { + this.selectNextGridItem(true, false); + }); + this.input.keyboard.on("keydown-DOWN", () => { + this.selectNextGridItem(false, false); + }); + this.input.keyboard.on("keydown-W", () => { + this.selectNextGridItem(true, false); + }); + this.input.keyboard.on("keydown-S", () => { + this.selectNextGridItem(false, false); + }); + this.input.keyboard.on("keydown-A", () => { + this.selectNextGridItem(true, true); + }); + this.input.keyboard.on("keydown-D", () => { + this.selectNextGridItem(false, true); + }); + } + + private selectNextGridItem(previous: boolean = false, horizontally: boolean): void { + if (this.selectedGridItemIndex === undefined) { + this.selectedGridItemIndex = 0; + } + if ( + previous + ? this.selectedGridItemIndex > 0 + : this.selectedGridItemIndex < this.charactersDraggableGrid.getAllItems().length - 1 + ) { + // NOTE: getItemsInRowCount() not working properly. Fix on lib side needed + const jump = horizontally ? this.gridRowsCount : 1; + const item = this.charactersDraggableGrid.getAllItems()[ + this.selectedGridItemIndex + (previous ? -jump : jump) + ] as WokaSlot; + if (!item) { + return; + } + this.selectedGridItemIndex += previous ? -1 : 1; + this.selectGridItem(item); + } + } + + private createWokaAnimation(key: string): void { + this.anims.create({ + key, + frames: this.anims.generateFrameNumbers(key, { start: 0, end: 11 }), + frameRate: 8, + repeat: -1, + }); } private isCustomizationAvailable(): boolean { diff --git a/front/src/Phaser/Reconnecting/ErrorScene.ts b/front/src/Phaser/Reconnecting/ErrorScene.ts index ea593c45..2e86983e 100644 --- a/front/src/Phaser/Reconnecting/ErrorScene.ts +++ b/front/src/Phaser/Reconnecting/ErrorScene.ts @@ -3,7 +3,6 @@ import Image = Phaser.GameObjects.Image; import Sprite = Phaser.GameObjects.Sprite; import Text = Phaser.GameObjects.Text; import ScenePlugin = Phaser.Scenes.ScenePlugin; -import { WAError } from "./WAError"; import Axios from "axios"; export const ErrorSceneName = "ErrorScene"; @@ -88,12 +87,6 @@ export class ErrorScene extends Phaser.Scene { title: "An error occurred", subTitle: error, }); - } else if (error instanceof WAError) { - scene.start(ErrorSceneName, { - title: error.title, - subTitle: error.subTitle, - message: error.details, - }); } else if (Axios.isAxiosError(error) && error.response) { // Axios HTTP error // client received an error response (5xx, 4xx) diff --git a/front/src/Phaser/Reconnecting/WAError.ts b/front/src/Phaser/Reconnecting/WAError.ts index abc71f6c..1481c54a 100644 --- a/front/src/Phaser/Reconnecting/WAError.ts +++ b/front/src/Phaser/Reconnecting/WAError.ts @@ -1,26 +1,65 @@ export class WAError extends Error { + private _type: string; + private _code: string; private _title: string; - private _subTitle: string; + private _subtitle: string; private _details: string; + private _timeToRetry: number; + private _canRetryManual: boolean; + private _urlToRedirect: string; + private _buttonTitle: string; - constructor(title: string, subTitle: string, details: string) { - super(title + " - " + subTitle + " - " + details); + constructor( + type: string, + code: string, + title: string, + subtitle: string, + details: string, + timeToRetry: number, + canRetryManual: boolean, + urlToRedirect: string, + buttonTitle: string + ) { + super(title + " - " + subtitle + " - " + details); + + this._type = type; + this._code = code; this._title = title; - this._subTitle = subTitle; + this._subtitle = subtitle; this._details = details; + this._timeToRetry = timeToRetry; + this._canRetryManual = canRetryManual; + this._urlToRedirect = urlToRedirect; + this._buttonTitle = buttonTitle; // Set the prototype explicitly. Object.setPrototypeOf(this, WAError.prototype); } + get type(): string { + return this._type; + } + get code(): string { + return this._code; + } get title(): string { return this._title; } - - get subTitle(): string { - return this._subTitle; + get subtitle(): string { + return this._subtitle; } - get details(): string { return this._details; } + get timeToRetry(): number { + return this._timeToRetry; + } + get buttonTitle(): string { + return this._buttonTitle; + } + get urlToRedirect(): string { + return this._urlToRedirect; + } + get canRetryManual(): boolean { + return this._canRetryManual; + } } diff --git a/front/src/Phaser/UserInput/GameSceneUserInputHandler.ts b/front/src/Phaser/UserInput/GameSceneUserInputHandler.ts index fd2f48f2..c8cc9bc5 100644 --- a/front/src/Phaser/UserInput/GameSceneUserInputHandler.ts +++ b/front/src/Phaser/UserInput/GameSceneUserInputHandler.ts @@ -20,7 +20,6 @@ export class GameSceneUserInputHandler implements UserInputHandlerInterface { gameObjects: Phaser.GameObjects.GameObject[], deltaX: number, deltaY: number, - // eslint-disable-next-line @typescript-eslint/no-unused-vars deltaZ: number ): void { this.gameScene.zoomByFactor(1 - (deltaY / 53) * 0.1); @@ -68,7 +67,7 @@ export class GameSceneUserInputHandler implements UserInputHandlerInterface { this.lastY = pointer.y; } - public handlePointerDownEvent(pointer: Phaser.Input.Pointer, gameObjects: Phaser.GameObjects.GameObject[]): void { } + public handlePointerDownEvent(pointer: Phaser.Input.Pointer, gameObjects: Phaser.GameObjects.GameObject[]): void {} public handleSpaceKeyUpEvent(event: Event): Event { const activatableManager = this.gameScene.getActivatablesManager(); diff --git a/front/src/Stores/ErrorScreenStore.ts b/front/src/Stores/ErrorScreenStore.ts new file mode 100644 index 00000000..564afb92 --- /dev/null +++ b/front/src/Stores/ErrorScreenStore.ts @@ -0,0 +1,18 @@ +import { writable } from "svelte/store"; +import { ErrorScreenMessage } from "../Messages/ts-proto-generated/protos/messages"; + +/** + * A store that contains one error of type WAError to be displayed. + */ +function createErrorScreenStore() { + const { subscribe, set } = writable(undefined); + + return { + subscribe, + setError: (e: ErrorScreenMessage): void => { + set(e); + }, + }; +} + +export const errorScreenStore = createErrorScreenStore(); diff --git a/front/src/Stores/ScreenSharingStore.ts b/front/src/Stores/ScreenSharingStore.ts index 08d9f1a3..843e6212 100644 --- a/front/src/Stores/ScreenSharingStore.ts +++ b/front/src/Stores/ScreenSharingStore.ts @@ -2,6 +2,7 @@ import { derived, Readable, readable, writable } from "svelte/store"; import { peerStore } from "./PeerStore"; import type { LocalStreamStoreValue } from "./MediaStore"; import { myCameraVisibilityStore } from "./MyCameraStoreVisibility"; +import type { DesktopCapturerSource } from "@wa-preload-app"; declare const navigator: any; // eslint-disable-line @typescript-eslint/no-explicit-any @@ -91,6 +92,25 @@ export const screenSharingConstraintsStore = derived( } as MediaStreamConstraints ); +async function getDesktopCapturerSources() { + showDesktopCapturerSourcePicker.set(true); + const source = await new Promise((resolve) => { + desktopCapturerSourcePromiseResolve = resolve; + }); + if (source === null) { + return; + } + return navigator.mediaDevices.getUserMedia({ + audio: false, + video: { + mandatory: { + chromeMediaSource: "desktop", + chromeMediaSourceId: source.id, + }, + }, + }); +} + /** * A store containing the MediaStream object for ScreenSharing (or null if nothing requested, or Error if an error occurred) */ @@ -110,7 +130,9 @@ export const screenSharingLocalStreamStore = derived; - if (navigator.getDisplayMedia) { + if (window.WAD?.getDesktopCapturerSources) { + currentStreamPromise = getDesktopCapturerSources(); + } else if (navigator.getDisplayMedia) { currentStreamPromise = navigator.getDisplayMedia({ constraints }); } else if (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) { currentStreamPromise = navigator.mediaDevices.getDisplayMedia({ constraints }); @@ -200,3 +222,7 @@ export const screenSharingLocalMedia = readable( unsubscribe(); }; }); + +export const showDesktopCapturerSourcePicker = writable(false); + +export let desktopCapturerSourcePromiseResolve: ((source: DesktopCapturerSource | null) => void) | undefined; diff --git a/front/src/Stores/SelectCharacterSceneStore.ts b/front/src/Stores/SelectCharacterSceneStore.ts index 654da03c..34ca93d4 100644 --- a/front/src/Stores/SelectCharacterSceneStore.ts +++ b/front/src/Stores/SelectCharacterSceneStore.ts @@ -1,3 +1,5 @@ import { writable } from "svelte/store"; export const customizeAvailableStore = writable(false); + +export const selectedCollection = writable(); diff --git a/front/src/WebRtc/ColorGenerator.ts b/front/src/WebRtc/ColorGenerator.ts index 77038aa7..0e69ced3 100644 --- a/front/src/WebRtc/ColorGenerator.ts +++ b/front/src/WebRtc/ColorGenerator.ts @@ -14,15 +14,6 @@ export function getColorRgbFromHue(hue: number): { r: number; g: number; b: numb return hsv_to_rgb(hue, 0.5, 0.95); } -// eslint-disable-next-line @typescript-eslint/no-unused-vars -function stringToDouble(string: string): number { - let num = 1; - for (const char of string.split("")) { - num *= char.charCodeAt(0); - } - return (num % 255) / 255; -} - //todo: test this. function hsv_to_rgb(hue: number, saturation: number, brightness: number): { r: number; g: number; b: number } { const h_i = Math.floor(hue * 6); diff --git a/front/src/index.ts b/front/src/index.ts index d45829b5..11929f8d 100644 --- a/front/src/index.ts +++ b/front/src/index.ts @@ -17,14 +17,12 @@ import { localUserStore } from "./Connexion/LocalUserStore"; import { ErrorScene } from "./Phaser/Reconnecting/ErrorScene"; import { iframeListener } from "./Api/IframeListener"; import { desktopApi } from "./Api/desktop/index"; -import { SelectCharacterMobileScene } from "./Phaser/Login/SelectCharacterMobileScene"; import { HdpiManager } from "./Phaser/Services/HdpiManager"; import { waScaleManager } from "./Phaser/Services/WaScaleManager"; import { Game } from "./Phaser/Game/Game"; import App from "./Components/App.svelte"; import { HtmlUtils } from "./WebRtc/HtmlUtils"; import WebGLRenderer = Phaser.Renderer.WebGL.WebGLRenderer; -import { isMediaBreakpointUp } from "./Utils/BreakpointsUtils"; const { width, height } = coWebsiteManager.getGameSize(); const valueGameQuality = localUserStore.getGameQualityValue(); @@ -91,7 +89,7 @@ const config: GameConfig = { scene: [ EntryScene, LoginScene, - isMediaBreakpointUp("md") ? SelectCharacterMobileScene : SelectCharacterScene, + SelectCharacterScene, SelectCompanionScene, EnableCameraScene, ReconnectingScene, diff --git a/front/yarn.lock b/front/yarn.lock index 49245be3..46e8ced7 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -806,10 +806,10 @@ debug@~3.1.0: dependencies: ms "2.0.0" -deep-copy-ts@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/deep-copy-ts/-/deep-copy-ts-0.5.0.tgz#b9493d8e2bae85ef7d659c16eb707c13efb84499" - integrity sha512-/3cgBcMkznRf5BM8wu6YWz3SQUkHzgh/v1TZFjevztLj9sMjFvNFBtpN4uUtPzw/rA/TldyD6c6LRL1zno4+YA== +deep-copy-ts@^0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/deep-copy-ts/-/deep-copy-ts-0.5.4.tgz#e81b15797e4075cb3a690a1a7ac30179f2d72562" + integrity sha512-YJbPjw0YqdosorpCsa6copy1p/gJsFT9Q6Zq0tLi7D0nXh6Y/usjeIQZfkzV3HVuqY0Hl/5gM7TwgIbIWvEjlA== deep-equal@^1.0.1: version "1.1.1" diff --git a/messages/JsonMessages/ErrorApiData.ts b/messages/JsonMessages/ErrorApiData.ts new file mode 100644 index 00000000..bb029159 --- /dev/null +++ b/messages/JsonMessages/ErrorApiData.ts @@ -0,0 +1,46 @@ +import { z } from "zod"; + +/* + * WARNING! The original file is in /messages/JsonMessages. + * All other files are automatically copied from this file on container startup / build + */ + +export const isErrorApiErrorData = z.object({ + // @ts-ignore + type: z.literal("error"), + code: z.string(), + title: z.string(), + subtitle: z.string(), + details: z.string(), + image: z.string(), +}); + +export const isErrorApiRetryData = z.object({ + type: z.literal("retry"), + code: z.string(), + title: z.string(), + subtitle: z.string(), + details: z.string(), + image: z.string(), + buttonTitle: z.optional(z.nullable(z.string())), + timeToRetry: z.number(), + canRetryManual: z.boolean(), +}); + +export const isErrorApiRedirectData = z.object({ + type: z.literal("redirect"), + urlToRedirect: z.string(), +}); + +export const isErrorApiUnauthorizedData = z.object({ + type: z.literal("unauthorized"), +}); + +export const isErrorApiData = z.discriminatedUnion("type", [ + isErrorApiErrorData, + isErrorApiRetryData, + isErrorApiRedirectData, + isErrorApiUnauthorizedData, +]); + +export type ErrorApiData = z.infer; diff --git a/messages/JsonMessages/MapDetailsData.ts b/messages/JsonMessages/MapDetailsData.ts index 5ee5432c..79407fdf 100644 --- a/messages/JsonMessages/MapDetailsData.ts +++ b/messages/JsonMessages/MapDetailsData.ts @@ -7,13 +7,10 @@ import { z } from "zod"; export const isMapDetailsData = z.object({ mapUrl: z.string(), - policy_type: z.number(), - tags: z.array(z.string()), authenticationMandatory: z.optional(z.nullable(z.boolean())), - roomSlug: z.nullable(z.string()), // deprecated - contactPage: z.nullable(z.string()), group: z.nullable(z.string()), + contactPage: z.optional(z.nullable(z.string())), iframeAuthentication: z.optional(z.nullable(z.string())), // The date (in ISO 8601 format) at which the room will expire expireOn: z.optional(z.string()), diff --git a/messages/protos/messages.proto b/messages/protos/messages.proto index 8317d829..68099982 100644 --- a/messages/protos/messages.proto +++ b/messages/protos/messages.proto @@ -217,10 +217,29 @@ message UserLeftMessage { int32 userId = 1; } +/* + * ErrorMessage is only used to console.error the message in the front + */ message ErrorMessage { string message = 1; } +/* + * ErrorScreenMessage is used to show the ErrorScreen in the front + */ +message ErrorScreenMessage { + string type = 1; + google.protobuf.StringValue code = 2; + google.protobuf.StringValue title = 3; + google.protobuf.StringValue subtitle = 4; + google.protobuf.StringValue details = 5; + google.protobuf.Int32Value timeToRetry = 6; + google.protobuf.BoolValue canRetryManual = 7; + google.protobuf.StringValue urlToRedirect = 8; + google.protobuf.StringValue buttonTitle = 9; + google.protobuf.StringValue image = 10; +} + message ItemStateMessage { int32 itemId = 1; string stateJson = 2; @@ -332,6 +351,7 @@ message ServerToClientMessage { FollowAbortMessage followAbortMessage = 23; InvalidTextureMessage invalidTextureMessage = 24; GroupUsersUpdateMessage groupUsersUpdateMessage = 25; + ErrorScreenMessage errorScreenMessage = 26; } } diff --git a/package.json b/package.json index 038edf2c..ff6c2a33 100644 --- a/package.json +++ b/package.json @@ -4,5 +4,6 @@ }, "scripts": { "prepare": "husky install" - } + }, + "dependencies": {} } diff --git a/pusher/.eslintrc.json b/pusher/.eslintrc.json index 27927fea..82ee1e79 100644 --- a/pusher/.eslintrc.json +++ b/pusher/.eslintrc.json @@ -27,8 +27,8 @@ "no-unused-vars": "off", "@typescript-eslint/no-explicit-any": "error", "@typescript-eslint/no-unused-vars": [ - "error" + "error", { "args": "none", "caughtErrors": "all", "varsIgnorePattern": "_exhaustiveCheck" } ], "no-throw-literal": "error" } -} \ No newline at end of file +} diff --git a/pusher/package.json b/pusher/package.json index 22f6960e..cbd5375e 100644 --- a/pusher/package.json +++ b/pusher/package.json @@ -40,6 +40,7 @@ }, "homepage": "https://github.com/thecodingmachine/workadventure#readme", "dependencies": { + "@anatine/zod-openapi": "^1.3.0", "axios": "^0.21.2", "circular-json": "^0.5.9", "debug": "^4.3.1", @@ -48,6 +49,7 @@ "hyper-express": "^5.8.1", "jsonwebtoken": "^8.5.1", "mkdirp": "^1.0.4", + "openapi3-ts": "^2.0.2", "openid-client": "^4.7.4", "prom-client": "^12.0.0", "qs": "^6.10.3", diff --git a/pusher/src/Controller/AuthenticateController.ts b/pusher/src/Controller/AuthenticateController.ts index 70ae8cfc..2d6e029d 100644 --- a/pusher/src/Controller/AuthenticateController.ts +++ b/pusher/src/Controller/AuthenticateController.ts @@ -1,6 +1,6 @@ import { v4 } from "uuid"; import { BaseHttpController } from "./BaseHttpController"; -import { adminApi, FetchMemberDataByUuidResponse } from "../Services/AdminApi"; +import { FetchMemberDataByUuidResponse } from "../Services/AdminApi"; import { AuthTokenData, jwtTokenManager } from "../Services/JWTTokenManager"; import { parse } from "query-string"; import { openIDClient } from "../Services/OpenIDClient"; @@ -172,7 +172,8 @@ export class AuthenticateController extends BaseHttpController { authTokenData.identifier, playUri as string, IPAddress, - [] + [], + req.header("accept-language") ); if (authTokenData.accessToken == undefined) { @@ -224,7 +225,13 @@ export class AuthenticateController extends BaseHttpController { //Get user data from Admin Back Office //This is very important to create User Local in LocalStorage in WorkAdventure - const data = await adminService.fetchMemberDataByUuid(sub, playUri as string, IPAddress, []); + const data = await adminService.fetchMemberDataByUuid( + sub, + playUri as string, + IPAddress, + [], + req.header("accept-language") + ); return res.json({ ...data, authToken, username: userInfo?.username, locale: userInfo?.locale, userUuid : sub }); } catch (e) { @@ -327,13 +334,18 @@ export class AuthenticateController extends BaseHttpController { try { if (typeof organizationMemberToken != "string") throw new Error("No organization token"); - const data = await adminApi.fetchMemberDataByToken(organizationMemberToken, playUri); + const data = await adminService.fetchMemberDataByToken( + organizationMemberToken, + playUri, + req.header("accept-language") + ); const userUuid = data.userUuid; const email = data.email; const roomUrl = data.roomUrl; const mapUrlStart = data.mapUrlStart; const authToken = jwtTokenManager.createAuthToken(email || userUuid); + res.json({ authToken, userUuid, @@ -419,7 +431,7 @@ export class AuthenticateController extends BaseHttpController { //get login profile res.status(302); - res.setHeader("Location", adminApi.getProfileUrl(authTokenData.accessToken)); + res.setHeader("Location", adminService.getProfileUrl(authTokenData.accessToken)); res.send(""); return; } catch (error) { @@ -485,7 +497,8 @@ export class AuthenticateController extends BaseHttpController { * @param email * @param playUri * @param IPAddress - * @return FetchMemberDataByUuidResponse|object + * @return + |object * @private */ private async getUserByUserIdentifier( @@ -503,7 +516,7 @@ export class AuthenticateController extends BaseHttpController { userRoomToken: undefined, }; try { - data = await adminApi.fetchMemberDataByUuid(email, playUri, IPAddress, []); + data = await adminService.fetchMemberDataByUuid(email, playUri, IPAddress, []); } catch (err) { console.error("openIDCallback => fetchMemberDataByUuid", err); } diff --git a/pusher/src/Controller/BaseHttpController.ts b/pusher/src/Controller/BaseHttpController.ts index a15f7529..b48e1457 100644 --- a/pusher/src/Controller/BaseHttpController.ts +++ b/pusher/src/Controller/BaseHttpController.ts @@ -1,6 +1,7 @@ import { Server } from "hyper-express"; import Response from "hyper-express/types/components/http/Response"; import axios from "axios"; +import { isErrorApiData } from "../Messages/JsonMessages/ErrorApiData"; export class BaseHttpController { constructor(protected app: Server) { @@ -31,12 +32,15 @@ export class BaseHttpController { if (axios.isAxiosError(e) && e.response) { res.status(e.response.status); - res.send( - "An error occurred: " + - e.response.status + - " " + - (e.response.data && e.response.data.message ? e.response.data.message : e.response.statusText) - ); + const errorType = isErrorApiData.safeParse(e?.response?.data); + if (!errorType.success) { + res.send( + "An error occurred: " + + e.response.status + + " " + + (e.response.data && e.response.data.message ? e.response.data.message : e.response.statusText) + ); + } else res.json(errorType.data); return; } else { res.status(500); diff --git a/pusher/src/Controller/IoSocketController.ts b/pusher/src/Controller/IoSocketController.ts index 4c5137b1..27b66ef0 100644 --- a/pusher/src/Controller/IoSocketController.ts +++ b/pusher/src/Controller/IoSocketController.ts @@ -1,5 +1,4 @@ import { ExSocketInterface } from "../Model/Websocket/ExSocketInterface"; -import { GameRoomPolicyTypes } from "../Model/PusherRoom"; import { PointInterface } from "../Model/Websocket/PointInterface"; import { SetPlayerDetailsMessage, @@ -25,7 +24,7 @@ import { import { UserMovesMessage } from "../Messages/generated/messages_pb"; import { parse } from "query-string"; import { AdminSocketTokenData, jwtTokenManager, tokenInvalidException } from "../Services/JWTTokenManager"; -import { adminApi, FetchMemberDataByUuidResponse } from "../Services/AdminApi"; +import { FetchMemberDataByUuidResponse } from "../Services/AdminApi"; import { socketManager } from "../Services/SocketManager"; import { emitInBatch } from "../Services/IoSocketHelpers"; import { ADMIN_API_URL, ADMIN_SOCKETS_TOKEN, DISABLE_ANONYMOUS, SOCKET_IDLE_TIMER } from "../Enum/EnvironmentVariable"; @@ -39,6 +38,8 @@ import { localWokaService } from "../Services/LocalWokaService"; import { WebSocket } from "uWebSockets.js"; import { WokaDetail } from "../Messages/JsonMessages/PlayerTextures"; import { z } from "zod"; +import { adminService } from "../Services/AdminService"; +import { ErrorApiData, isErrorApiData } from "../Messages/JsonMessages/ErrorApiData"; /** * The object passed between the "open" and the "upgrade" methods when opening a websocket @@ -66,13 +67,21 @@ interface UpgradeData { }; } -interface UpgradeFailedData { +interface UpgradeFailedInvalidData { rejected: true; reason: "tokenInvalid" | "textureInvalid" | null; message: string; roomId: string; } +interface UpgradeFailedErrorData { + rejected: true; + reason: "error"; + error: ErrorApiData; +} + +type UpgradeFailedData = UpgradeFailedErrorData | UpgradeFailedInvalidData; + export class IoSocketController { private nextUserId: number = 1; @@ -234,6 +243,7 @@ export class IoSocketController { const websocketProtocol = req.getHeader("sec-websocket-protocol"); const websocketExtensions = req.getHeader("sec-websocket-extensions"); const IPAddress = req.getHeader("x-forwarded-for"); + const locale = req.getHeader("accept-language"); const roomId = query.roomId; try { @@ -285,7 +295,6 @@ export class IoSocketController { let memberMessages: unknown; let memberUserRoomToken: string | undefined; let memberTextures: WokaDetail[] = []; - const room = await socketManager.getOrCreateRoom(roomId); let userData: FetchMemberDataByUuidResponse = { email: userIdentifier, userUuid: userIdentifier, @@ -302,61 +311,52 @@ export class IoSocketController { if (ADMIN_API_URL) { try { try { - userData = await adminApi.fetchMemberDataByUuid( + userData = await adminService.fetchMemberDataByUuid( userIdentifier, roomId, IPAddress, - characterLayers + characterLayers, + locale ); } catch (err) { if (Axios.isAxiosError(err)) { - if (err?.response?.status == 404) { - // If we get an HTTP 404, the token is invalid. Let's perform an anonymous login! - - console.warn( - 'Cannot find user with email "' + - (userIdentifier || "anonymous") + - '". Performing an anonymous login instead.' - ); - } else if (err?.response?.status == 403) { - // If we get an HTTP 403, the world is full. We need to broadcast a special error to the client. - // we finish immediately the upgrade then we will close the socket as soon as it starts opening. + const errorType = isErrorApiData.safeParse(err?.response?.data); + if (errorType.success) { return res.upgrade( { rejected: true, - message: err?.response?.data.message, + reason: "error", status: err?.response?.status, - roomId, - }, + error: errorType.data, + } as UpgradeFailedData, + websocketKey, + websocketProtocol, + websocketExtensions, + context + ); + } else { + return res.upgrade( + { + rejected: true, + reason: null, + status: 500, + message: err?.response?.data, + roomId: roomId, + } as UpgradeFailedData, websocketKey, websocketProtocol, websocketExtensions, context ); } - } else { - throw err; } + throw err; } memberMessages = userData.messages; memberTags = userData.tags; memberVisitCardUrl = userData.visitCardUrl; memberTextures = userData.textures; memberUserRoomToken = userData.userRoomToken; - - if ( - room.policyType === GameRoomPolicyTypes.USE_TAGS_POLICY && - (userData.anonymous === true || !room.canAccess(memberTags)) - ) { - throw new Error("Insufficient privileges to access this room"); - } - if ( - room.policyType === GameRoomPolicyTypes.MEMBERS_ONLY_POLICY && - userData.anonymous === true - ) { - throw new Error("Use the login URL to connect"); - } - characterLayerObjs = memberTextures; } catch (e) { console.log( @@ -480,8 +480,8 @@ export class IoSocketController { socketManager.emitTokenExpiredMessage(ws); } else if (ws.reason === "textureInvalid") { socketManager.emitInvalidTextureMessage(ws); - } else if (ws.message === "World is full") { - socketManager.emitWorldFullMessage(ws); + } else if (ws.reason === "error") { + socketManager.emitErrorScreenMessage(ws, ws.error); } else { socketManager.emitConnexionErrorMessage(ws, ws.message); } diff --git a/pusher/src/Controller/MapController.ts b/pusher/src/Controller/MapController.ts index ff1ba9ad..14b2c2c9 100644 --- a/pusher/src/Controller/MapController.ts +++ b/pusher/src/Controller/MapController.ts @@ -1,11 +1,8 @@ -import { adminApi } from "../Services/AdminApi"; -import { ADMIN_API_URL, DISABLE_ANONYMOUS } from "../Enum/EnvironmentVariable"; -import { GameRoomPolicyTypes } from "../Model/PusherRoom"; -import { isMapDetailsData, MapDetailsData } from "../Messages/JsonMessages/MapDetailsData"; -import { AuthTokenData, jwtTokenManager } from "../Services/JWTTokenManager"; -import { InvalidTokenError } from "./InvalidTokenError"; +import { DISABLE_ANONYMOUS } from "../Enum/EnvironmentVariable"; +import { isMapDetailsData } from "../Messages/JsonMessages/MapDetailsData"; import { parse } from "query-string"; import { BaseHttpController } from "./BaseHttpController"; +import { adminService } from "../Services/AdminService"; export class MapController extends BaseHttpController { // Returns a map mapping map name to file name of the map @@ -107,66 +104,17 @@ export class MapController extends BaseHttpController { return; } - // If no admin URL is set, let's react on '/_/[instance]/[map url]' URLs - if (!ADMIN_API_URL) { - const roomUrl = new URL(query.playUri); - - const match = /\/_\/[^/]+\/(.+)/.exec(roomUrl.pathname); - if (!match) { - res.status(404); - res.json({}); - return; - } - - const mapUrl = roomUrl.protocol + "//" + match[1]; - - res.json({ - mapUrl, - policy_type: GameRoomPolicyTypes.ANONYMOUS_POLICY, - roomSlug: null, // Deprecated - group: null, - tags: [], - contactPage: null, - authenticationMandatory: DISABLE_ANONYMOUS, - } as MapDetailsData); - - return; - } - (async () => { try { - let userId: string | undefined = undefined; - if (query.authToken != undefined) { - let authTokenData: AuthTokenData; - try { - authTokenData = jwtTokenManager.verifyJWTToken(query.authToken as string); - userId = authTokenData.identifier; - } catch (e) { - try { - // Decode token, in this case we don't need to create new token. - authTokenData = jwtTokenManager.verifyJWTToken(query.authToken as string, true); - userId = authTokenData.identifier; - console.info("JWT expire, but decoded", userId); - } catch (e) { - if (e instanceof InvalidTokenError) { - // The token was not good, redirect user on login page - res.status(401); - res.send("Token decrypted error"); - return; - } else { - this.castErrorToResponse(e, res); - return; - } - } - } - } const mapDetails = isMapDetailsData.parse( - await adminApi.fetchMapDetails(query.playUri as string, userId) + await adminService.fetchMapDetails( + query.playUri as string, + query.authToken as string, + req.header("accept-language") + ) ); - if (DISABLE_ANONYMOUS) { - mapDetails.authenticationMandatory = true; - } + if (DISABLE_ANONYMOUS) mapDetails.authenticationMandatory = true; res.json(mapDetails); return; diff --git a/pusher/src/Model/PusherRoom.ts b/pusher/src/Model/PusherRoom.ts index 2a976e55..01a687b1 100644 --- a/pusher/src/Model/PusherRoom.ts +++ b/pusher/src/Model/PusherRoom.ts @@ -1,7 +1,6 @@ import { ExSocketInterface } from "../Model/Websocket/ExSocketInterface"; import { PositionDispatcher } from "./PositionDispatcher"; import { ViewportInterface } from "../Model/Websocket/ViewportMessage"; -import { arrayIntersect } from "../Services/ArrayHelper"; import { ZoneEventListener } from "../Model/Zone"; import { apiClientRepository } from "../Services/ApiClientRepository"; import { @@ -24,8 +23,6 @@ export enum GameRoomPolicyTypes { export class PusherRoom { private readonly positionNotifier: PositionDispatcher; - public tags: string[]; - public policyType: GameRoomPolicyTypes; private versionNumber: number = 1; private backConnection!: ClientReadableStream; private isClosing: boolean = false; @@ -33,9 +30,6 @@ export class PusherRoom { //public readonly variables = new Map(); constructor(public readonly roomUrl: string, private socketListener: ZoneEventListener) { - this.tags = []; - this.policyType = GameRoomPolicyTypes.ANONYMOUS_POLICY; - // A zone is 10 sprites wide. this.positionNotifier = new PositionDispatcher(this.roomUrl, 320, 320, this.socketListener); } @@ -53,10 +47,6 @@ export class PusherRoom { this.listeners.delete(socket); } - public canAccess(userTags: string[]): boolean { - return arrayIntersect(userTags, this.tags); - } - public isEmpty(): boolean { return this.positionNotifier.isEmpty(); } diff --git a/pusher/src/Services/AdminApi.ts b/pusher/src/Services/AdminApi.ts index 5e7fff37..b8f84141 100644 --- a/pusher/src/Services/AdminApi.ts +++ b/pusher/src/Services/AdminApi.ts @@ -7,6 +7,8 @@ import { z } from "zod"; import { isWokaDetail } from "../Messages/JsonMessages/PlayerTextures"; import qs from "qs"; import { AdminInterface } from "./AdminInterface"; +import { AuthTokenData, jwtTokenManager } from "./JWTTokenManager"; +import { InvalidTokenError } from "../Controller/InvalidTokenError"; export interface AdminBannedData { is_banned: boolean; @@ -20,6 +22,7 @@ export const isFetchMemberDataByUuidResponse = z.object({ visitCardUrl: z.nullable(z.string()), textures: z.array(isWokaDetail), messages: z.array(z.unknown()), + anonymous: z.optional(z.boolean()), userRoomToken: z.optional(z.string()), }); @@ -27,14 +30,38 @@ export const isFetchMemberDataByUuidResponse = z.object({ export type FetchMemberDataByUuidResponse = z.infer; class AdminApi implements AdminInterface { - /** - * @var playUri: is url of the room - * @var userId: can to be undefined or email or uuid - * @return MapDetailsData|RoomRedirect - */ - async fetchMapDetails(playUri: string, userId?: string): Promise { - if (!ADMIN_API_URL) { - return Promise.reject(new Error("No admin backoffice set!")); + async fetchMapDetails( + playUri: string, + authToken?: string, + locale?: string + ): Promise { + let userId: string | undefined = undefined; + if (authToken != undefined) { + let authTokenData: AuthTokenData; + try { + authTokenData = jwtTokenManager.verifyJWTToken(authToken); + userId = authTokenData.identifier; + //eslint-disable-next-line @typescript-eslint/no-unused-vars + } catch (e) { + try { + // Decode token, in this case we don't need to create new token. + authTokenData = jwtTokenManager.verifyJWTToken(authToken, true); + userId = authTokenData.identifier; + console.info("JWT expire, but decoded:", userId); + } catch (e) { + if (e instanceof InvalidTokenError) { + throw new Error("Token decrypted error"); + // The token was not good, redirect user on login page + //res.status(401); + //res.send("Token decrypted error"); + //return; + } else { + throw new Error("Error on decryption of token :" + e); + //this.castErrorToResponse(e, res); + //return; + } + } + } } const params: { playUri: string; userId?: string } = { @@ -43,7 +70,7 @@ class AdminApi implements AdminInterface { }; const res = await Axios.get>(ADMIN_API_URL + "/api/map", { - headers: { Authorization: `${ADMIN_API_TOKEN}` }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": locale ?? "en" }, params, }); @@ -69,11 +96,9 @@ class AdminApi implements AdminInterface { userIdentifier: string, playUri: string, ipAddress: string, - characterLayers: string[] + characterLayers: string[], + locale?: string ): Promise { - if (!ADMIN_API_URL) { - return Promise.reject(new Error("No admin backoffice set!")); - } const res = await Axios.get>(ADMIN_API_URL + "/api/room/access", { params: { userIdentifier, @@ -81,7 +106,7 @@ class AdminApi implements AdminInterface { ipAddress, characterLayers, }, - headers: { Authorization: `${ADMIN_API_TOKEN}` }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": locale ?? "en" }, paramsSerializer: (p) => { return qs.stringify(p, { arrayFormat: "brackets" }); }, @@ -100,14 +125,15 @@ class AdminApi implements AdminInterface { ); } - async fetchMemberDataByToken(organizationMemberToken: string, playUri: string | null): Promise { - if (!ADMIN_API_URL) { - return Promise.reject(new Error("No admin backoffice set!")); - } + async fetchMemberDataByToken( + organizationMemberToken: string, + playUri: string | null, + locale?: string + ): Promise { //todo: this call can fail if the corresponding world is not activated or if the token is invalid. Handle that case. const res = await Axios.get(ADMIN_API_URL + "/api/login-url/" + organizationMemberToken, { params: { playUri }, - headers: { Authorization: `${ADMIN_API_TOKEN}` }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": locale ?? "en" }, }); const adminApiData = isAdminApiData.safeParse(res.data); @@ -125,11 +151,9 @@ class AdminApi implements AdminInterface { reportedUserUuid: string, reportedUserComment: string, reporterUserUuid: string, - reportWorldSlug: string + reportWorldSlug: string, + locale?: string ) { - if (!ADMIN_API_URL) { - return Promise.reject(new Error("No admin backoffice set!")); - } return Axios.post( `${ADMIN_API_URL}/api/report`, { @@ -139,15 +163,17 @@ class AdminApi implements AdminInterface { reportWorldSlug, }, { - headers: { Authorization: `${ADMIN_API_TOKEN}` }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": locale ?? "en" }, } ); } - async verifyBanUser(userUuid: string, ipAddress: string, roomUrl: string): Promise { - if (!ADMIN_API_URL) { - return Promise.reject(new Error("No admin backoffice set!")); - } + async verifyBanUser( + userUuid: string, + ipAddress: string, + roomUrl: string, + locale?: string + ): Promise { //todo: this call can fail if the corresponding world is not activated or if the token is invalid. Handle that case. return Axios.get( ADMIN_API_URL + @@ -158,28 +184,20 @@ class AdminApi implements AdminInterface { encodeURIComponent(userUuid) + "&roomUrl=" + encodeURIComponent(roomUrl), - { headers: { Authorization: `${ADMIN_API_TOKEN}` } } + { headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": locale ?? "en" } } ).then((data) => { return data.data; }); } - async getUrlRoomsFromSameWorld(roomUrl: string): Promise { - if (!ADMIN_API_URL) { - return Promise.reject(new Error("No admin backoffice set!")); - } - + async getUrlRoomsFromSameWorld(roomUrl: string, locale?: string): Promise { return Axios.get(ADMIN_API_URL + "/api/room/sameWorld" + "?roomUrl=" + encodeURIComponent(roomUrl), { - headers: { Authorization: `${ADMIN_API_TOKEN}` }, + headers: { Authorization: `${ADMIN_API_TOKEN}`, "Accept-Language": locale ?? "en" }, }).then((data) => { return data.data; }); } - /** - * - * @param accessToken - */ getProfileUrl(accessToken: string): string { if (!OPID_PROFILE_SCREEN_PROVIDER) { throw new Error("No admin backoffice set!"); @@ -187,7 +205,7 @@ class AdminApi implements AdminInterface { return `${OPID_PROFILE_SCREEN_PROVIDER}?accessToken=${accessToken}`; } - async logoutOauth(token: string) { + async logoutOauth(token: string): Promise { await Axios.get(ADMIN_API_URL + `/oauth/logout?token=${token}`); } } diff --git a/pusher/src/Services/AdminInterface.ts b/pusher/src/Services/AdminInterface.ts index 66121316..e70a653a 100644 --- a/pusher/src/Services/AdminInterface.ts +++ b/pusher/src/Services/AdminInterface.ts @@ -1,10 +1,82 @@ -import { FetchMemberDataByUuidResponse } from "./AdminApi"; +import { AdminBannedData, FetchMemberDataByUuidResponse } from "./AdminApi"; +import { MapDetailsData } from "../Messages/JsonMessages/MapDetailsData"; +import { RoomRedirect } from "../Messages/JsonMessages/RoomRedirect"; +import { AdminApiData } from "../Messages/JsonMessages/AdminApiData"; export interface AdminInterface { + /** + * @var playUri: is url of the room + * @var userIdentifier: can to be undefined or email or uuid + * @var ipAddress + * @var characterLayers + * @return MapDetailsData|RoomRedirect + */ fetchMemberDataByUuid( userIdentifier: string, playUri: string, ipAddress: string, - characterLayers: string[] + characterLayers: string[], + locale?: string ): Promise; + + /** + * @var playUri: is url of the room + * @var userId: can to be undefined or email or uuid + * @return MapDetailsData|RoomRedirect + */ + fetchMapDetails(playUri: string, authToken?: string, locale?: string): Promise; + + /** + * @param locale + * @param organizationMemberToken + * @param playUri + * @return AdminApiData + */ + fetchMemberDataByToken( + organizationMemberToken: string, + playUri: string | null, + locale?: string + ): Promise; + + /** + * @param locale + * @param reportedUserUuid + * @param reportedUserComment + * @param reporterUserUuid + * @param reportWorldSlug + */ + reportPlayer( + reportedUserUuid: string, + reportedUserComment: string, + reporterUserUuid: string, + reportWorldSlug: string, + locale?: string + ): Promise; + + /** + * @param locale + * @param userUuid + * @param ipAddress + * @param roomUrl + * @return AdminBannedData + */ + verifyBanUser(userUuid: string, ipAddress: string, roomUrl: string, locale?: string): Promise; + + /** + * @param locale + * @param roomUrl + * @return string[] + */ + getUrlRoomsFromSameWorld(roomUrl: string, locale?: string): Promise; + + /** + * @param accessToken + * @return string + */ + getProfileUrl(accessToken: string): string; + + /** + * @param token + */ + logoutOauth(token: string): Promise; } diff --git a/pusher/src/Services/LocalAdmin.ts b/pusher/src/Services/LocalAdmin.ts index 4e2c41a0..8470efb9 100644 --- a/pusher/src/Services/LocalAdmin.ts +++ b/pusher/src/Services/LocalAdmin.ts @@ -1,5 +1,10 @@ -import { FetchMemberDataByUuidResponse } from "./AdminApi"; +import { AdminBannedData, FetchMemberDataByUuidResponse } from "./AdminApi"; import { AdminInterface } from "./AdminInterface"; +import { MapDetailsData } from "../Messages/JsonMessages/MapDetailsData"; +import { RoomRedirect } from "../Messages/JsonMessages/RoomRedirect"; +import { GameRoomPolicyTypes } from "../Model/PusherRoom"; +import { DISABLE_ANONYMOUS } from "../Enum/EnvironmentVariable"; +import { AdminApiData } from "../Messages/JsonMessages/AdminApiData"; /** * A local class mocking a real admin if no admin is configured. @@ -7,12 +12,10 @@ import { AdminInterface } from "./AdminInterface"; class LocalAdmin implements AdminInterface { fetchMemberDataByUuid( userIdentifier: string, - // eslint-disable-next-line @typescript-eslint/no-unused-vars playUri: string, - // eslint-disable-next-line @typescript-eslint/no-unused-vars ipAddress: string, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - characterLayers: string[] + characterLayers: string[], + locale?: string ): Promise { return Promise.resolve({ email: userIdentifier, @@ -24,6 +27,70 @@ class LocalAdmin implements AdminInterface { userRoomToken: undefined, }); } + + fetchMapDetails(playUri: string, authToken?: string, locale?: string): Promise { + const roomUrl = new URL(playUri); + + const match = /\/_\/[^/]+\/(.+)/.exec(roomUrl.pathname); + if (!match) { + throw new Error("URL format is not good"); + } + + const mapUrl = roomUrl.protocol + "//" + match[1]; + + return Promise.resolve({ + mapUrl, + policy_type: GameRoomPolicyTypes.ANONYMOUS_POLICY, + tags: [], + authenticationMandatory: DISABLE_ANONYMOUS, + roomSlug: null, + contactPage: null, + group: null, + iframeAuthentication: null, + loadingLogo: null, + loginSceneLogo: null, + }); + } + + async fetchMemberDataByToken( + organizationMemberToken: string, + playUri: string | null, + locale?: string + ): Promise { + return Promise.reject(new Error("No admin backoffice set!")); + } + + reportPlayer( + reportedUserUuid: string, + reportedUserComment: string, + reporterUserUuid: string, + reportWorldSlug: string, + locale?: string + ) { + return Promise.reject(new Error("No admin backoffice set!")); + } + + async verifyBanUser( + userUuid: string, + ipAddress: string, + roomUrl: string, + locale?: string + ): Promise { + return Promise.reject(new Error("No admin backoffice set!")); + } + + async getUrlRoomsFromSameWorld(roomUrl: string, locale?: string): Promise { + return Promise.reject(new Error("No admin backoffice set!")); + } + + getProfileUrl(accessToken: string): string { + new Error("No admin backoffice set!"); + return ""; + } + + async logoutOauth(token: string): Promise { + return Promise.reject(new Error("No admin backoffice set!")); + } } export const localAdmin = new LocalAdmin(); diff --git a/pusher/src/Services/LocalWokaService.ts b/pusher/src/Services/LocalWokaService.ts index 2834f63c..87bf6054 100644 --- a/pusher/src/Services/LocalWokaService.ts +++ b/pusher/src/Services/LocalWokaService.ts @@ -5,7 +5,6 @@ class LocalWokaService implements WokaServiceInterface { /** * Returns the list of all available Wokas & Woka Parts for the current user. */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars async getWokaList(roomId: string, token: string): Promise { const wokaData: WokaList = await require("../../data/woka.json"); if (!wokaData) { diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index 60bb22be..fa11a820 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -39,10 +39,10 @@ import { PlayerDetailsUpdatedMessage, LockGroupPromptMessage, InvalidTextureMessage, + ErrorScreenMessage, } from "../Messages/generated/messages_pb"; import { ProtobufUtils } from "../Model/Websocket/ProtobufUtils"; -import { ADMIN_API_URL, JITSI_ISS, JITSI_URL, SECRET_JITSI_KEY, PUSHER_FORCE_ROOM_UPDATE } from "../Enum/EnvironmentVariable"; -import { adminApi } from "./AdminApi"; +import { JITSI_ISS, JITSI_URL, SECRET_JITSI_KEY } from "../Enum/EnvironmentVariable"; import { emitInBatch } from "./IoSocketHelpers"; import Jwt from "jsonwebtoken"; import { clientEventsEmitter } from "./ClientEventsEmitter"; @@ -52,7 +52,9 @@ import { GroupDescriptor, UserDescriptor, ZoneEventListener } from "../Model/Zon import Debug from "debug"; import { ExAdminSocketInterface } from "../Model/Websocket/ExAdminSocketInterface"; import { compressors } from "hyper-express"; -import { isMapDetailsData } from "../Messages/JsonMessages/MapDetailsData"; +import { adminService } from "./AdminService"; +import { ErrorApiData } from "../Messages/JsonMessages/ErrorApiData"; +import { BoolValue, Int32Value, StringValue } from "google-protobuf/google/protobuf/wrappers_pb"; const debug = Debug("socket"); @@ -382,7 +384,8 @@ export class SocketManager implements ZoneEventListener { async handleReportMessage(client: ExSocketInterface, reportPlayerMessage: ReportPlayerMessage) { try { - await adminApi.reportPlayer( + await adminService.reportPlayer( + "en", reportPlayerMessage.getReporteduseruuid(), reportPlayerMessage.getReportcomment(), client.userUuid, @@ -458,30 +461,12 @@ export class SocketManager implements ZoneEventListener { let room = this.rooms.get(roomUrl); if (room === undefined) { room = new PusherRoom(roomUrl, this); - if (ADMIN_API_URL) { - await this.updateRoomWithAdminData(room); - } await room.init(); this.rooms.set(roomUrl, room); - } else if (PUSHER_FORCE_ROOM_UPDATE && ADMIN_API_URL) { - await this.updateRoomWithAdminData(room); } return room; } - public async updateRoomWithAdminData(room: PusherRoom): Promise { - const data = await adminApi.fetchMapDetails(room.roomUrl); - const mapDetailsData = isMapDetailsData.safeParse(data); - - if (mapDetailsData.success) { - room.tags = mapDetailsData.data.tags; - room.policyType = Number(mapDetailsData.data.policy_type); - } else { - // TODO: if the updated room data is actually a redirect, we need to take everybody on the map - // and redirect everybody to the new location (so we need to close the connection for everybody) - } - } - public getWorlds(): Map { return this.rooms; } @@ -670,12 +655,39 @@ export class SocketManager implements ZoneEventListener { client.send(serverToClientMessage.serializeBinary().buffer, true); } + public emitErrorScreenMessage(client: compressors.WebSocket, errorApi: ErrorApiData) { + const errorMessage = new ErrorScreenMessage(); + errorMessage.setType(errorApi.type); + if (errorApi.type == "retry" || errorApi.type == "error") { + errorMessage.setCode(new StringValue().setValue(errorApi.code)); + errorMessage.setTitle(new StringValue().setValue(errorApi.title)); + errorMessage.setSubtitle(new StringValue().setValue(errorApi.subtitle)); + errorMessage.setDetails(new StringValue().setValue(errorApi.details)); + errorMessage.setImage(new StringValue().setValue(errorApi.image)); + } + if (errorApi.type == "retry") { + if (errorApi.buttonTitle) errorMessage.setButtontitle(new StringValue().setValue(errorApi.buttonTitle)); + if (errorApi.canRetryManual !== undefined) + errorMessage.setCanretrymanual(new BoolValue().setValue(errorApi.canRetryManual)); + if (errorApi.timeToRetry) + errorMessage.setTimetoretry(new Int32Value().setValue(Number(errorApi.timeToRetry))); + } + if (errorApi.type == "redirect" && errorApi.urlToRedirect) + errorMessage.setUrltoredirect(new StringValue().setValue(errorApi.urlToRedirect)); + + const serverToClientMessage = new ServerToClientMessage(); + serverToClientMessage.setErrorscreenmessage(errorMessage); + + //if (!client.disconnecting) { + client.send(serverToClientMessage.serializeBinary().buffer, true); + //} + } + private refreshRoomData(roomId: string, versionNumber: number): void { const room = this.rooms.get(roomId); //this function is run for every users connected to the room, so we need to make sure the room wasn't already refreshed. if (!room || !room.needsUpdate(versionNumber)) return; - - this.updateRoomWithAdminData(room); + //TODO check right of user in admin } handleEmotePromptMessage(client: ExSocketInterface, emoteEventmessage: EmotePromptMessage) { @@ -697,7 +709,7 @@ export class SocketManager implements ZoneEventListener { let tabUrlRooms: string[]; if (playGlobalMessageEvent.getBroadcasttoworld()) { - tabUrlRooms = await adminApi.getUrlRoomsFromSameWorld(clientRoomUrl); + tabUrlRooms = await adminService.getUrlRoomsFromSameWorld("en", clientRoomUrl); } else { tabUrlRooms = [clientRoomUrl]; } diff --git a/pusher/yarn.lock b/pusher/yarn.lock index f698837e..ba0178c4 100644 --- a/pusher/yarn.lock +++ b/pusher/yarn.lock @@ -2,6 +2,14 @@ # yarn lockfile v1 +"@anatine/zod-openapi@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@anatine/zod-openapi/-/zod-openapi-1.3.0.tgz#b5b38c3d821b79674226aa7b327c88c371860d0d" + integrity sha512-l54DypUdDsIq1Uwjv4ib9IBkTXMKZQLUj7qvdFL51EExC5LdSSqOlTOyaVVZZGYgWPKM7ZjGklhdoknLz4EC+w== + dependencies: + ts-deepmerge "^1.1.0" + validator "^13.7.0" + "@apidevtools/json-schema-ref-parser@^9.0.6": version "9.0.9" resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b" @@ -1926,6 +1934,13 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" +openapi3-ts@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/openapi3-ts/-/openapi3-ts-2.0.2.tgz#a200dd838bf24c9086c8eedcfeb380b7eb31e82a" + integrity sha512-TxhYBMoqx9frXyOgnRHufjQfPXomTIHYKhSKJ6jHfj13kS8OEIhvmE8CTuQyKtjjWttAjX5DPxM1vmalEpo8Qw== + dependencies: + yaml "^1.10.2" + openid-client@^4.7.4: version "4.9.1" resolved "https://registry.yarnpkg.com/openid-client/-/openid-client-4.9.1.tgz#4f00a9d1566c0fa08f0dd5986cf0e6b1e5d14186" @@ -2563,6 +2578,11 @@ tree-kill@^1.2.2: resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== +ts-deepmerge@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ts-deepmerge/-/ts-deepmerge-1.1.0.tgz#4236ae102199affe2e77690dcf198a420160eef2" + integrity sha512-VvwaV/6RyYMwT9d8dClmfHIsG2PCdm6WY430QKOIbPRR50Y/1Q2ilp4i2XEZeHFcNqfaYnAQzpyUC6XA0AqqBg== + ts-node-dev@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/ts-node-dev/-/ts-node-dev-1.1.8.tgz#95520d8ab9d45fffa854d6668e2f8f9286241066" @@ -2689,7 +2709,7 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== -validator@^13.6.0: +validator@^13.6.0, validator@^13.7.0: version "13.7.0" resolved "https://registry.yarnpkg.com/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857" integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw== @@ -2796,7 +2816,7 @@ yaml@2.0.0-1: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.0.0-1.tgz#8c3029b3ee2028306d5bcf396980623115ff8d18" integrity sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ== -yaml@^1.10.0: +yaml@^1.10.0, yaml@^1.10.2: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== diff --git a/tests/tests/utils/roles.ts b/tests/tests/utils/roles.ts index b4d3b8af..7e8ebe20 100644 --- a/tests/tests/utils/roles.ts +++ b/tests/tests/utils/roles.ts @@ -11,8 +11,9 @@ export async function login( await page.fill('input[name="loginSceneName"]', userName); await page.click('button.loginSceneFormSubmit'); + await page.waitForTimeout(1000); for (let i = 0; i < characterNumber; i++) { - await page.click('button.selectCharacterButtonRight'); + await page.keyboard.press('ArrowRight'); } await page.click('button.selectCharacterSceneFormSubmit'); diff --git a/tests/tests/variables.spec.ts b/tests/tests/variables.spec.ts index a652a247..0534eb64 100644 --- a/tests/tests/variables.spec.ts +++ b/tests/tests/variables.spec.ts @@ -83,7 +83,9 @@ test.describe('Variables', () => { ); // Redis will reconnect automatically and will store the variable on reconnect! // So we should see the new value. - await expect(textField).toHaveValue('value set while Redis stopped'); + await expect(textField).toHaveValue('value set while Redis stopped', { + timeout: 60000, + }); // Now, let's try to kill / reboot the back await rebootBack();