Merge branch 'develop' of github.com:thecodingmachine/workadventure into develop

This commit is contained in:
_Bastler 2022-03-29 15:38:41 +02:00
commit 7f4677e640
19 changed files with 73 additions and 55 deletions

View File

@ -295,9 +295,9 @@ ansi-escapes@^4.2.1:
type-fest "^0.21.3" type-fest "^0.21.3"
ansi-regex@^4.1.0: ansi-regex@^4.1.0:
version "4.1.0" version "4.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed"
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==
ansi-regex@^5.0.1: ansi-regex@^5.0.1:
version "5.0.1" version "5.0.1"
@ -2409,9 +2409,9 @@ pirates@^4.0.1:
integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==
plist@^3.0.1, plist@^3.0.4: plist@^3.0.1, plist@^3.0.4:
version "3.0.4" version "3.0.5"
resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.4.tgz#a62df837e3aed2bb3b735899d510c4f186019cbe" resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.5.tgz#2cbeb52d10e3cdccccf0c11a63a85d830970a987"
integrity sha512-ksrr8y9+nXOxQB2osVNqrgvX/XQPOXaU4BQMKjYq8PvaY1U18mo+fKgBSwzK+luSyinOuPae956lSVcBwxlAMg== integrity sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA==
dependencies: dependencies:
base64-js "^1.5.1" base64-js "^1.5.1"
xmlbuilder "^9.0.7" xmlbuilder "^9.0.7"

View File

@ -587,9 +587,9 @@ minimatch@^3.0.4:
brace-expansion "^1.1.7" brace-expansion "^1.1.7"
minimist@^1.2.0, minimist@^1.2.5: minimist@^1.2.0, minimist@^1.2.5:
version "1.2.5" version "1.2.6"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
mkdirp@^0.5.1: mkdirp@^0.5.1:
version "0.5.5" version "0.5.5"

View File

