From 2229fda3edd84d821e6d8b4f0044fc5a71794969 Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Thu, 19 Sep 2024 05:33:06 +0000 Subject: [PATCH] passes linting --- .../src/components/MenuBar/NavigationBar.tsx | 21 +- .../src/components/MenuBar/PageNumInput.tsx | 18 +- .../src/contexts/StateContextProvider.tsx | 297 ++++++++++-------- .../src/contexts/UrlContextProvider.tsx | 8 +- new-log-viewer/src/services/LogFileManager.ts | 9 +- .../src/services/decoders/JsonlDecoder.ts | 66 ++-- 6 files changed, 236 insertions(+), 183 deletions(-) diff --git a/new-log-viewer/src/components/MenuBar/NavigationBar.tsx b/new-log-viewer/src/components/MenuBar/NavigationBar.tsx index ebdea6f1..cc64276d 100644 --- a/new-log-viewer/src/components/MenuBar/NavigationBar.tsx +++ b/new-log-viewer/src/components/MenuBar/NavigationBar.tsx @@ -1,4 +1,7 @@ -import React, {useContext, useMemo} from "react"; +import React, { + useContext, + useMemo, +} from "react"; import NavigateBefore from "@mui/icons-material/NavigateBefore"; import NavigateNext from "@mui/icons-material/NavigateNext"; @@ -6,19 +9,16 @@ import SkipNext from "@mui/icons-material/SkipNext"; import SkipPrevious from "@mui/icons-material/SkipPrevious"; import {StateContext} from "../../contexts/StateContextProvider"; +import {CONFIG_KEY} from "../../typings/config"; import { ACTION_NAME, handleAction, } from "../../utils/actions"; +import {getConfig} from "../../utils/config"; +import {getChunkNum} from "../../utils/math"; import PageNumInput from "./PageNumInput"; import SmallIconButton from "./SmallIconButton"; -import {getConfig} from "../../utils/config"; -import {CONFIG_KEY} from "../../typings/config"; -import { - getChunkNum, -} from "../../utils/math"; - /** * Renders a navigation bar for page switching actions. @@ -27,8 +27,11 @@ import { */ const NavigationBar = () => { const {pageNum, numFilteredEvents, loadPage} = useContext(StateContext); - let numPages: number = - useMemo(() => getChunkNum(numFilteredEvents, getConfig(CONFIG_KEY.PAGE_SIZE)),[numFilteredEvents]); + const numPages: number = + useMemo( + () => getChunkNum(numFilteredEvents, getConfig(CONFIG_KEY.PAGE_SIZE)), + [numFilteredEvents] + ); const handleNavButtonClick = (event: React.MouseEvent) => { const {actionName} = event.currentTarget.dataset as { actionName: ACTION_NAME }; if (Object.values(ACTION_NAME).includes(actionName)) { diff --git a/new-log-viewer/src/components/MenuBar/PageNumInput.tsx b/new-log-viewer/src/components/MenuBar/PageNumInput.tsx index b5c12a66..c0c93658 100644 --- a/new-log-viewer/src/components/MenuBar/PageNumInput.tsx +++ b/new-log-viewer/src/components/MenuBar/PageNumInput.tsx @@ -1,21 +1,18 @@ import React, { useContext, useEffect, + useMemo, useRef, useState, - useMemo, } from "react"; -import {getConfig} from "../../utils/config"; -import {CONFIG_KEY} from "../../typings/config"; -import { - getChunkNum, -} from "../../utils/math"; - import {Typography} from "@mui/joy"; import Input from "@mui/joy/Input"; import {StateContext} from "../../contexts/StateContextProvider"; +import {CONFIG_KEY} from "../../typings/config"; +import {getConfig} from "../../utils/config"; +import {getChunkNum} from "../../utils/math"; import "./PageNumInput.css"; @@ -30,8 +27,11 @@ const PAGE_NUM_INPUT_FIT_EXTRA_WIDTH = 2; */ const PageNumInput = () => { const {loadPage, numFilteredEvents, pageNum} = useContext(StateContext); - let numPages: number = - useMemo(() => getChunkNum(numFilteredEvents, getConfig(CONFIG_KEY.PAGE_SIZE)),[numFilteredEvents]); + const numPages: number = + useMemo( + () => getChunkNum(numFilteredEvents, getConfig(CONFIG_KEY.PAGE_SIZE)), + [numFilteredEvents] + ); const adjustedPageNum = (null === pageNum) ? 0 : diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index d131f56a..4d9ef933 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -39,18 +39,18 @@ import { interface StateContextType { - beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap, - fileName: string, - firstLogEventNumOnPage: number[], - lastLogEventNumOnPage: number[], - logData: string, - numEvents: number, - numFilteredEvents: number, - pageNum: Nullable, - - changeLogLevelFilter: (newLogLevelFilter: LogLevelFilter) => void, - loadFile: (fileSrc: FileSrcType, cursor: CursorType) => void, - loadPage: (newPageNum: number) => void, + beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap; + fileName: string; + firstLogEventNumOnPage: number[]; + lastLogEventNumOnPage: number[]; + logData: string; + numEvents: number; + numFilteredEvents: number; + pageNum: Nullable; + + changeLogLevelFilter: (newLogLevelFilter: LogLevelFilter) => void; + loadFile: (fileSrc: FileSrcType, cursor: CursorType) => void; + loadPage: (newPageNum: number) => void; } const StateContext = createContext({} as StateContextType); @@ -74,7 +74,7 @@ const STATE_DEFAULT: Readonly = Object.freeze({ }); interface StateContextProviderProps { - children: React.ReactNode + children: React.ReactNode; } /** @@ -89,7 +89,7 @@ interface StateContextProviderProps { const workerPostReq = ( worker: Worker, code: T, - args: WorkerReq + args: WorkerReq, ) => { worker.postMessage({code, args}); }; @@ -111,78 +111,123 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { const [logData, setLogData] = useState(STATE_DEFAULT.logData); const [numEvents, setNumEvents] = useState(STATE_DEFAULT.numEvents); - const [numFilteredEvents, setNumFilteredEvents] = useState(STATE_DEFAULT.numFilteredEvents); - - const [pageNum, setPageNum] = useState>(STATE_DEFAULT.pageNum); - - const beginLineNumToLogEventNumRef = - useRef(STATE_DEFAULT.beginLineNumToLogEventNum); - - const firstLogEventNumPerPage = - useRef(STATE_DEFAULT.firstLogEventNumOnPage); - const lastLogEventNumPerPage = - useRef(STATE_DEFAULT.lastLogEventNumOnPage); - - const mainWorkerRef = useRef(null); - - const handleMainWorkerResp = useCallback((ev: MessageEvent) => { - const {code, args} = ev.data; - console.log(`[MainWorker -> Renderer] code=${code}`); - switch (code) { - case WORKER_RESP_CODE.LOG_FILE_INFO: - setFileName(args.fileName); - setNumEvents(args.numEvents); - break; - case WORKER_RESP_CODE.NOTIFICATION: - // eslint-disable-next-line no-warning-comments - // TODO: notifications should be shown in the UI when the NotificationProvider - // is added - console.error(args.logLevel, args.message); - break; - case WORKER_RESP_CODE.PAGE_DATA: { - setLogData(args.logs); - beginLineNumToLogEventNumRef.current = args.beginLineNumToLogEventNum; - console.log(`page data log event`) - //console.log(logEventNumRef.current); - //let logEventInput = logEventNumRef.current; - const newLogEventNum: number = getClosestLogEventNum(args.beginLineNumToLogEventNum) - updateWindowUrlHashParams({ - logEventNum: newLogEventNum, - }); - break; + const [numFilteredEvents, setNumFilteredEvents] = useState( + STATE_DEFAULT.numFilteredEvents, + ); + + const [pageNum, setPageNum] = useState>( + STATE_DEFAULT.pageNum, + ); + + const beginLineNumToLogEventNumRef = useRef( + STATE_DEFAULT.beginLineNumToLogEventNum, + ); + + const firstLogEventNumPerPage = useRef( + STATE_DEFAULT.firstLogEventNumOnPage, + ); + const lastLogEventNumPerPage = useRef( + STATE_DEFAULT.lastLogEventNumOnPage, + ); + + const previousFilePath = useRef(""); + + const mainWorkerRef = useRef(null); + + const getClosestLogEventNum = useCallback( + (beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap) => { + const inputLogEventNum = logEventNum; + let newLogEventNum: Nullable = null; + const logEventNumOnPage = Array.from(beginLineNumToLogEventNum.values()); + + // On initial load we don't know load event so just use last value + if (!inputLogEventNum) { + newLogEventNum = logEventNumOnPage.at(-1) as number; + + return newLogEventNum; } - case WORKER_RESP_CODE.VIEW_INFO: - setNumFilteredEvents(args.numFilteredEvents) - firstLogEventNumPerPage.current = args.firstLogEventNumPerPage; - lastLogEventNumPerPage.current = args.lastLogEventNumPerPage; - break; - default: - console.error(`Unexpected ev.data: ${JSON.stringify(ev.data)}`); - break; - } - }, []); - const loadFile = useCallback((fileSrc: FileSrcType, cursor: CursorType) => { - if ("string" !== typeof fileSrc) { - updateWindowUrlSearchParams({[SEARCH_PARAM_NAMES.FILE_PATH]: null}); - } - if (null !== mainWorkerRef.current) { - mainWorkerRef.current.terminate(); - } - mainWorkerRef.current = new Worker( - new URL("../services/MainWorker.ts", import.meta.url) - ); - mainWorkerRef.current.onmessage = handleMainWorkerResp; - workerPostReq(mainWorkerRef.current, WORKER_REQ_CODE.LOAD_FILE, { - fileSrc: fileSrc, - pageSize: getConfig(CONFIG_KEY.PAGE_SIZE), - cursor: cursor, - decoderOptions: getConfig(CONFIG_KEY.DECODER_OPTIONS), - }); - }, [ - handleMainWorkerResp, - ]); + for (let i = logEventNumOnPage.length; 0 < i; i--) { + if ((logEventNumOnPage[i] as number) <= inputLogEventNum) { + newLogEventNum = logEventNumOnPage[i] as number; + break; + } + } + + if (!newLogEventNum) { + // If all elements larger than logEvent, i.e. all checks in findLastIndex are false, + // i.e. logEvent is the smallest return first one + newLogEventNum = logEventNumOnPage[0] as number; + } + + return newLogEventNum; + }, + [logEventNum], + ); + + const handleMainWorkerResp = useCallback( + (ev: MessageEvent) => { + const {code, args} = ev.data; + console.log(`[MainWorker -> Renderer] code=${code}`); + switch (code) { + case WORKER_RESP_CODE.LOG_FILE_INFO: + setFileName(args.fileName); + setNumEvents(args.numEvents); + break; + case WORKER_RESP_CODE.NOTIFICATION: + // eslint-disable-next-line no-warning-comments + // TODO: notifications should be shown in the UI when the NotificationProvider + // is added + console.error(args.logLevel, args.message); + break; + case WORKER_RESP_CODE.PAGE_DATA: { + setLogData(args.logs); + beginLineNumToLogEventNumRef.current = args.beginLineNumToLogEventNum; + console.log("page data log event"); + + const newLogEventNum: number = getClosestLogEventNum( + args.beginLineNumToLogEventNum, + ); + + updateWindowUrlHashParams({ + logEventNum: newLogEventNum, + }); + break; + } + case WORKER_RESP_CODE.VIEW_INFO: + setNumFilteredEvents(args.numFilteredEvents); + firstLogEventNumPerPage.current = args.firstLogEventNumPerPage; + lastLogEventNumPerPage.current = args.lastLogEventNumPerPage; + break; + default: + console.error(`Unexpected ev.data: ${JSON.stringify(ev.data)}`); + break; + } + }, + [getClosestLogEventNum], + ); + const loadFile = useCallback( + (fileSrc: FileSrcType, cursor: CursorType) => { + if ("string" !== typeof fileSrc) { + updateWindowUrlSearchParams({[SEARCH_PARAM_NAMES.FILE_PATH]: null}); + } + if (null !== mainWorkerRef.current) { + mainWorkerRef.current.terminate(); + } + mainWorkerRef.current = new Worker( + new URL("../services/MainWorker.ts", import.meta.url), + ); + mainWorkerRef.current.onmessage = handleMainWorkerResp; + workerPostReq(mainWorkerRef.current, WORKER_REQ_CODE.LOAD_FILE, { + fileSrc: fileSrc, + pageSize: getConfig(CONFIG_KEY.PAGE_SIZE), + cursor: cursor, + decoderOptions: getConfig(CONFIG_KEY.DECODER_OPTIONS), + }); + }, + [handleMainWorkerResp], + ); const changeLogLevelFilter = (newLogLevelFilter: LogLevelFilter) => { if (null === mainWorkerRef.current) { @@ -194,10 +239,10 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { }); }; - const loadPage = (newPageNum: number) => { if (null === mainWorkerRef.current) { console.error("Unexpected null mainWorkerRef.current"); + return; } workerPostReq(mainWorkerRef.current, WORKER_REQ_CODE.LOAD_PAGE, { @@ -207,28 +252,33 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { // On `logEventNum` update, clamp it then switch page if necessary or simply update the URL. useEffect(() => { - console.log(logEventNum) - if (null === mainWorkerRef.current || URL_HASH_PARAMS_DEFAULT.logEventNum === logEventNum || - 0 === firstLogEventNumPerPage.current.length || numEvents === STATE_DEFAULT.numEvents) { + if ( + null === mainWorkerRef.current || + URL_HASH_PARAMS_DEFAULT.logEventNum === logEventNum || + 0 === firstLogEventNumPerPage.current.length || + numEvents === STATE_DEFAULT.numEvents + ) { return; } - let clampedLogEventNum: number = clamp(logEventNum, 1, numEvents); - - console.log(logEventNum) + const clampedLogEventNum: number = clamp(logEventNum, 1, numEvents); - const newPageIndex = firstLogEventNumPerPage.current.findLastIndex((value: number) => value <= clampedLogEventNum); + const newPageIndex = firstLogEventNumPerPage.current.findLastIndex( + (value: number) => value <= clampedLogEventNum, + ); if (-1 === newPageIndex) { // logEventNum is not on any available page - if (logEventNum !== clampedLogEventNum) - updateWindowUrlHashParams({ - logEventNum: clampedLogEventNum, - }); + if (logEventNum !== clampedLogEventNum) { + updateWindowUrlHashParams({ + logEventNum: clampedLogEventNum, + }); + } + return; } - const newPageNum = newPageIndex + 1 + const newPageNum = newPageIndex + 1; if (newPageNum !== pageNum) { loadPage(newPageNum); @@ -236,21 +286,30 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { } else { // Page has not changed // This will trigger another useEffect but shouldn't do anything - const newLogEventNum = getClosestLogEventNum(beginLineNumToLogEventNumRef.current) + const newLogEventNum = getClosestLogEventNum( + beginLineNumToLogEventNumRef.current, + ); + updateWindowUrlHashParams({ logEventNum: newLogEventNum, }); } - }, [ + }, [numEvents, + pageNum, logEventNum, - ]); + getClosestLogEventNum]); // On `filePath` update, load file. useEffect(() => { - if (URL_SEARCH_PARAMS_DEFAULT.filePath === filePath) { + if ( + previousFilePath.current === filePath || + URL_SEARCH_PARAMS_DEFAULT.filePath === filePath + ) { return; } + previousFilePath.current = filePath; + let cursor: CursorType = {code: CURSOR_CODE.LAST_EVENT, args: null}; if (URL_HASH_PARAMS_DEFAULT.logEventNum !== logEventNum) { // Set which page to load since the user specified a specific `logEventNum`.\= @@ -258,45 +317,16 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { // minimum of the page number. const newPageNum = Math.max( getChunkNum(logEventNum, getConfig(CONFIG_KEY.PAGE_SIZE)), - 1 + 1, ); cursor = {code: CURSOR_CODE.PAGE_NUM, args: {pageNum: newPageNum}}; - setPageNum(newPageNum) + setPageNum(newPageNum); } loadFile(filePath, cursor); - }, [ + }, [logEventNum, filePath, - loadFile, - ]); - - // Do not move this out of component. There are some strange effects with React that will occasionally - // set logEventNum to null if outside. - const getClosestLogEventNum = (beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap) => { - let inputLogEventNum = logEventNum; - let newLogEventNum: Nullable = null; - const logEventNumOnPage = Array.from(beginLineNumToLogEventNum.values()) - - // On initial load we don't know load event so just use last value - if (!inputLogEventNum) { - newLogEventNum = logEventNumOnPage.at(-1) as number - return newLogEventNum; - } - - for (let i = logEventNumOnPage.length; i > 0; i--) { - if (logEventNumOnPage[i] as number <= inputLogEventNum) { - newLogEventNum = logEventNumOnPage[i] as number; - break; - } - } - - if (!newLogEventNum) { - //If all elements larger than logEvent, i.e. all checks in findLastIndex are false, i.e. logEvent is the smallest return first one - newLogEventNum = logEventNumOnPage[0] as number; - } - - return newLogEventNum; - }; + loadFile]); return ( { ); }; - export default StateContextProvider; export {StateContext}; diff --git a/new-log-viewer/src/contexts/UrlContextProvider.tsx b/new-log-viewer/src/contexts/UrlContextProvider.tsx index 0ac356eb..ba3cc6bf 100644 --- a/new-log-viewer/src/contexts/UrlContextProvider.tsx +++ b/new-log-viewer/src/contexts/UrlContextProvider.tsx @@ -212,8 +212,8 @@ const getWindowUrlHashParams = () => { parsed; } - console.log("update params") - console.log(urlHashParams) + console.log("update params"); + console.log(urlHashParams); return urlHashParams; }; @@ -242,8 +242,8 @@ const UrlContextProvider = ({children}: UrlContextProviderProps) => { useEffect(() => { const handleHashChange = () => { - console.log("set params") - console.log(getWindowUrlHashParams()) + console.log("set params"); + console.log(getWindowUrlHashParams()); setUrlParams({ ...URL_SEARCH_PARAMS_DEFAULT, ...URL_HASH_PARAMS_DEFAULT, diff --git a/new-log-viewer/src/services/LogFileManager.ts b/new-log-viewer/src/services/LogFileManager.ts index b84f5462..4f2b6665 100644 --- a/new-log-viewer/src/services/LogFileManager.ts +++ b/new-log-viewer/src/services/LogFileManager.ts @@ -1,3 +1,5 @@ +/* eslint-disable max-lines */ + import { Decoder, DecoderOptions, @@ -227,7 +229,11 @@ class LogFileManager { implemented for this file type on new log viewer`); } - logLevelFilter ? this.#computeFilteredPageBoundaries() : this.#computeUnfilteredPageBoundaries() + if (logLevelFilter) { + this.#computeFilteredPageBoundaries(); + } else { + this.#computeUnfilteredPageBoundaries(); + } } /** @@ -243,7 +249,6 @@ class LogFileManager { this.#numFilteredEvents = filteredLogEventsIndices.length; for (let i = 0; i < this.#numFilteredEvents; i += this.#pageSize) { - const firstLogEventOnPageIdx: number = filteredLogEventsIndices[i] as number; this.#firstLogEventNumOnPage.push(1 + firstLogEventOnPageIdx); diff --git a/new-log-viewer/src/services/decoders/JsonlDecoder.ts b/new-log-viewer/src/services/decoders/JsonlDecoder.ts index cc1e3c2e..9a18aeb1 100644 --- a/new-log-viewer/src/services/decoders/JsonlDecoder.ts +++ b/new-log-viewer/src/services/decoders/JsonlDecoder.ts @@ -21,6 +21,7 @@ import { } from "../../typings/logs"; import LogbackFormatter from "../formatters/LogbackFormatter"; + /** * A decoder for JSONL (JSON lines) files that contain log events. See `JsonlDecodeOptionsType` for * properties that are specific to log events (compared to generic JSON records). @@ -62,7 +63,7 @@ class JsonlDecoder implements Decoder { return this.#logEvents.length; } - getFilteredLogEvents () : number[] { + getFilteredLogEvents (): number[] { return this.#filteredLogIndices; } @@ -73,7 +74,9 @@ class JsonlDecoder implements Decoder { this.#deserialize(); - const numInvalidEvents = Array.from(this.#invalidLogEventIdxToRawLine.keys()).length; + const numInvalidEvents = Array.from( + this.#invalidLogEventIdxToRawLine.keys(), + ).length; return { numValidEvents: this.#logEvents.length - numInvalidEvents, @@ -83,20 +86,30 @@ class JsonlDecoder implements Decoder { changeLogLevelFilter (logLevelFilter: LogLevelFilter): boolean { this.#filterLogs(logLevelFilter); - this.#isFiltered = logLevelFilter ? true : false; + this.#isFiltered = Boolean(logLevelFilter); + return true; } decodeRange (beginIdx: number, endIdx: number): Nullable { - return this.#decodeAnyRange(beginIdx,endIdx,false) + return this.#decodeAnyRange(beginIdx, endIdx, false); } - decodeFilteredRange (beginIdx: number, endIdx: number): Nullable { - return this.#decodeAnyRange(beginIdx,endIdx,this.#isFiltered) + decodeFilteredRange ( + beginIdx: number, + endIdx: number, + ): Nullable { + return this.#decodeAnyRange(beginIdx, endIdx, this.#isFiltered); } - #decodeAnyRange (beginIdx: number, endIdx: number, useFilter: boolean): Nullable { - let length: number = useFilter ? this.#filteredLogIndices.length : this.#logEvents.length + #decodeAnyRange ( + beginIdx: number, + endIdx: number, + useFilter: boolean, + ): Nullable { + const length: number = useFilter ? + this.#filteredLogIndices.length : + this.#logEvents.length; if (0 > beginIdx || length < endIdx) { return null; @@ -113,9 +126,9 @@ class JsonlDecoder implements Decoder { // Explicit cast since typescript thinks `#filteredLogIndices[filteredLogEventIdx]` can // be undefined, but it shouldn't be since we performed a bounds check at the beginning // of the method. - let filteredIdx: number = useFilter ? - this.#filteredLogIndices[logEventIdx] as number : - logEventIdx + const filteredIdx: number = useFilter ? + (this.#filteredLogIndices[logEventIdx] as number) : + logEventIdx; if (this.#invalidLogEventIdxToRawLine.has(filteredIdx)) { timestamp = INVALID_TIMESTAMP_VALUE; @@ -124,18 +137,19 @@ class JsonlDecoder implements Decoder { } else { // Explicit cast since typescript thinks `#logEvents[logEventIdx]` can be undefined, // but it shouldn't be since the index comes from a class-internal filter. - const logEvent: JsonLogEvent = this.#logEvents[filteredIdx] as JsonLogEvent; + const logEvent: JsonLogEvent = this.#logEvents[ + filteredIdx + ] as JsonLogEvent; + logLevel = logEvent.level; message = this.#formatter.formatLogEvent(logEvent); timestamp = logEvent.timestamp.valueOf(); } - results.push([ - message, + results.push([message, timestamp, logLevel, - filteredIdx + 1, - ]); + filteredIdx + 1]); } return results; @@ -154,11 +168,12 @@ class JsonlDecoder implements Decoder { let beginIdx = 0; while (beginIdx < text.length) { const endIdx = text.indexOf("\n", beginIdx); - const line = (-1 === endIdx) ? - text.substring(beginIdx) : - text.substring(beginIdx, endIdx); + const line = + -1 === endIdx ? + text.substring(beginIdx) : + text.substring(beginIdx, endIdx); - beginIdx = (-1 === endIdx) ? + beginIdx = -1 === endIdx ? text.length : endIdx + 1; @@ -224,14 +239,15 @@ class JsonlDecoder implements Decoder { return logLevel; } - const logLevelStr = "object" === typeof parsedLogLevel ? - JSON.stringify(parsedLogLevel) : - String(parsedLogLevel); + const logLevelStr = + "object" === typeof parsedLogLevel ? + JSON.stringify(parsedLogLevel) : + String(parsedLogLevel); - if (false === (logLevelStr.toUpperCase() in LOG_LEVEL)) { + if (false === logLevelStr.toUpperCase() in LOG_LEVEL) { console.error(`${logLevelStr} doesn't match any known log level.`); } else { - logLevel = LOG_LEVEL[logLevelStr as (keyof typeof LOG_LEVEL)]; + logLevel = LOG_LEVEL[logLevelStr as keyof typeof LOG_LEVEL]; } return logLevel;