Merged in feat/sw-3596-console (pull request #3100)

feat(SW-3596): added lint rule for no console.log. Use logger instead.

* feat(SW-3596): added lint rule for no console.log. Use logger instead.


Approved-by: Joakim Jäderberg
This commit is contained in:
Linus Flood
2025-11-07 08:14:16 +00:00
parent 2d237b8d14
commit 1a24eb68c7
18 changed files with 43 additions and 27 deletions

View File

@@ -35,7 +35,7 @@ export async function POST(_req: NextRequest) {
) )
if (!newTokens || error) { if (!newTokens || error) {
console.error("Error refreshing token", error) logger.error("Error refreshing token", error)
if (isResponseError(error)) { if (isResponseError(error)) {
if (error.status === 400 && error.cause === "invalid_grant") { if (error.status === 400 && error.cause === "invalid_grant") {

View File

@@ -28,6 +28,7 @@ export default defineConfig([
}, },
rules: { rules: {
"no-console": "warn",
"no-unused-vars": "off", "no-unused-vars": "off",
"react/function-component-definition": "error", "react/function-component-definition": "error",
"import/no-relative-packages": "error", "import/no-relative-packages": "error",

View File

@@ -21,6 +21,7 @@ export default defineConfig([
parser: tsParser, parser: tsParser,
}, },
rules: { rules: {
"no-console": "warn",
"no-unused-vars": "off", "no-unused-vars": "off",
"simple-import-sort/imports": "error", "simple-import-sort/imports": "error",
"simple-import-sort/exports": "error", "simple-import-sort/exports": "error",

View File

@@ -1,3 +1,4 @@
/* eslint-disable no-console */
import crypto from "node:crypto"; import crypto from "node:crypto";
function generateApiKey(length = 32): string { function generateApiKey(length = 32): string {

View File

@@ -80,6 +80,3 @@ export const redisConfig = {
username: redisMatch.groups.username, username: redisMatch.groups.username,
password: redisMatch.groups.password, password: redisMatch.groups.password,
}; };
console.log("env", env);
console.log("redisConfig", redisConfig);

View File

@@ -1,6 +1,5 @@
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { env } from "@/env/server"
import { getProfile } from "@/lib/trpc/memoizedRequests" import { getProfile } from "@/lib/trpc/memoizedRequests"
import { TeamMemberCardTrigger } from "@/components/DigitalTeamMemberCard/Trigger" import { TeamMemberCardTrigger } from "@/components/DigitalTeamMemberCard/Trigger"

View File

@@ -28,6 +28,7 @@ export default defineConfig([
}, },
rules: { rules: {
"no-console": "warn",
"no-unused-vars": "off", "no-unused-vars": "off",
"react/function-component-definition": "error", "react/function-component-definition": "error",
"import/no-relative-packages": "error", "import/no-relative-packages": "error",

View File

@@ -1,23 +1,26 @@
import crypto from "crypto" import crypto from "crypto"
import jwt from "jsonwebtoken" import jwt from "jsonwebtoken"
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
import { safeTry } from "@scandic-hotels/common/utils/safeTry"
import { import {
type WarmupFunctionsKey, type WarmupFunctionsKey,
warmupKeys, warmupKeys,
} from "@/services/warmup/warmupKeys" } from "@/services/warmup/warmupKeys"
import { safeTry } from "@scandic-hotels/common/utils/safeTry"
import { timeout } from "@/utils/timeout" import { timeout } from "@/utils/timeout"
import type { Config, Context } from "@netlify/functions" import type { Config, Context } from "@netlify/functions"
async function WarmupHandler(request: Request, context: Context) { async function WarmupHandler(request: Request, context: Context) {
const warmupLogger = createLogger("warmup")
const [_, error] = await safeTry(validateRequest(request, context)) const [_, error] = await safeTry(validateRequest(request, context))
if (error) { if (error) {
if (error instanceof Error) { if (error instanceof Error) {
switch (error.message as ErrorCode) { switch (error.message as ErrorCode) {
case ErrorCodes.WARMUP_DISABLED: case ErrorCodes.WARMUP_DISABLED:
console.warn("[WARMUP] Warmup is disabled") warmupLogger.warn("Warmup is disabled")
return return
case ErrorCodes.REQUEST_NOT_FOR_CURRENT_CONTEXT: case ErrorCodes.REQUEST_NOT_FOR_CURRENT_CONTEXT:
// This is expected, this webhook will be called for all deployments // This is expected, this webhook will be called for all deployments
@@ -26,19 +29,20 @@ async function WarmupHandler(request: Request, context: Context) {
} }
} }
console.error("[WARMUP] Warmup failed", error) warmupLogger.error("Warmup failed", error)
return return
} }
console.log("[WARMUP] Request is valid, starting warmup") warmupLogger.info("Request is valid, starting warmup")
await performWarmup(context) await performWarmup(context)
console.log("[WARMUP] Warmup completed") warmupLogger.info("Warmup completed")
} }
async function validateRequest( async function validateRequest(
request: Request, request: Request,
context: Context context: Context
): Promise<true> { ): Promise<true> {
const warmupLogger = createLogger("warmup")
if (request.method !== "POST") { if (request.method !== "POST") {
throw new Error(ErrorCodes.METHOD_NOT_ALLOWED) throw new Error(ErrorCodes.METHOD_NOT_ALLOWED)
} }
@@ -57,7 +61,7 @@ async function validateRequest(
} }
const body = await request.text() const body = await request.text()
console.log("[WARMUP] Warmup body", body) warmupLogger.info("Warmup body", body)
const deployment = JSON.parse(body) as DeploymentInfo const deployment = JSON.parse(body) as DeploymentInfo
if (!deployment) { if (!deployment) {
throw new Error(ErrorCodes.UNABLE_TO_PARSE_DEPLOYMENT_INFO) throw new Error(ErrorCodes.UNABLE_TO_PARSE_DEPLOYMENT_INFO)
@@ -72,7 +76,7 @@ async function validateRequest(
throw new Error(ErrorCodes.REQUEST_NOT_FOR_CURRENT_CONTEXT) throw new Error(ErrorCodes.REQUEST_NOT_FOR_CURRENT_CONTEXT)
} }
console.log("[WARMUP] Warmup request", deployment) warmupLogger.info("Warmup request", deployment)
let signature: string let signature: string
try { try {
const headerValue = request.headers.get("x-webhook-signature") const headerValue = request.headers.get("x-webhook-signature")
@@ -81,7 +85,7 @@ async function validateRequest(
} }
signature = headerValue signature = headerValue
} catch (e) { } catch (e) {
console.warn("[WARMUP] Failed to parse signature", e) warmupLogger.warn("Failed to parse signature", e)
throw new Error(ErrorCodes.FAILED_TO_PARSE_SIGNATURE) throw new Error(ErrorCodes.FAILED_TO_PARSE_SIGNATURE)
} }
@@ -99,8 +103,9 @@ async function validateRequest(
} }
export async function performWarmup(context: Context) { export async function performWarmup(context: Context) {
const warmupLogger = createLogger("warmup")
for (const key of warmupKeys) { for (const key of warmupKeys) {
console.log("[WARMUP] Warming up cache", key) warmupLogger.info("Warming up cache", key)
await callWarmup(key, context) await callWarmup(key, context)
// allow api to catch up // allow api to catch up
await timeout(1000) await timeout(1000)
@@ -108,6 +113,7 @@ export async function performWarmup(context: Context) {
} }
async function callWarmup(key: WarmupFunctionsKey, context: Context) { async function callWarmup(key: WarmupFunctionsKey, context: Context) {
const warmupLogger = createLogger("warmup")
const baseUrl = context.url.origin const baseUrl = context.url.origin
const url = new URL("/api/web/warmup", baseUrl) const url = new URL("/api/web/warmup", baseUrl)
@@ -126,13 +132,13 @@ async function callWarmup(key: WarmupFunctionsKey, context: Context) {
}) })
if (!response.ok) { if (!response.ok) {
console.error( warmupLogger.error(
`[WARMUP] Warmup failed '${url.href}' with error: ${response.status}: ${response.statusText}` `Warmup failed '${url.href}' with error: ${response.status}: ${response.statusText}`
) )
} }
} catch (error) { } catch (error) {
console.error( warmupLogger.error(
`[WARMUP] Warmup failed '${url.href}' with error: ${error instanceof Error ? error.message : error}` `Warmup failed '${url.href}' with error: ${error instanceof Error ? error.message : error}`
) )
} }
} }
@@ -143,6 +149,7 @@ export const config: Config = {
} }
async function validateSignature(token: string, buffer: string) { async function validateSignature(token: string, buffer: string) {
const warmupLogger = createLogger("warmup")
try { try {
const secret = const secret =
process.env.WARMUP_SIGNATURE_SECRET || process.env.WARMUP_SIGNATURE_SECRET ||
@@ -160,15 +167,15 @@ async function validateSignature(token: string, buffer: string) {
const hashedBody = crypto.createHash("sha256").update(buffer).digest("hex") const hashedBody = crypto.createHash("sha256").update(buffer).digest("hex")
if (!hasSha256(decoded)) { if (!hasSha256(decoded)) {
console.error( warmupLogger.error(
"[WARMUP] Decoded jwt does not contain sha256, unable to verify signature" "Decoded jwt does not contain sha256, unable to verify signature"
) )
return false return false
} }
return decoded.sha256 === hashedBody return decoded.sha256 === hashedBody
} catch (error) { } catch (error) {
console.error("[WARMUP] Failed to validate signature", error) warmupLogger.error("Failed to validate signature", error)
return false return false
} }
} }

View File

@@ -46,6 +46,7 @@ export default defineConfig([
}, },
rules: { rules: {
"no-console": "warn",
"no-unused-vars": "off", "no-unused-vars": "off",
"react/function-component-definition": "error", "react/function-component-definition": "error",
"import/no-relative-packages": "error", "import/no-relative-packages": "error",

View File

@@ -14,6 +14,7 @@ export function DebugButton() {
const handleClick = () => { const handleClick = () => {
const allRoomAvailability = getAllRoomAvailability(context) const allRoomAvailability = getAllRoomAvailability(context)
const allRoomPackages = getAllRoomPackages(context) const allRoomPackages = getAllRoomPackages(context)
// eslint-disable-next-line no-console
console.log("%c SelectRateContext: ", "background: #AD0015; color: #FFF", { console.log("%c SelectRateContext: ", "background: #AD0015; color: #FFF", {
...context, ...context,
...allRoomAvailability, ...allRoomAvailability,

View File

@@ -214,7 +214,7 @@ export function SelectRateProvider({
}) })
if (selectedRatesPerRoom && selectedRatesPerRoom.length > 1) { if (selectedRatesPerRoom && selectedRatesPerRoom.length > 1) {
console.error(`Multiple selected rates found for room index ${ix}:`) logger.error(`Multiple selected rates found for room index ${ix}:`)
} }
const selectedRate = selectedRatesPerRoom?.at(0) const selectedRate = selectedRatesPerRoom?.at(0)
@@ -234,7 +234,7 @@ export function SelectRateProvider({
const getPriceForRoom = useCallback( const getPriceForRoom = useCallback(
(roomIndex: number): Price | null => { (roomIndex: number): Price | null => {
if (roomIndex < 0 || roomIndex >= selectedRates.length) { if (roomIndex < 0 || roomIndex >= selectedRates.length) {
console.warn("Room index out of bounds:", roomIndex) logger.warn("Room index out of bounds:", roomIndex)
return null return null
} }
@@ -422,7 +422,7 @@ export function SelectRateProvider({
selectPackages: ({ roomIndex, packages }) => { selectPackages: ({ roomIndex, packages }) => {
const updatedRoom = selectRateBooking?.rooms?.[roomIndex] const updatedRoom = selectRateBooking?.rooms?.[roomIndex]
if (!updatedRoom) { if (!updatedRoom) {
console.error("No room found at index", roomIndex) logger.error("No room found at index", roomIndex)
// TODO: What to do here? // TODO: What to do here?
return return
} }
@@ -443,7 +443,7 @@ export function SelectRateProvider({
}) => { }) => {
const updatedRoom = selectRateBooking?.rooms?.[roomIndex] const updatedRoom = selectRateBooking?.rooms?.[roomIndex]
if (!updatedRoom) { if (!updatedRoom) {
console.error("No room found at index", roomIndex) logger.error("No room found at index", roomIndex)
// TODO: What to do here? // TODO: What to do here?
return return
} }

View File

@@ -30,6 +30,7 @@ export default defineConfig([
}, },
rules: { rules: {
"no-console": "warn",
"no-unused-vars": "off", "no-unused-vars": "off",
"import/no-relative-packages": "error", "import/no-relative-packages": "error",
"simple-import-sort/imports": [ "simple-import-sort/imports": [

View File

@@ -47,6 +47,7 @@ export function createLogger(loggerPrefix: string | (() => Promise<string>)) {
`${await getLoggerPrefix()} ${message}`.trim(), `${await getLoggerPrefix()} ${message}`.trim(),
logValue logValue
) )
// eslint-disable-next-line no-console
console[level](`${await getLoggerPrefix()} ${message}`.trim(), ...args) console[level](`${await getLoggerPrefix()} ${message}`.trim(), ...args)
} }

View File

@@ -8,6 +8,7 @@ export const minimumLogLevel = (() => {
).toLowerCase() as (typeof logLevels)[number] ).toLowerCase() as (typeof logLevels)[number]
if (!logLevels.includes(configuredMinimumLogLevel)) { if (!logLevels.includes(configuredMinimumLogLevel)) {
// eslint-disable-next-line no-console
console.warn( console.warn(
`Invalid log level configured: ${configuredMinimumLogLevel}, defaulting to 'info'` `Invalid log level configured: ${configuredMinimumLogLevel}, defaulting to 'info'`
) )

View File

@@ -30,6 +30,7 @@ export default defineConfig([
}, },
rules: { rules: {
"no-console": "warn",
"no-unused-vars": "off", "no-unused-vars": "off",
"import/no-relative-packages": "error", "import/no-relative-packages": "error",
"simple-import-sort/imports": [ "simple-import-sort/imports": [

View File

@@ -30,6 +30,7 @@ export default defineConfig([
}, },
rules: { rules: {
"no-console": "warn",
"no-unused-vars": "off", "no-unused-vars": "off",
"import/no-relative-packages": "error", "import/no-relative-packages": "error",
"simple-import-sort/imports": [ "simple-import-sort/imports": [

View File

@@ -177,7 +177,7 @@ export const enterDetails = safeProtectedServiceProcedure
} }
if (selectedRooms.some((sr) => !sr)) { if (selectedRooms.some((sr) => !sr)) {
console.log("DEBUG: REDIRECTING TO SELECT RATE", selectedRooms) logger.debug("DEBUG: REDIRECTING TO SELECT RATE", selectedRooms)
return selectRateRedirectURL(input, selectedRooms.map(Boolean)) return selectRateRedirectURL(input, selectedRooms.map(Boolean))
} }

View File

@@ -1,3 +1,5 @@
import { logger } from "@scandic-hotels/common/logger"
import type { FacilityEnum } from "@scandic-hotels/common/constants/facilities" import type { FacilityEnum } from "@scandic-hotels/common/constants/facilities"
import type { Lang } from "@scandic-hotels/common/constants/language" import type { Lang } from "@scandic-hotels/common/constants/language"
@@ -140,7 +142,7 @@ function getLocalizedCountryByCountryCode(
const country = new Intl.DisplayNames([lang], { type: "region" }) const country = new Intl.DisplayNames([lang], { type: "region" })
const localizedCountry = country.of(countryCode) const localizedCountry = country.of(countryCode)
if (!localizedCountry) { if (!localizedCountry) {
console.error(`Could not map ${countryCode} to localized country.`) logger.error(`Could not map ${countryCode} to localized country.`)
return null return null
} }