@ -1,5 +1,5 @@
import { Subject } from "rxjs"; import { Subject } from "rxjs";
import type { BanUserMessage, SendUserMessage } from "../Messages/ts-proto-generated/messages"; import type { BanUserMessage, SendUserMessage } from "../Messages/ts-proto-generated/protos/messages";
export enum AdminMessageEventTypes { export enum AdminMessageEventTypes {
admin = "message", admin = "message",

View File

@ -89,8 +89,7 @@ class ConnectionManager {
* @return returns a promise to the Room we are going to load OR a pointer to the URL we must redirect to if authentication is needed. * @return returns a promise to the Room we are going to load OR a pointer to the URL we must redirect to if authentication is needed.
*/ */
public async initGameConnexion(): Promise<Room | URL> { public async initGameConnexion(): Promise<Room | URL> {
const connexionType = urlManager.getGameConnexionType(); this.connexionType = urlManager.getGameConnexionType();
this.connexionType = connexionType;
this._currentRoom = null; this._currentRoom = null;
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams(window.location.search);
@ -103,14 +102,15 @@ class ConnectionManager {
urlParams.delete("token"); urlParams.delete("token");
} }
if (connexionType === GameConnexionTypes.login) { if (this.connexionType === GameConnexionTypes.login) {
this._currentRoom = await Room.createRoom(new URL(localUserStore.getLastRoomUrl())); this._currentRoom = await Room.createRoom(new URL(localUserStore.getLastRoomUrl()));
const redirect = this.loadOpenIDScreen(); const redirect = this.loadOpenIDScreen();
if (redirect !== null) { if (redirect !== null) {
return redirect; return redirect;
} }
urlManager.pushRoomIdToUrl(this._currentRoom); urlManager.pushRoomIdToUrl(this._currentRoom);
} else if (connexionType === GameConnexionTypes.jwt) { } else if (this.connexionType === GameConnexionTypes.jwt) {
/** @deprecated */
if (!token) { if (!token) {
const code = urlParams.get("code"); const code = urlParams.get("code");
const state = urlParams.get("state"); const state = urlParams.get("state");
@ -136,8 +136,9 @@ class ConnectionManager {
return redirect; return redirect;
} }
urlManager.pushRoomIdToUrl(this._currentRoom); urlManager.pushRoomIdToUrl(this._currentRoom);
} else if (connexionType === GameConnexionTypes.register) { }
//@deprecated //@deprecated
else if (this.connexionType === GameConnexionTypes.register) {
const organizationMemberToken = urlManager.getOrganizationToken(); const organizationMemberToken = urlManager.getOrganizationToken();
const data = await Axios.post(`${PUSHER_URL}/register`, { organizationMemberToken }).then( const data = await Axios.post(`${PUSHER_URL}/register`, { organizationMemberToken }).then(
(res) => res.data (res) => res.data
@ -166,11 +167,11 @@ class ConnectionManager {
) )
); );
urlManager.pushRoomIdToUrl(this._currentRoom); urlManager.pushRoomIdToUrl(this._currentRoom);
} else if (connexionType === GameConnexionTypes.room || connexionType === GameConnexionTypes.empty) { } else if (this.connexionType === GameConnexionTypes.room || this.connexionType === GameConnexionTypes.empty) {
this.authToken = localUserStore.getAuthToken(); this.authToken = localUserStore.getAuthToken();
let roomPath: string; let roomPath: string;
if (connexionType === GameConnexionTypes.empty) { if (this.connexionType === GameConnexionTypes.empty) {
roomPath = localUserStore.getLastRoomUrl(); roomPath = localUserStore.getLastRoomUrl();
//get last room path from cache api //get last room path from cache api
try { try {

View File

@ -43,8 +43,8 @@ export interface PositionInterface {
export interface GroupCreatedUpdatedMessageInterface { export interface GroupCreatedUpdatedMessageInterface {
position: PositionInterface; position: PositionInterface;
groupId: number; groupId: number;
groupSize: number; groupSize?: number;
locked: boolean; locked?: boolean;
} }
export interface GroupUsersUpdateMessageInterface { export interface GroupUsersUpdateMessageInterface {

View File

@ -41,7 +41,7 @@ import {
SetPlayerDetailsMessage as SetPlayerDetailsMessageTsProto, SetPlayerDetailsMessage as SetPlayerDetailsMessageTsProto,
PingMessage as PingMessageTsProto, PingMessage as PingMessageTsProto,
CharacterLayerMessage, CharacterLayerMessage,
} from "../Messages/ts-proto-generated/messages"; } from "../Messages/ts-proto-generated/protos/messages";
import { Subject } from "rxjs"; import { Subject } from "rxjs";
import { selectCharacterSceneVisibleStore } from "../Stores/SelectCharacterStore"; import { selectCharacterSceneVisibleStore } from "../Stores/SelectCharacterStore";
import { gameManager } from "../Phaser/Game/GameManager"; import { gameManager } from "../Phaser/Game/GameManager";

View File

@ -1,4 +1,4 @@
import { PositionMessage, PositionMessage_Direction } from "../Messages/ts-proto-generated/messages"; import { PositionMessage, PositionMessage_Direction } from "../Messages/ts-proto-generated/protos/messages";
import type { PointInterface } from "../Connexion/ConnexionModels"; import type { PointInterface } from "../Connexion/ConnexionModels";

View File

@ -76,7 +76,7 @@ import { userIsAdminStore } from "../../Stores/GameStore";
import { contactPageStore } from "../../Stores/MenuStore"; import { contactPageStore } from "../../Stores/MenuStore";
import type { WasCameraUpdatedEvent } from "../../Api/Events/WasCameraUpdatedEvent"; import type { WasCameraUpdatedEvent } from "../../Api/Events/WasCameraUpdatedEvent";
import { audioManagerFileStore } from "../../Stores/AudioManagerStore"; import { audioManagerFileStore } from "../../Stores/AudioManagerStore";
import { currentPlayerGroupIdStore, currentPlayerGroupLockStateStore } from "../../Stores/CurrentPlayerGroupStore"; import { currentPlayerGroupLockStateStore } from "../../Stores/CurrentPlayerGroupStore";
import EVENT_TYPE = Phaser.Scenes.Events; import EVENT_TYPE = Phaser.Scenes.Events;
import Texture = Phaser.Textures.Texture; import Texture = Phaser.Textures.Texture;
@ -727,10 +727,6 @@ export class GameScene extends DirtyScene {
} }
}); });
this.currentPlayerGroupIdStoreUnsubscribe = currentPlayerGroupIdStore.subscribe((groupId) => {
this.currentPlayerGroupId = groupId;
});
Promise.all([ Promise.all([
this.connectionAnswerPromiseDeferred.promise as Promise<unknown>, this.connectionAnswerPromiseDeferred.promise as Promise<unknown>,
...scriptPromises, ...scriptPromises,
@ -863,8 +859,7 @@ export class GameScene extends DirtyScene {
}); });
this.connection.groupUsersUpdateMessageStream.subscribe((message) => { this.connection.groupUsersUpdateMessageStream.subscribe((message) => {
// TODO: how else can we deduce our current group? this.currentPlayerGroupId = message.groupId;
currentPlayerGroupIdStore.set(message.groupId);
}); });
/** /**
@ -1905,7 +1900,6 @@ export class GameScene extends DirtyScene {
break; break;
case "DeleteGroupEvent": { case "DeleteGroupEvent": {
this.doDeleteGroup(event.groupId); this.doDeleteGroup(event.groupId);
currentPlayerGroupIdStore.set(undefined);
currentPlayerGroupLockStateStore.set(undefined); currentPlayerGroupLockStateStore.set(undefined);
break; break;
} }

View File

@ -280,6 +280,9 @@ export class UserInputManager {
); );
this.scene.input.keyboard.on("keyup-SPACE", (event: Event) => { this.scene.input.keyboard.on("keyup-SPACE", (event: Event) => {
if (this.isInputDisabled) {
return;
}
this.userInputHandler.handleSpaceKeyUpEvent(event); this.userInputHandler.handleSpaceKeyUpEvent(event);
}); });
} }

View File

@ -1,4 +1,3 @@
import { writable } from "svelte/store"; import { writable } from "svelte/store";
export const currentPlayerGroupIdStore = writable<number | undefined>(undefined);
export const currentPlayerGroupLockStateStore = writable<boolean | undefined>(undefined); export const currentPlayerGroupLockStateStore = writable<boolean | undefined>(undefined);

View File

@ -3,10 +3,10 @@ import { localUserStore } from "../Connexion/LocalUserStore";
export enum GameConnexionTypes { export enum GameConnexionTypes {
room = 1, room = 1,
register, register /*@deprecated*/,
empty, empty,
unknown, unknown,
jwt, jwt /*@deprecated*/,
login, login,
} }
@ -16,11 +16,15 @@ class UrlManager {
const url = window.location.pathname.toString(); const url = window.location.pathname.toString();
if (url === "/login") { if (url === "/login") {
return GameConnexionTypes.login; return GameConnexionTypes.login;
} else if (url === "/jwt") { }
//@deprecated jwt url will be replace by "?token=<private access token>"
else if (url === "/jwt") {
return GameConnexionTypes.jwt; return GameConnexionTypes.jwt;
} else if (url.includes("_/") || url.includes("*/") || url.includes("@/")) { } else if (url.includes("_/") || url.includes("*/") || url.includes("@/")) {
return GameConnexionTypes.room; return GameConnexionTypes.room;
} else if (url.includes("register/")) { }
//@deprecated register url will be replace by "?token=<private access token>"
else if (url.includes("register/")) {
return GameConnexionTypes.register; return GameConnexionTypes.register;
} else if (url === "/") { } else if (url === "/") {
return GameConnexionTypes.empty; return GameConnexionTypes.empty;
@ -29,6 +33,9 @@ class UrlManager {
} }
} }
/**
* @deprecated
*/
public getOrganizationToken(): string | null { public getOrganizationToken(): string | null {
const match = /\/register\/(.+)/.exec(window.location.pathname.toString()); const match = /\/register\/(.+)/.exec(window.location.pathname.toString());
return match ? match[1] : null; return match ? match[1] : null;

View File

@ -124,9 +124,9 @@ ansi-escapes@^4.2.1:
type-fest "^0.21.3" type-fest "^0.21.3"
ansi-regex@^4.1.0: ansi-regex@^4.1.0:
version "4.1.0" version "4.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed"
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==
ansi-regex@^5.0.0: ansi-regex@^5.0.0:
version "5.0.1" version "5.0.1"

View File

@ -6,7 +6,7 @@
"proto": "grpc_tools_node_protoc --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts --grpc_out=generated --js_out=\"import_style=commonjs,binary:generated\" --ts_out=generated -I ./protos protos/*.proto", "proto": "grpc_tools_node_protoc --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts --grpc_out=generated --js_out=\"import_style=commonjs,binary:generated\" --ts_out=generated -I ./protos protos/*.proto",
"ts-proto": "grpc_tools_node_protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=ts-proto-generated --ts_proto_opt=oneof=unions --ts_proto_opt=esModuleInterop=true protos/*.proto", "ts-proto": "grpc_tools_node_protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=ts-proto-generated --ts_proto_opt=oneof=unions --ts_proto_opt=esModuleInterop=true protos/*.proto",
"copy-to-back": "rm -rf ../back/src/Messages/generated && cp -rf generated/ ../back/src/Messages/generated", "copy-to-back": "rm -rf ../back/src/Messages/generated && cp -rf generated/ ../back/src/Messages/generated",
"copy-to-front-ts-proto": "sed 's/import { Observable } from \"rxjs\";/import type { Observable } from \"rxjs\";/g' ts-proto-generated/protos/messages.ts > ../front/src/Messages/ts-proto-generated/messages.ts", "copy-to-front-ts-proto": "cp -rf ts-proto-generated/* ../front/src/Messages/ts-proto-generated/ && sed -i 's/import { Observable } from \"rxjs\";/import type { Observable } from \"rxjs\";/g' ../front/src/Messages/ts-proto-generated/protos/messages.ts",
"copy-to-pusher": "rm -rf ../pusher/src/Messages/generated && cp -rf generated/ ../pusher/src/Messages/generated", "copy-to-pusher": "rm -rf ../pusher/src/Messages/generated && cp -rf generated/ ../pusher/src/Messages/generated",
"json-copy-to-pusher": "rm -rf ../pusher/src/Messages/JsonMessages/* && cp -rf JsonMessages/* ../pusher/src/Messages/JsonMessages/", "json-copy-to-pusher": "rm -rf ../pusher/src/Messages/JsonMessages/* && cp -rf JsonMessages/* ../pusher/src/Messages/JsonMessages/",
"json-copy-to-back": "rm -rf ../back/src/Messages/JsonMessages/* && cp -rf JsonMessages/* ../back/src/Messages/JsonMessages/", "json-copy-to-back": "rm -rf ../back/src/Messages/JsonMessages/* && cp -rf JsonMessages/* ../back/src/Messages/JsonMessages/",

View File

@ -1,5 +1,7 @@
syntax = "proto3"; syntax = "proto3";
import "google/protobuf/wrappers.proto";
/*********** PARTIAL MESSAGES **************/ /*********** PARTIAL MESSAGES **************/
message PositionMessage { message PositionMessage {
@ -189,8 +191,8 @@ message BatchMessage {
message GroupUpdateMessage { message GroupUpdateMessage {
int32 groupId = 1; int32 groupId = 1;
PointMessage position = 2; PointMessage position = 2;
int32 groupSize = 3; google.protobuf.UInt32Value groupSize = 3;
bool locked = 4; google.protobuf.BoolValue locked = 4;
} }
message GroupDeleteMessage { message GroupDeleteMessage {

View File

@ -320,10 +320,11 @@ export class AuthenticateController extends BaseHttpController {
//todo: what to do if the organizationMemberToken is already used? //todo: what to do if the organizationMemberToken is already used?
const organizationMemberToken: string | null = param.organizationMemberToken; const organizationMemberToken: string | null = param.organizationMemberToken;
const playUri: string | null = param.playUri;
try { try {
if (typeof organizationMemberToken != "string") throw new Error("No organization token"); if (typeof organizationMemberToken != "string") throw new Error("No organization token");
const data = await adminApi.fetchMemberDataByToken(organizationMemberToken); const data = await adminApi.fetchMemberDataByToken(organizationMemberToken, playUri);
const userUuid = data.userUuid; const userUuid = data.userUuid;
const email = data.email; const email = data.email;
const roomUrl = data.roomUrl; const roomUrl = data.roomUrl;

View File

@ -13,14 +13,14 @@ export class OpenIdProfileController extends BaseHttpController {
} }
try { try {
const resCheckTokenAuth = await openIDClient.checkTokenAuth(accessToken as string); const resCheckTokenAuth = await openIDClient.checkTokenAuth(accessToken as string);
if (!resCheckTokenAuth.email) { if (!resCheckTokenAuth.sub) {
throw new Error("Email was not found"); throw new Error("Email was not found");
} }
res.send( res.send(
this.buildHtml( this.buildHtml(
OPID_CLIENT_ISSUER, OPID_CLIENT_ISSUER,
resCheckTokenAuth.email as string, resCheckTokenAuth.sub
resCheckTokenAuth.picture as string | undefined /*resCheckTokenAuth.picture as string | undefined*/
) )
); );
return; return;

View File

@ -22,6 +22,7 @@ import {
import { ClientReadableStream } from "grpc"; import { ClientReadableStream } from "grpc";
import { PositionDispatcher } from "_Model/PositionDispatcher"; import { PositionDispatcher } from "_Model/PositionDispatcher";
import Debug from "debug"; import Debug from "debug";
import { BoolValue, UInt32Value } from "google-protobuf/google/protobuf/wrappers_pb";
const debug = Debug("zone"); const debug = Debug("zone");
@ -125,9 +126,9 @@ export class UserDescriptor {
export class GroupDescriptor { export class GroupDescriptor {
private constructor( private constructor(
public readonly groupId: number, public readonly groupId: number,
private groupSize: number, private groupSize: number | undefined,
private position: PointMessage, private position: PointMessage,
private locked: boolean private locked: boolean | undefined
) {} ) {}
public static createFromGroupUpdateZoneMessage(message: GroupUpdateZoneMessage): GroupDescriptor { public static createFromGroupUpdateZoneMessage(message: GroupUpdateZoneMessage): GroupDescriptor {
@ -150,9 +151,13 @@ export class GroupDescriptor {
throw new Error("GroupDescriptor.groupId is not an integer: " + this.groupId); throw new Error("GroupDescriptor.groupId is not an integer: " + this.groupId);
} }
groupUpdateMessage.setGroupid(this.groupId); groupUpdateMessage.setGroupid(this.groupId);
groupUpdateMessage.setGroupsize(this.groupSize); if (this.groupSize !== undefined) {
groupUpdateMessage.setGroupsize(new UInt32Value().setValue(this.groupSize));
}
groupUpdateMessage.setPosition(this.position); groupUpdateMessage.setPosition(this.position);
groupUpdateMessage.setLocked(this.locked); if (this.locked !== undefined) {
groupUpdateMessage.setLocked(new BoolValue().setValue(this.locked));
}
return groupUpdateMessage; return groupUpdateMessage;
} }
} }

View File

@ -61,7 +61,7 @@ class AdminApi {
async fetchMemberDataByUuid( async fetchMemberDataByUuid(
userIdentifier: string | null, userIdentifier: string | null,
roomId: string, playUri: string,
ipAddress: string, ipAddress: string,
characterLayers: string[] characterLayers: string[]
): Promise<FetchMemberDataByUuidResponse> { ): Promise<FetchMemberDataByUuidResponse> {
@ -69,7 +69,12 @@ class AdminApi {
return Promise.reject(new Error("No admin backoffice set!")); return Promise.reject(new Error("No admin backoffice set!"));
} }
const res = await Axios.get<unknown, AxiosResponse<unknown>>(ADMIN_API_URL + "/api/room/access", { const res = await Axios.get<unknown, AxiosResponse<unknown>>(ADMIN_API_URL + "/api/room/access", {
params: { userIdentifier, roomId, ipAddress, characterLayers }, params: {
userIdentifier,
playUri,
ipAddress,
characterLayers,
},
headers: { Authorization: `${ADMIN_API_TOKEN}` }, headers: { Authorization: `${ADMIN_API_TOKEN}` },
paramsSerializer: (p) => { paramsSerializer: (p) => {
return qs.stringify(p, { arrayFormat: "brackets" }); return qs.stringify(p, { arrayFormat: "brackets" });
@ -84,12 +89,13 @@ class AdminApi {
return res.data; return res.data;
} }
async fetchMemberDataByToken(organizationMemberToken: string): Promise<AdminApiData> { async fetchMemberDataByToken(organizationMemberToken: string, playUri: string | null): Promise<AdminApiData> {
if (!ADMIN_API_URL) { if (!ADMIN_API_URL) {
return Promise.reject(new Error("No admin backoffice set!")); return Promise.reject(new Error("No admin backoffice set!"));
} }
//todo: this call can fail if the corresponding world is not activated or if the token is invalid. Handle that case. //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, { const res = await Axios.get(ADMIN_API_URL + "/api/login-url/" + organizationMemberToken, {
params: { playUri },
headers: { Authorization: `${ADMIN_API_TOKEN}` }, headers: { Authorization: `${ADMIN_API_TOKEN}` },
}); });
if (!isAdminApiData(res.data)) { if (!isAdminApiData(res.data)) {

View File

@ -174,9 +174,9 @@ ansi-escapes@^4.2.1:
type-fest "^0.11.0" type-fest "^0.11.0"
ansi-regex@^4.1.0: ansi-regex@^4.1.0:
version "4.1.0" version "4.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed"
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==
ansi-regex@^5.0.0: ansi-regex@^5.0.0:
version "5.0.0" version "5.0.0"