Implement logger on pusher

This commit is contained in:
Alexis Faizeau 2021-11-08 19:05:25 +01:00
parent 6a195be814
commit dd89f12c2e
15 changed files with 263 additions and 72 deletions

View File

@ -53,7 +53,8 @@
"prom-client": "^12.0.0",
"query-string": "^6.13.3",
"uWebSockets.js": "uNetworking/uWebSockets.js#v18.5.0",
"uuidv4": "^6.0.7"
"uuidv4": "^6.0.7",
"winston": "^3.3.3"
},
"devDependencies": {
"@types/busboy": "^0.2.3",

View File

@ -1,4 +1,6 @@
// lib/server.ts
import App from "./src/App";
import { PUSHER_HTTP_PORT } from "./src/Enum/EnvironmentVariable";
App.listen(PUSHER_HTTP_PORT, () => console.log(`WorkAdventure starting on port ${PUSHER_HTTP_PORT}!`))
import log from "./src/Services/Logger";
App.listen(PUSHER_HTTP_PORT, () => log.info(`WorkAdventure starting on port ${PUSHER_HTTP_PORT}!`));

View File

@ -7,6 +7,7 @@ import {
WorldFullWarningToRoomMessage,
RefreshRoomPromptMessage,
} from "../Messages/generated/messages_pb";
import log from "../Services/Logger";
export class AdminController extends BaseController {
constructor(private App: TemplatedApp) {
@ -25,14 +26,14 @@ export class AdminController extends BaseController {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
this.App.post("/room/refresh", async (res: HttpResponse, req: HttpRequest) => {
res.onAborted(() => {
console.warn("/message request was aborted");
log.warn("/message request was aborted");
});
const token = req.getHeader("admin-token");
const body = await res.json();
if (token !== ADMIN_API_TOKEN) {
console.error("Admin access refused for token: " + token);
log.error("Admin access refused for token: " + token);
res.writeStatus("401 Unauthorized").end("Incorrect token");
return;
}
@ -72,14 +73,14 @@ export class AdminController extends BaseController {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
this.App.post("/message", async (res: HttpResponse, req: HttpRequest) => {
res.onAborted(() => {
console.warn("/message request was aborted");
log.warn("/message request was aborted");
});
const token = req.getHeader("admin-token");
const body = await res.json();
if (token !== ADMIN_API_TOKEN) {
console.error("Admin access refused for token: " + token);
log.error("Admin access refused for token: " + token);
res.writeStatus("401 Unauthorized").end("Incorrect token");
return;
}

View File

@ -5,6 +5,7 @@ import { adminApi } from "../Services/AdminApi";
import { AuthTokenData, jwtTokenManager } from "../Services/JWTTokenManager";
import { parse } from "query-string";
import { openIDClient } from "../Services/OpenIDClient";
import log from "../Services/Logger";
export interface TokenInterface {
userUuid: string;
@ -24,7 +25,7 @@ export class AuthenticateController extends BaseController {
//eslint-disable-next-line @typescript-eslint/no-misused-promises
this.App.get("/login-screen", async (res: HttpResponse, req: HttpRequest) => {
res.onAborted(() => {
console.warn("/message request was aborted");
log.warn("/message request was aborted");
});
try {
@ -43,7 +44,7 @@ export class AuthenticateController extends BaseController {
res.writeHeader("Location", loginUri);
return res.end();
} catch (e) {
console.error("openIDLogin => e", e);
log.error("openIDLogin => e", e);
return this.errorToResponse(e, res);
}
});
@ -53,7 +54,7 @@ export class AuthenticateController extends BaseController {
//eslint-disable-next-line @typescript-eslint/no-misused-promises
this.App.get("/login-callback", async (res: HttpResponse, req: HttpRequest) => {
res.onAborted(() => {
console.warn("/message request was aborted");
log.warn("/message request was aborted");
});
const { code, nonce, token } = parse(req.getQuery());
try {
@ -69,7 +70,7 @@ export class AuthenticateController extends BaseController {
this.addCorsHeaders(res);
return res.end(JSON.stringify({ authToken: token }));
} catch (err) {
console.info("User was not connected", err);
log.info("User was not connected", err);
}
}
@ -84,7 +85,7 @@ export class AuthenticateController extends BaseController {
this.addCorsHeaders(res);
return res.end(JSON.stringify({ authToken }));
} catch (e) {
console.error("openIDCallback => ERROR", e);
log.error("openIDCallback => ERROR", e);
return this.errorToResponse(e, res);
}
});
@ -92,7 +93,7 @@ export class AuthenticateController extends BaseController {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
this.App.get("/logout-callback", async (res: HttpResponse, req: HttpRequest) => {
res.onAborted(() => {
console.warn("/message request was aborted");
log.warn("/message request was aborted");
});
const { token } = parse(req.getQuery());
@ -104,7 +105,7 @@ export class AuthenticateController extends BaseController {
}
await openIDClient.logoutUser(authTokenData.hydraAccessToken);
} catch (error) {
console.error("openIDCallback => logout-callback", error);
log.error("openIDCallback => logout-callback", error);
} finally {
res.writeStatus("200");
this.addCorsHeaders(res);
@ -125,7 +126,7 @@ export class AuthenticateController extends BaseController {
this.App.post("/register", (res: HttpResponse, req: HttpRequest) => {
(async () => {
res.onAborted(() => {
console.warn("Login request was aborted");
log.warn("Login request was aborted");
});
const param = await res.json();
@ -156,7 +157,7 @@ export class AuthenticateController extends BaseController {
})
);
} catch (e) {
console.error("register => ERROR", e);
log.error("register => ERROR", e);
this.errorToResponse(e, res);
}
})();
@ -172,7 +173,7 @@ export class AuthenticateController extends BaseController {
this.App.post("/anonymLogin", (res: HttpResponse, req: HttpRequest) => {
res.onAborted(() => {
console.warn("Login request was aborted");
log.warn("Login request was aborted");
});
const userUuid = v4();
@ -194,7 +195,7 @@ export class AuthenticateController extends BaseController {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
this.App.get("/profile-callback", async (res: HttpResponse, req: HttpRequest) => {
res.onAborted(() => {
console.warn("/message request was aborted");
log.warn("/message request was aborted");
});
const { userIdentify, token } = parse(req.getQuery());
try {
@ -218,7 +219,7 @@ export class AuthenticateController extends BaseController {
}
}
} catch (error) {
console.error("profileCallback => ERROR", error);
log.error("profileCallback => ERROR", error);
this.errorToResponse(error, res);
}
});

View File

@ -1,4 +1,5 @@
import { HttpResponse } from "uWebSockets.js";
import log from "../Services/Logger";
export class BaseController {
protected addCorsHeaders(res: HttpResponse): void {
@ -19,12 +20,12 @@ export class BaseController {
} else {
url = "";
}
console.error("ERROR: " + e.message + url);
log.error("ERROR: " + e.message + url);
} else if (typeof e === "string") {
console.error(e);
log.error(e);
}
if (e.stack) {
console.error(e.stack);
log.error(e.stack);
}
if (e.response) {
res.writeStatus(e.response.status + " " + e.response.statusText);

View File

@ -31,6 +31,7 @@ import { Zone } from "_Model/Zone";
import { ExAdminSocketInterface } from "_Model/Websocket/ExAdminSocketInterface";
import { v4 } from "uuid";
import { CharacterTexture } from "../Services/AdminApi/CharacterTexture";
import log from "../Services/Logger";
export class IoSocketController {
private nextUserId: number = 1;
@ -49,13 +50,13 @@ export class IoSocketController {
const websocketExtensions = req.getHeader("sec-websocket-extensions");
const token = query.token;
if (token !== ADMIN_API_TOKEN) {
console.log("Admin access refused for token: " + token);
log.info("Admin access refused for token: " + token);
res.writeStatus("401 Unauthorized").end("Incorrect token");
return;
}
const roomId = query.roomId;
if (typeof roomId !== "string") {
console.error("Received");
log.error("Received");
res.writeStatus("400 Bad Request").end("Missing room id");
return;
}
@ -63,7 +64,7 @@ export class IoSocketController {
res.upgrade({ roomId }, websocketKey, websocketProtocol, websocketExtensions, context);
},
open: (ws) => {
console.log("Admin socket connect for room: " + ws.roomId);
log.info("Admin socket connect for room: " + ws.roomId);
ws.disconnecting = false;
socketManager.handleAdminRoom(ws as ExAdminSocketInterface, ws.roomId as string);
@ -96,7 +97,7 @@ export class IoSocketController {
}
}
} catch (err) {
console.error(err);
log.error(err);
}
},
close: (ws, code, message) => {
@ -105,8 +106,8 @@ export class IoSocketController {
Client.disconnecting = true;
socketManager.leaveAdminRoom(Client);
} catch (e) {
console.error('An error occurred on admin "disconnect"');
console.error(e);
log.error('An error occurred on admin "disconnect"');
log.error(e);
}
},
});
@ -198,7 +199,7 @@ export class IoSocketController {
if (err?.response?.status == 404) {
// If we get an HTTP 404, the token is invalid. Let's perform an anonymous login!
console.warn(
log.warn(
'Cannot find user with email "' +
(userIdentifier || "anonymous") +
'". Performing an anonymous login instead.'
@ -238,13 +239,13 @@ export class IoSocketController {
throw new Error("Use the login URL to connect");
}
} catch (e) {
console.log(
log.info(
"access not granted for user " +
(userIdentifier || "anonymous") +
" and room " +
roomId
);
console.error(e);
log.error(e);
throw new Error("User cannot access this world");
}
}
@ -254,7 +255,7 @@ export class IoSocketController {
SocketManager.mergeCharacterLayersAndCustomTextures(characterLayers, memberTextures);
if (upgradeAborted.aborted) {
console.log("Ouch! Client disconnected before we could upgrade it!");
log.info("Ouch! Client disconnected before we could upgrade it!");
/* You must not upgrade now */
return;
}
@ -395,7 +396,7 @@ export class IoSocketController {
//let ok = ws.send(message, isBinary);
},
drain: (ws) => {
console.log("WebSocket backpressure: " + ws.getBufferedAmount());
log.info("WebSocket backpressure: " + ws.getBufferedAmount());
},
close: (ws, code, message) => {
const Client = ws as ExSocketInterface;
@ -404,8 +405,8 @@ export class IoSocketController {
//leave room
socketManager.leaveRoom(Client);
} catch (e) {
console.error('An error occurred on "disconnect"');
console.error(e);
log.error('An error occurred on "disconnect"');
log.error(e);
}
},
});

View File

@ -8,6 +8,7 @@ import { MapDetailsData } from "../Services/AdminApi/MapDetailsData";
import { socketManager } from "../Services/SocketManager";
import { AuthTokenData, jwtTokenManager } from "../Services/JWTTokenManager";
import { v4 } from "uuid";
import log from "../Services/Logger";
export class MapController extends BaseController {
constructor(private App: TemplatedApp) {
@ -26,13 +27,13 @@ export class MapController extends BaseController {
this.App.get("/map", (res: HttpResponse, req: HttpRequest) => {
res.onAborted(() => {
console.warn("/map request was aborted");
log.warn("/map request was aborted");
});
const query = parse(req.getQuery());
if (typeof query.playUri !== "string") {
console.error("Expected playUri parameter in /map endpoint");
log.error("Expected playUri parameter in /map endpoint");
res.writeStatus("400 Bad request");
this.addCorsHeaders(res);
res.end("Expected playUri parameter");
@ -82,7 +83,7 @@ export class MapController extends BaseController {
// 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);
log.info("JWT expire, but decoded", userId);
}
}
const mapDetails = await adminApi.fetchMapDetails(query.playUri as string, userId);

View File

@ -11,6 +11,7 @@
import { Zone, ZoneEventListener } from "./Zone";
import { ViewportInterface } from "_Model/Websocket/ViewportMessage";
import { ExSocketInterface } from "_Model/Websocket/ExSocketInterface";
import log from "../Services/Logger";
//import Debug from "debug";
//const debug = Debug('positiondispatcher');
@ -44,7 +45,7 @@ export class PositionDispatcher {
*/
public setViewport(socket: ExSocketInterface, viewport: ViewportInterface): void {
if (viewport.left > viewport.right || viewport.top > viewport.bottom) {
console.warn("Invalid viewport received: ", viewport);
log.warn("Invalid viewport received: ", viewport);
return;
}

View File

@ -20,6 +20,7 @@ import {
import { ClientReadableStream } from "grpc";
import { PositionDispatcher } from "_Model/PositionDispatcher";
import Debug from "debug";
import log from "../Services/Logger";
const debug = Debug("zone");
@ -209,7 +210,7 @@ export class Zone {
const userDescriptor = this.users.get(userId);
if (userDescriptor === undefined) {
console.error('Unexpected move message received for user "' + userId + '"');
log.error('Unexpected move message received for user "' + userId + '"');
return;
}

View File

@ -2,6 +2,7 @@ import { createWriteStream } from "fs";
import { join, dirname } from "path";
import Busboy from "busboy";
import mkdirp from "mkdirp";
import log from "../../Services/Logger";
function formData(
contType: string,
@ -19,7 +20,7 @@ function formData(
filename?: (oldName: string) => string;
} = {}
) {
console.log("Enter form data");
log.info("Enter form data");
options.headers = {
"content-type": contType,
};

View File

@ -1,4 +1,5 @@
import { CPU_OVERHEAT_THRESHOLD } from "../Enum/EnvironmentVariable";
import log from "./Logger";
function secNSec2ms(secNSec: Array<number> | number) {
if (Array.isArray(secNSec)) {
@ -28,16 +29,16 @@ class CpuTracker {
if (!this.overHeating && this.cpuPercent > CPU_OVERHEAT_THRESHOLD) {
this.overHeating = true;
console.warn('CPU high threshold alert. Going in "overheat" mode');
log.warn('CPU high threshold alert. Going in "overheat" mode');
} else if (this.overHeating && this.cpuPercent <= CPU_OVERHEAT_THRESHOLD) {
this.overHeating = false;
console.log('CPU is back to normal. Canceling "overheat" mode');
log.info('CPU is back to normal. Canceling "overheat" mode');
}
/*console.log('elapsed time ms: ', elapTimeMS)
console.log('elapsed user ms: ', elapUserMS)
console.log('elapsed system ms:', elapSystMS)
console.log('cpu percent: ', this.cpuPercent)*/
/*log.info('elapsed time ms: ', elapTimeMS)
log.info('elapsed user ms: ', elapUserMS)
log.info('elapsed system ms:', elapSystMS)
log.info('cpu percent: ', this.cpuPercent)*/
}, 100);
}

View File

@ -1,6 +1,7 @@
import { ExSocketInterface } from "_Model/Websocket/ExSocketInterface";
import { BatchMessage, ErrorMessage, ServerToClientMessage, SubMessage } from "../Messages/generated/messages_pb";
import { WebSocket } from "uWebSockets.js";
import log from "./Logger";
export function emitInBatch(socket: ExSocketInterface, payload: SubMessage): void {
socket.batchedMessages.addPayload(payload);
@ -31,5 +32,5 @@ export function emitError(Client: WebSocket, message: string): void {
if (!Client.disconnecting) {
Client.send(serverToClientMessage.serializeBinary().buffer, true);
}
console.warn(message);
log.warn(message);
}

View File

@ -0,0 +1,16 @@
import * as winston from "winston";
const logger = winston.createLogger({
transports: [
new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(),
winston.format.timestamp(),
winston.format.align(),
winston.format.printf((info) => `${info.timestamp} ${info.level}: ${info.message}`)
),
}),
],
});
export default logger;

View File

@ -49,6 +49,7 @@ import { ExAdminSocketInterface } from "_Model/Websocket/ExAdminSocketInterface"
import { WebSocket } from "uWebSockets.js";
import { isRoomRedirect } from "./AdminApi/RoomRedirect";
import { CharacterTexture } from "./AdminApi/CharacterTexture";
import log from "./Logger";
const debug = Debug("socket");
@ -115,15 +116,15 @@ export class SocketManager implements ZoneEventListener {
}
})
.on("end", () => {
console.warn("Admin connection lost to back server");
log.warn("Admin connection lost to back server");
// Let's close the front connection if the back connection is closed. This way, we can retry connecting from the start.
if (!client.disconnecting) {
this.closeWebsocketConnection(client, 1011, "Admin Connection lost to back server");
}
console.log("A user left");
log.info("A user left");
})
.on("error", (err: Error) => {
console.error("Error in connection to back server:", err);
log.error("Error in connection to back server:", err);
if (!client.disconnecting) {
this.closeWebsocketConnection(client, 1011, "Error while connecting to back server");
}
@ -166,7 +167,7 @@ export class SocketManager implements ZoneEventListener {
joinRoomMessage.addCharacterlayer(characterLayerMessage);
}
console.log("Calling joinRoom '"+client.roomId+"' for client "+client.userUuid);
log.info("Calling joinRoom '" + client.roomId + "' for client " + client.userUuid);
const apiClient = await apiClientRepository.getClient(client.roomId);
const streamToPusher = apiClient.joinRoom();
clientEventsEmitter.emitClientJoin(client.userUuid, client.roomId);
@ -198,12 +199,21 @@ export class SocketManager implements ZoneEventListener {
if (!client.disconnecting) {
this.closeWebsocketConnection(client, 1011, "Connection lost to back server");
}
console.log("Closed connection for user '"+client.userUuid+"' to back server "+apiClient.getChannel().getTarget());
log.info(
"Closed connection for user '" +
client.userUuid +
"' to back server " +
apiClient.getChannel().getTarget()
);
})
.on("error", (err: Error) => {
console.error("Error in connection to back server '"+apiClient.getChannel().getTarget()+"':", err);
log.error("Error in connection to back server '" + apiClient.getChannel().getTarget() + "':", err);
if (!client.disconnecting) {
this.closeWebsocketConnection(client, 1011, "Error while connecting to back server '"+apiClient.getChannel().getTarget()+"'");
this.closeWebsocketConnection(
client,
1011,
"Error while connecting to back server '" + apiClient.getChannel().getTarget() + "'"
);
}
});
@ -214,8 +224,8 @@ export class SocketManager implements ZoneEventListener {
const pusherRoom = await this.getOrCreateRoom(client.roomId);
pusherRoom.join(client);
} catch (e) {
console.error('An error occurred on "join_room" event');
console.error(e);
log.error('An error occurred on "join_room" event');
log.error(e);
}
}
@ -232,13 +242,13 @@ export class SocketManager implements ZoneEventListener {
const room = this.rooms.get(client.roomId);
if (!room) {
console.error("In SET_VIEWPORT, could not find world with id '", client.roomId, "'");
log.error("In SET_VIEWPORT, could not find world with id '", client.roomId, "'");
return;
}
room.setViewport(client, client.viewport);
} catch (e) {
console.error('An error occurred on "SET_VIEWPORT" event');
console.error(e);
log.error('An error occurred on "SET_VIEWPORT" event');
log.error(e);
}
}
@ -309,8 +319,8 @@ export class SocketManager implements ZoneEventListener {
client.roomId
);
} catch (e) {
console.error('An error occurred on "handleReportMessage"');
console.error(e);
log.error('An error occurred on "handleReportMessage"');
log.error(e);
}
}
@ -345,14 +355,14 @@ export class SocketManager implements ZoneEventListener {
debug("Room %s is empty. Deleting.", socket.roomId);
}
} else {
console.error("Could not find the GameRoom the user is leaving!");
log.error("Could not find the GameRoom the user is leaving!");
}
//user leave previous room
//Client.leave(Client.roomId);
} finally {
//delete Client.roomId;
clientEventsEmitter.emitClientLeave(socket.userUuid, socket.roomId);
console.log("User '"+socket.userUuid+"' left");
log.info("User '" + socket.userUuid + "' left");
}
}
} finally {
@ -434,7 +444,7 @@ export class SocketManager implements ZoneEventListener {
client.send(serverToClientMessage.serializeBinary().buffer, true);
} catch (e) {
console.error("An error occurred while generating the Jitsi JWT token: ", e);
log.error("An error occurred while generating the Jitsi JWT token: ", e);
}
}
@ -458,7 +468,7 @@ export class SocketManager implements ZoneEventListener {
backAdminMessage.setType(type);
backConnection.sendAdminMessage(backAdminMessage, (error) => {
if (error !== null) {
console.error("Error while sending admin message", error);
log.error("Error while sending admin message", error);
}
});
}
@ -483,7 +493,7 @@ export class SocketManager implements ZoneEventListener {
banMessage.setType(type);
backConnection.ban(banMessage, (error) => {
if (error !== null) {
console.error("Error while sending admin message", error);
log.error("Error while sending admin message", error);
}
});
}

View File

@ -23,6 +23,15 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
"@dabh/diagnostics@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.2.tgz#290d08f7b381b8f94607dc8f471a12c675f9db31"
integrity sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==
dependencies:
colorspace "1.1.x"
enabled "2.0.x"
kuler "^2.0.0"
"@mapbox/node-pre-gyp@^1.0.4":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz#2a0b32fcb416fb3f2250fd24cb2a81421a4f5950"
@ -367,6 +376,11 @@ astral-regex@^2.0.0:
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
async@^3.1.0:
version "3.2.2"
resolved "https://registry.yarnpkg.com/async/-/async-3.2.2.tgz#2eb7671034bb2194d45d30e31e24ec7e7f9670cd"
integrity sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==
axios@^0.21.2:
version "0.21.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.2.tgz#21297d5084b2aeeb422f5d38e7be4fbb82239017"
@ -549,7 +563,7 @@ code-point-at@^1.0.0:
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
color-convert@^1.9.0:
color-convert@^1.9.0, color-convert@^1.9.3:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
@ -568,16 +582,45 @@ color-name@1.1.3:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
color-name@~1.1.4:
color-name@^1.0.0, color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-string@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.6.0.tgz#c3915f61fe267672cb7e1e064c9d692219f6c312"
integrity sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==
dependencies:
color-name "^1.0.0"
simple-swizzle "^0.2.2"
color@^3.1.3:
version "3.2.1"
resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164"
integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==
dependencies:
color-convert "^1.9.3"
color-string "^1.6.0"
colorette@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
colors@^1.2.1:
version "1.4.0"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
colorspace@1.1.x:
version "1.1.4"
resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243"
integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==
dependencies:
color "^3.1.3"
text-hex "1.0.x"
colour@~0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/colour/-/colour-0.7.1.tgz#9cb169917ec5d12c0736d3e8685746df1cadf778"
@ -731,6 +774,11 @@ emoji-regex@^8.0.0:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
enabled@2.0.x:
version "2.0.0"
resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2"
integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==
end-of-stream@^1.1.0:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
@ -909,6 +957,11 @@ fast-levenshtein@~2.0.6:
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
fecha@^4.2.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.1.tgz#0a83ad8f86ef62a091e22bb5a039cd03d23eecce"
integrity sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==
figures@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
@ -949,6 +1002,11 @@ flatted@^2.0.0:
resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138"
integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==
fn.name@1.x.x:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
follow-redirects@^1.14.0:
version "1.14.4"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379"
@ -1168,7 +1226,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
inherits@2, inherits@~2.0.3:
inherits@2, inherits@^2.0.3, inherits@~2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@ -1202,6 +1260,11 @@ is-arrayish@^0.2.1:
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
is-arrayish@^0.3.1:
version "0.3.2"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
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"
@ -1373,6 +1436,11 @@ keyv@^4.0.0:
dependencies:
json-buffer "3.0.1"
kuler@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3"
integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==
lcid@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
@ -1495,6 +1563,17 @@ log-update@^4.0.0:
slice-ansi "^4.0.0"
wrap-ansi "^6.2.0"
logform@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/logform/-/logform-2.3.0.tgz#a3997a05985de2ebd325ae0d166dffc9c6fe6b57"
integrity sha512-graeoWUH2knKbGthMtuG1EfaSPMZFZBIrhuJHhkS5ZseFBrc7DupCzihOQAzsK/qIKPQaPJ/lFQFctILUY5ARQ==
dependencies:
colors "^1.2.1"
fecha "^4.2.0"
ms "^2.1.1"
safe-stable-stringify "^1.1.0"
triple-beam "^1.3.0"
long@~3:
version "3.2.0"
resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b"
@ -1687,6 +1766,13 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
dependencies:
wrappy "1"
one-time@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45"
integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==
dependencies:
fn.name "1.x.x"
onetime@^5.1.0, onetime@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
@ -1867,7 +1953,7 @@ quick-lru@^5.1.1:
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
readable-stream@^2.0.6:
readable-stream@^2.0.6, readable-stream@^2.3.7:
version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
@ -1880,6 +1966,15 @@ readable-stream@^2.0.6:
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
readable-stream@^3.4.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
dependencies:
inherits "^2.0.3"
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
@ -1963,7 +2058,7 @@ rxjs@^6.6.0, rxjs@^6.6.7:
dependencies:
tslib "^1.9.0"
safe-buffer@^5.0.1:
safe-buffer@^5.0.1, safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
@ -1973,6 +2068,11 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
safe-stable-stringify@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz#c8a220ab525cd94e60ebf47ddc404d610dc5d84a"
integrity sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==
"safer-buffer@>= 2.1.2 < 3":
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
@ -2034,6 +2134,13 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
simple-swizzle@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=
dependencies:
is-arrayish "^0.3.1"
slice-ansi@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636"
@ -2084,6 +2191,11 @@ sprintf-js@~1.0.2:
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
stack-trace@0.0.x:
version "0.0.10"
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=
streamsearch@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
@ -2134,6 +2246,13 @@ string-width@^4.1.0, string-width@^4.2.0:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.0"
string_decoder@^1.1.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
dependencies:
safe-buffer "~5.2.0"
string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
@ -2241,6 +2360,11 @@ tdigest@^0.1.1:
dependencies:
bintrees "1.0.1"
text-hex@1.0.x:
version "1.0.0"
resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5"
integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==
text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
@ -2270,6 +2394,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==
triple-beam@^1.2.0, triple-beam@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"
integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==
ts-node-dev@^1.0.0-pre.44:
version "1.1.8"
resolved "https://registry.yarnpkg.com/ts-node-dev/-/ts-node-dev-1.1.8.tgz#95520d8ab9d45fffa854d6668e2f8f9286241066"
@ -2353,7 +2482,7 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
util-deprecate@~1.0.1:
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
@ -2402,6 +2531,29 @@ window-size@^0.1.4:
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876"
integrity sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=
winston-transport@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.4.0.tgz#17af518daa690d5b2ecccaa7acf7b20ca7925e59"
integrity sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==
dependencies:
readable-stream "^2.3.7"
triple-beam "^1.2.0"
winston@^3.3.3:
version "3.3.3"
resolved "https://registry.yarnpkg.com/winston/-/winston-3.3.3.tgz#ae6172042cafb29786afa3d09c8ff833ab7c9170"
integrity sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==
dependencies:
"@dabh/diagnostics" "^2.0.2"
async "^3.1.0"
is-stream "^2.0.0"
logform "^2.2.0"
one-time "^1.0.0"
readable-stream "^3.4.0"
stack-trace "0.0.x"
triple-beam "^1.3.0"
winston-transport "^4.4.0"
word-wrap@~1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"