Merged in feature/wrap-logging (pull request #2511)
Feature/wrap logging * feat: change all logging to go through our own logger function so that we can control log levels * move packages/trpc to using our own logger * merge Approved-by: Linus Flood
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { phoneValidator } from "@scandic-hotels/common/utils/zod/phoneValidator"
|
import { phoneValidator } from "@scandic-hotels/common/utils/zod/phoneValidator"
|
||||||
import * as api from "@scandic-hotels/trpc/api"
|
import * as api from "@scandic-hotels/trpc/api"
|
||||||
import { ApiLang } from "@scandic-hotels/trpc/constants/apiLang"
|
import { ApiLang } from "@scandic-hotels/trpc/constants/apiLang"
|
||||||
@@ -47,7 +48,7 @@ export const editProfile = protectedServerActionProcedure
|
|||||||
const intl = await getIntl()
|
const intl = await getIntl()
|
||||||
const payload = editProfilePayload.safeParse(input)
|
const payload = editProfilePayload.safeParse(input)
|
||||||
if (!payload.success) {
|
if (!payload.success) {
|
||||||
console.error(
|
logger.error(
|
||||||
"editProfile payload validation error",
|
"editProfile payload validation error",
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
query: input,
|
query: input,
|
||||||
@@ -70,7 +71,7 @@ export const editProfile = protectedServerActionProcedure
|
|||||||
|
|
||||||
const profile = await getProfile()
|
const profile = await getProfile()
|
||||||
if (!profile || "error" in profile) {
|
if (!profile || "error" in profile) {
|
||||||
console.error(
|
logger.error(
|
||||||
"editProfile profile fetch error",
|
"editProfile profile fetch error",
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
query: input,
|
query: input,
|
||||||
@@ -144,7 +145,7 @@ export const editProfile = protectedServerActionProcedure
|
|||||||
status: Status.success,
|
status: Status.success,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
logger.debug(
|
||||||
`[edit profile: ${profile.membershipNumber}] body keys: ${JSON.stringify(Object.keys(body))}`
|
`[edit profile: ${profile.membershipNumber}] body keys: ${JSON.stringify(Object.keys(body))}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -159,7 +160,7 @@ export const editProfile = protectedServerActionProcedure
|
|||||||
|
|
||||||
if (!apiResponse.ok) {
|
if (!apiResponse.ok) {
|
||||||
const text = await apiResponse.text()
|
const text = await apiResponse.text()
|
||||||
console.error(
|
logger.error(
|
||||||
"editProfile api patch error",
|
"editProfile api patch error",
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
query: input,
|
query: input,
|
||||||
@@ -184,7 +185,7 @@ export const editProfile = protectedServerActionProcedure
|
|||||||
const json = await apiResponse.json()
|
const json = await apiResponse.json()
|
||||||
if (json.errors?.length) {
|
if (json.errors?.length) {
|
||||||
json.errors.forEach((error: any) => {
|
json.errors.forEach((error: any) => {
|
||||||
console.warn(
|
logger.warn(
|
||||||
"editProfile api patch errors (not aborting)",
|
"editProfile api patch errors (not aborting)",
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
query: input,
|
query: input,
|
||||||
@@ -196,7 +197,7 @@ export const editProfile = protectedServerActionProcedure
|
|||||||
|
|
||||||
const validatedData = editProfileSchema.safeParse(json.data.attributes)
|
const validatedData = editProfileSchema.safeParse(json.data.attributes)
|
||||||
if (!validatedData.success) {
|
if (!validatedData.success) {
|
||||||
console.error(
|
logger.error(
|
||||||
"editProfile validation error",
|
"editProfile validation error",
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
query: input,
|
query: input,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { type NextRequest, NextResponse } from "next/server"
|
|||||||
import { AuthError } from "next-auth"
|
import { AuthError } from "next-auth"
|
||||||
|
|
||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
import { internalServerError } from "@/server/errors/next"
|
import { internalServerError } from "@/server/errors/next"
|
||||||
@@ -20,7 +21,7 @@ export async function GET(
|
|||||||
const returnUrl = request.headers.get("x-returnurl")
|
const returnUrl = request.headers.get("x-returnurl")
|
||||||
const isSeamless = request.headers.get("x-logout-source") === "seamless"
|
const isSeamless = request.headers.get("x-logout-source") === "seamless"
|
||||||
|
|
||||||
console.log(
|
logger.debug(
|
||||||
`[logout] source: ${request.headers.get("x-logout-source") || "normal"}`
|
`[logout] source: ${request.headers.get("x-logout-source") || "normal"}`
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ export async function GET(
|
|||||||
if (returnUrl) {
|
if (returnUrl) {
|
||||||
redirectTo = returnUrl
|
redirectTo = returnUrl
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
logger.debug(
|
||||||
`[login] missing returnUrl, using fallback: ${redirectToFallback}`
|
`[login] missing returnUrl, using fallback: ${redirectToFallback}`
|
||||||
)
|
)
|
||||||
redirectTo = redirectToFallback
|
redirectTo = redirectToFallback
|
||||||
@@ -42,9 +43,9 @@ export async function GET(
|
|||||||
|
|
||||||
// Make relative URL to absolute URL
|
// Make relative URL to absolute URL
|
||||||
if (redirectTo.startsWith("/")) {
|
if (redirectTo.startsWith("/")) {
|
||||||
console.log(`[logout] make redirectTo absolute, from ${redirectTo}`)
|
logger.debug(`[logout] make redirectTo absolute, from ${redirectTo}`)
|
||||||
redirectTo = new URL(redirectTo, publicURL).href
|
redirectTo = new URL(redirectTo, publicURL).href
|
||||||
console.log(`[logout] make redirectTo absolute, to ${redirectTo}`)
|
logger.debug(`[logout] make redirectTo absolute, to ${redirectTo}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -72,21 +73,21 @@ export async function GET(
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
const redirectUrl = new URL(redirectUrlValue)
|
const redirectUrl = new URL(redirectUrlValue)
|
||||||
console.log(
|
logger.debug(
|
||||||
`[logout] creating redirect to seamless logout: ${redirectUrl}`
|
`[logout] creating redirect to seamless logout: ${redirectUrl}`
|
||||||
)
|
)
|
||||||
redirectTo = redirectUrl.toString()
|
redirectTo = redirectUrl.toString()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(
|
logger.error(
|
||||||
"Unable to create URL for seamless logout, proceeding without it."
|
"Unable to create URL for seamless logout, proceeding without it.",
|
||||||
|
e
|
||||||
)
|
)
|
||||||
console.error(e)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
redirectTo = `${env.CURITY_ISSUER_USER}/authn/authenticate/logout?redirect_uri=${encodeURIComponent(redirectTo)}`
|
redirectTo = `${env.CURITY_ISSUER_USER}/authn/authenticate/logout?redirect_uri=${encodeURIComponent(redirectTo)}`
|
||||||
console.log(`[logout] final redirectUrl: ${redirectTo}`)
|
logger.debug(`[logout] final redirectUrl: ${redirectTo}`)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Passing `redirect: false` to `signOut` will return a result object
|
* Passing `redirect: false` to `signOut` will return a result object
|
||||||
@@ -99,16 +100,16 @@ export async function GET(
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (redirectUrlObj) {
|
if (redirectUrlObj) {
|
||||||
console.log(`[logout] redirecting to: ${redirectUrlObj.redirect}`)
|
logger.debug(`[logout] redirecting to: ${redirectUrlObj.redirect}`)
|
||||||
return NextResponse.redirect(redirectUrlObj.redirect)
|
return NextResponse.redirect(redirectUrlObj.redirect)
|
||||||
} else {
|
} else {
|
||||||
console.error(`[logout] missing redirectUrlObj reponse from signOut()`)
|
logger.error(`[logout] missing redirectUrlObj reponse from signOut()`)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof AuthError) {
|
if (error instanceof AuthError) {
|
||||||
console.log({ signOutAuthError: error })
|
logger.error("signOutAuthError", { signOutAuthError: error })
|
||||||
} else {
|
} else {
|
||||||
console.log({ signOutError: error })
|
logger.error("signOutError", { signOutError: error })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import * as Sentry from "@sentry/nextjs"
|
|||||||
import { useEffect } from "react"
|
import { useEffect } from "react"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
export default function Error({
|
export default function Error({
|
||||||
error,
|
error,
|
||||||
}: {
|
}: {
|
||||||
@@ -14,7 +16,7 @@ export default function Error({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!error) return
|
if (!error) return
|
||||||
|
|
||||||
console.error({ breadcrumbsError: error })
|
logger.error("Breadcrumbs Error", { breadcrumbsError: error })
|
||||||
Sentry.captureException(error)
|
Sentry.captureException(error)
|
||||||
}, [error])
|
}, [error])
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import * as Sentry from "@sentry/nextjs"
|
|||||||
import { useEffect } from "react"
|
import { useEffect } from "react"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
export default function Error({
|
export default function Error({
|
||||||
error,
|
error,
|
||||||
}: {
|
}: {
|
||||||
@@ -14,7 +16,7 @@ export default function Error({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!error) return
|
if (!error) return
|
||||||
|
|
||||||
console.error(error)
|
logger.error("My Pages", error)
|
||||||
Sentry.captureException(error)
|
Sentry.captureException(error)
|
||||||
}, [error])
|
}, [error])
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import * as Sentry from "@sentry/nextjs"
|
|||||||
import { useEffect } from "react"
|
import { useEffect } from "react"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import { DestinationOverviewPageError } from "@/components/ContentType/DestinationPage/DestinationOverviewPage/error"
|
import { DestinationOverviewPageError } from "@/components/ContentType/DestinationPage/DestinationOverviewPage/error"
|
||||||
|
|
||||||
export default function Error({
|
export default function Error({
|
||||||
@@ -16,7 +18,7 @@ export default function Error({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!error) return
|
if (!error) return
|
||||||
|
|
||||||
console.error(error)
|
logger.error("Destination overview page", error)
|
||||||
Sentry.captureException(error)
|
Sentry.captureException(error)
|
||||||
}, [error])
|
}, [error])
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { NextResponse } from "next/server"
|
import { NextResponse } from "next/server"
|
||||||
import { AuthError } from "next-auth"
|
import { AuthError } from "next-auth"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import { dtmcApiCallback } from "@/constants/routes/dtmc"
|
import { dtmcApiCallback } from "@/constants/routes/dtmc"
|
||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
import { internalServerError, serviceUnavailable } from "@/server/errors/next"
|
import { internalServerError, serviceUnavailable } from "@/server/errors/next"
|
||||||
@@ -21,22 +23,22 @@ export async function GET() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (redirectUrl) {
|
if (redirectUrl) {
|
||||||
console.log(`[dtmc] redirecting to: ${redirectUrl}`)
|
logger.debug(`[dtmc] redirecting to: ${redirectUrl}`)
|
||||||
return NextResponse.redirect(redirectUrl)
|
return NextResponse.redirect(redirectUrl)
|
||||||
} else {
|
} else {
|
||||||
console.error(`[dtmc] missing redirectUrl response from signIn()`)
|
logger.error(`[dtmc] missing redirectUrl response from signIn()`)
|
||||||
return internalServerError(
|
return internalServerError(
|
||||||
"[dtmc] Missing redirect URL from authentication service"
|
"[dtmc] Missing redirect URL from authentication service"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof AuthError) {
|
if (error instanceof AuthError) {
|
||||||
console.error({ signInAuthError: error })
|
logger.error("signInAuthError", { signInAuthError: error })
|
||||||
return serviceUnavailable(
|
return serviceUnavailable(
|
||||||
"[dtmc] Microsoft authentication service unavailable"
|
"[dtmc] Microsoft authentication service unavailable"
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
console.error({ signInError: error })
|
logger.error("signInError", { signInError: error })
|
||||||
return internalServerError(
|
return internalServerError(
|
||||||
"[dtmc] Unexpected error during authentication"
|
"[dtmc] Unexpected error during authentication"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { notFound } from "next/navigation"
|
import { notFound } from "next/navigation"
|
||||||
|
|
||||||
import { myStay } from "@scandic-hotels/common/constants/routes/myStay"
|
import { myStay } from "@scandic-hotels/common/constants/routes/myStay"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCode"
|
import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCode"
|
||||||
|
|
||||||
import { PaymentCallbackStatusEnum } from "@/constants/booking"
|
import { PaymentCallbackStatusEnum } from "@/constants/booking"
|
||||||
@@ -25,7 +26,7 @@ export default async function GuaranteePaymentCallbackPage(
|
|||||||
) {
|
) {
|
||||||
const searchParams = await props.searchParams
|
const searchParams = await props.searchParams
|
||||||
const params = await props.params
|
const params = await props.params
|
||||||
console.log(`[gla-payment-callback] callback started`)
|
logger.debug(`[gla-payment-callback] callback started`)
|
||||||
const lang = params.lang
|
const lang = params.lang
|
||||||
const status = searchParams.status
|
const status = searchParams.status
|
||||||
const confirmationNumber = searchParams.confirmationNumber
|
const confirmationNumber = searchParams.confirmationNumber
|
||||||
@@ -49,7 +50,7 @@ export default async function GuaranteePaymentCallbackPage(
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
console.log(`[gla-payment-callback] redirecting to: ${myStayUrl}`)
|
logger.debug(`[gla-payment-callback] redirecting to: ${myStayUrl}`)
|
||||||
return <TrackGuarantee status={status} redirectUrl={myStayUrl} />
|
return <TrackGuarantee status={status} redirectUrl={myStayUrl} />
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +77,7 @@ export default async function GuaranteePaymentCallbackPage(
|
|||||||
: BookingErrorCodeEnum.TransactionFailed
|
: BookingErrorCodeEnum.TransactionFailed
|
||||||
)
|
)
|
||||||
} catch {
|
} catch {
|
||||||
console.error(
|
logger.error(
|
||||||
`[gla-payment-callback] failed to get booking status for ${confirmationNumber}, status: ${status}`
|
`[gla-payment-callback] failed to get booking status for ${confirmationNumber}, status: ${status}`
|
||||||
)
|
)
|
||||||
if (status === PaymentCallbackStatusEnum.Cancel) {
|
if (status === PaymentCallbackStatusEnum.Cancel) {
|
||||||
@@ -86,7 +87,10 @@ export default async function GuaranteePaymentCallbackPage(
|
|||||||
errorMessage = `Failed to get booking status for ${confirmationNumber}, status: ${status}`
|
errorMessage = `Failed to get booking status for ${confirmationNumber}, status: ${status}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(errorMessage)
|
|
||||||
|
if (errorMessage) {
|
||||||
|
logger.error(errorMessage)
|
||||||
|
}
|
||||||
|
|
||||||
if (isAncillaryFlow) {
|
if (isAncillaryFlow) {
|
||||||
searchObject.set("ancillary", "ancillary")
|
searchObject.set("ancillary", "ancillary")
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { notFound } from "next/navigation"
|
import { notFound } from "next/navigation"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { getServiceToken } from "@scandic-hotels/common/tokenManager"
|
import { getServiceToken } from "@scandic-hotels/common/tokenManager"
|
||||||
import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCode"
|
import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCode"
|
||||||
import { getBooking } from "@scandic-hotels/trpc/routers/booking/utils"
|
import { getBooking } from "@scandic-hotels/trpc/routers/booking/utils"
|
||||||
@@ -31,13 +32,13 @@ export default async function PaymentCallbackPage(
|
|||||||
) {
|
) {
|
||||||
const searchParams = await props.searchParams
|
const searchParams = await props.searchParams
|
||||||
const params = await props.params
|
const params = await props.params
|
||||||
console.log(`[payment-callback] callback started`)
|
logger.debug(`[payment-callback] callback started`)
|
||||||
const lang = params.lang
|
const lang = params.lang
|
||||||
const status = searchParams.status
|
const status = searchParams.status
|
||||||
const confirmationNumber = searchParams.confirmationNumber
|
const confirmationNumber = searchParams.confirmationNumber
|
||||||
|
|
||||||
if (!status || !confirmationNumber) {
|
if (!status || !confirmationNumber) {
|
||||||
console.error(
|
logger.error(
|
||||||
`[payment-callback] missing status or confirmationNumber in search params`
|
`[payment-callback] missing status or confirmationNumber in search params`
|
||||||
)
|
)
|
||||||
notFound()
|
notFound()
|
||||||
@@ -71,7 +72,7 @@ export default async function PaymentCallbackPage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
console.error(
|
logger.error(
|
||||||
`[payment-callback] no token found for user, cannot fetch booking`
|
`[payment-callback] no token found for user, cannot fetch booking`
|
||||||
)
|
)
|
||||||
notFound()
|
notFound()
|
||||||
@@ -89,7 +90,7 @@ export default async function PaymentCallbackPage(
|
|||||||
const expire = Math.floor(Date.now() / 1000) + 60
|
const expire = Math.floor(Date.now() / 1000) + 60
|
||||||
const sig = encrypt(expire.toString())
|
const sig = encrypt(expire.toString())
|
||||||
const confirmationUrl = `${bookingConfirmation(lang)}?RefId=${encodeURIComponent(refId)}`
|
const confirmationUrl = `${bookingConfirmation(lang)}?RefId=${encodeURIComponent(refId)}`
|
||||||
console.log(
|
logger.debug(
|
||||||
`[payment-callback] rendering success callback with confirmation number: ${confirmationNumber}`
|
`[payment-callback] rendering success callback with confirmation number: ${confirmationNumber}`
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -126,7 +127,7 @@ export default async function PaymentCallbackPage(
|
|||||||
: BookingErrorCodeEnum.TransactionFailed
|
: BookingErrorCodeEnum.TransactionFailed
|
||||||
)
|
)
|
||||||
} catch {
|
} catch {
|
||||||
console.error(
|
logger.error(
|
||||||
`[payment-callback] failed to get booking status for ${confirmationNumber}, status: ${status}`
|
`[payment-callback] failed to get booking status for ${confirmationNumber}, status: ${status}`
|
||||||
)
|
)
|
||||||
searchObject.set("errorCode", BookingErrorCodeEnum.TransactionFailed)
|
searchObject.set("errorCode", BookingErrorCodeEnum.TransactionFailed)
|
||||||
@@ -135,7 +136,7 @@ export default async function PaymentCallbackPage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status === PaymentCallbackStatusEnum.Error) {
|
if (status === PaymentCallbackStatusEnum.Error) {
|
||||||
console.error(
|
logger.error(
|
||||||
`[payment-callback] error status received for ${confirmationNumber}, status: ${status}`
|
`[payment-callback] error status received for ${confirmationNumber}, status: ${status}`
|
||||||
)
|
)
|
||||||
searchObject.set("errorCode", BookingErrorCodeEnum.TransactionFailed)
|
searchObject.set("errorCode", BookingErrorCodeEnum.TransactionFailed)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { type NextRequest, NextResponse } from "next/server"
|
|||||||
import { AuthError } from "next-auth"
|
import { AuthError } from "next-auth"
|
||||||
|
|
||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
import { internalServerError } from "@/server/errors/next"
|
import { internalServerError } from "@/server/errors/next"
|
||||||
@@ -25,7 +26,7 @@ export async function GET(
|
|||||||
const isSeamlessMagicLink =
|
const isSeamlessMagicLink =
|
||||||
request.headers.get("x-login-source") === "seamless-magiclink"
|
request.headers.get("x-login-source") === "seamless-magiclink"
|
||||||
|
|
||||||
console.log(
|
logger.debug(
|
||||||
`[login] source: ${request.headers.get("x-login-source") || "normal"}`
|
`[login] source: ${request.headers.get("x-login-source") || "normal"}`
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -34,8 +35,8 @@ export async function GET(
|
|||||||
request.nextUrl.searchParams.get("redirectTo")
|
request.nextUrl.searchParams.get("redirectTo")
|
||||||
const redirectToFallback = "/"
|
const redirectToFallback = "/"
|
||||||
|
|
||||||
console.log(`[login] redirectTo cookie value: ${redirectToCookieValue}`)
|
logger.debug(`[login] redirectTo cookie value: ${redirectToCookieValue}`)
|
||||||
console.log(
|
logger.debug(
|
||||||
`[login] redirectTo search param value: ${redirectToSearchParamValue}`
|
`[login] redirectTo search param value: ${redirectToSearchParamValue}`
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@ export async function GET(
|
|||||||
if (returnUrl) {
|
if (returnUrl) {
|
||||||
redirectTo = returnUrl
|
redirectTo = returnUrl
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
logger.debug(
|
||||||
`[login] missing returnUrl, using fallback: ${redirectToFallback}`
|
`[login] missing returnUrl, using fallback: ${redirectToFallback}`
|
||||||
)
|
)
|
||||||
redirectTo = redirectToFallback
|
redirectTo = redirectToFallback
|
||||||
@@ -54,9 +55,9 @@ export async function GET(
|
|||||||
|
|
||||||
// Make relative URL to absolute URL
|
// Make relative URL to absolute URL
|
||||||
if (redirectTo.startsWith("/")) {
|
if (redirectTo.startsWith("/")) {
|
||||||
console.log(`[login] make redirectTo absolute, from ${redirectTo}`)
|
logger.debug(`[login] make redirectTo absolute, from ${redirectTo}`)
|
||||||
redirectTo = new URL(redirectTo, publicURL).href
|
redirectTo = new URL(redirectTo, publicURL).href
|
||||||
console.log(`[login] make redirectTo absolute, to ${redirectTo}`)
|
logger.debug(`[login] make redirectTo absolute, to ${redirectTo}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up cookie from authRequired middleware
|
// Clean up cookie from authRequired middleware
|
||||||
@@ -90,9 +91,11 @@ export async function GET(
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
const redirectUrl = new URL(redirectUrlValue)
|
const redirectUrl = new URL(redirectUrlValue)
|
||||||
console.log(`[login] creating redirect to seamless login: ${redirectUrl}`)
|
logger.debug(
|
||||||
|
`[login] creating redirect to seamless login: ${redirectUrl}`
|
||||||
|
)
|
||||||
redirectUrl.searchParams.set("returnurl", redirectTo)
|
redirectUrl.searchParams.set("returnurl", redirectTo)
|
||||||
console.log(
|
logger.debug(
|
||||||
`[login] returnurl for seamless login: ${redirectUrl.searchParams.get("returnurl")}`
|
`[login] returnurl for seamless login: ${redirectUrl.searchParams.get("returnurl")}`
|
||||||
)
|
)
|
||||||
redirectTo = redirectUrl.toString()
|
redirectTo = redirectUrl.toString()
|
||||||
@@ -105,7 +108,7 @@ export async function GET(
|
|||||||
"; Max-Age=300; Path=/; HttpOnly; SameSite=Lax"
|
"; Max-Age=300; Path=/; HttpOnly; SameSite=Lax"
|
||||||
)
|
)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(
|
logger.error(
|
||||||
"[login] unable to create URL for seamless login, proceeding without it.",
|
"[login] unable to create URL for seamless login, proceeding without it.",
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
@@ -113,7 +116,7 @@ export async function GET(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log(`[login] final redirectUrl: ${redirectTo}`)
|
logger.debug(`[login] final redirectUrl: ${redirectTo}`)
|
||||||
|
|
||||||
/** Record<string, any> is next-auth typings */
|
/** Record<string, any> is next-auth typings */
|
||||||
const params: Record<string, any> = {
|
const params: Record<string, any> = {
|
||||||
@@ -174,16 +177,16 @@ export async function GET(
|
|||||||
const redirectOpts = {
|
const redirectOpts = {
|
||||||
headers: redirectHeaders,
|
headers: redirectHeaders,
|
||||||
}
|
}
|
||||||
console.log(`[login] redirecting to: ${redirectUrl}`, redirectOpts)
|
logger.debug(`[login] redirecting to: ${redirectUrl}`, redirectOpts)
|
||||||
return NextResponse.redirect(redirectUrl, redirectOpts)
|
return NextResponse.redirect(redirectUrl, redirectOpts)
|
||||||
} else {
|
} else {
|
||||||
console.error(`[login] missing redirectUrl reponse from signIn()`)
|
logger.error(`[login] missing redirectUrl reponse from signIn()`)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof AuthError) {
|
if (error instanceof AuthError) {
|
||||||
console.error({ signInAuthError: error })
|
logger.error("signInAuthError", { signInAuthError: error })
|
||||||
} else {
|
} else {
|
||||||
console.error({ signInError: error })
|
logger.error("signInError", { signInError: error })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { type NextRequest, NextResponse } from "next/server"
|
import { type NextRequest, NextResponse } from "next/server"
|
||||||
import { AuthError } from "next-auth"
|
import { AuthError } from "next-auth"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import { badRequest, internalServerError } from "@/server/errors/next"
|
import { badRequest, internalServerError } from "@/server/errors/next"
|
||||||
import { getPublicURL } from "@/server/utils"
|
import { getPublicURL } from "@/server/utils"
|
||||||
|
|
||||||
@@ -16,7 +18,7 @@ export async function GET(
|
|||||||
|
|
||||||
const loginKey = request.nextUrl.searchParams.get("loginKey")
|
const loginKey = request.nextUrl.searchParams.get("loginKey")
|
||||||
if (!loginKey) {
|
if (!loginKey) {
|
||||||
console.log(
|
logger.debug(
|
||||||
`[verifymagiclink] missing required loginKey, aborting bad request`
|
`[verifymagiclink] missing required loginKey, aborting bad request`
|
||||||
)
|
)
|
||||||
return badRequest()
|
return badRequest()
|
||||||
@@ -24,14 +26,14 @@ export async function GET(
|
|||||||
|
|
||||||
let redirectTo: string
|
let redirectTo: string
|
||||||
|
|
||||||
console.log(`[verifymagiclink] verifying callback`)
|
logger.debug(`[verifymagiclink] verifying callback`)
|
||||||
|
|
||||||
const redirectToCookieValue = request.cookies.get(
|
const redirectToCookieValue = request.cookies.get(
|
||||||
"magicLinkRedirectTo"
|
"magicLinkRedirectTo"
|
||||||
)?.value // Set redirect url from the magicLinkRedirect Cookie which is set when intiating login
|
)?.value // Set redirect url from the magicLinkRedirect Cookie which is set when intiating login
|
||||||
const redirectToFallback = "/"
|
const redirectToFallback = "/"
|
||||||
|
|
||||||
console.log(
|
logger.debug(
|
||||||
`[verifymagiclink] magicLinkRedirectTo cookie value: ${redirectToCookieValue}`
|
`[verifymagiclink] magicLinkRedirectTo cookie value: ${redirectToCookieValue}`
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -39,11 +41,11 @@ export async function GET(
|
|||||||
|
|
||||||
// Make relative URL to absolute URL
|
// Make relative URL to absolute URL
|
||||||
if (redirectTo.startsWith("/")) {
|
if (redirectTo.startsWith("/")) {
|
||||||
console.log(
|
logger.debug(
|
||||||
`[verifymagiclink] make redirectTo absolute, from ${redirectTo}`
|
`[verifymagiclink] make redirectTo absolute, from ${redirectTo}`
|
||||||
)
|
)
|
||||||
redirectTo = new URL(redirectTo, publicURL).href
|
redirectTo = new URL(redirectTo, publicURL).href
|
||||||
console.log(`[verifymagiclink] make redirectTo absolute, to ${redirectTo}`)
|
logger.debug(`[verifymagiclink] make redirectTo absolute, to ${redirectTo}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update Seamless login url as Magic link login has a different authenticator in Curity
|
// Update Seamless login url as Magic link login has a different authenticator in Curity
|
||||||
@@ -59,7 +61,7 @@ export async function GET(
|
|||||||
)
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log(`[verifymagiclink] final redirectUrl: ${redirectTo}`)
|
logger.debug(`[verifymagiclink] final redirectUrl: ${redirectTo}`)
|
||||||
|
|
||||||
const params = await context.params
|
const params = await context.params
|
||||||
/**
|
/**
|
||||||
@@ -92,18 +94,18 @@ export async function GET(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (redirectUrl) {
|
if (redirectUrl) {
|
||||||
console.log(`[verifymagiclink] redirecting to: ${redirectUrl}`)
|
logger.debug(`[verifymagiclink] redirecting to: ${redirectUrl}`)
|
||||||
return NextResponse.redirect(redirectUrl)
|
return NextResponse.redirect(redirectUrl)
|
||||||
} else {
|
} else {
|
||||||
console.error(
|
logger.error(
|
||||||
`[verifymagiclink] missing redirectUrl reponse from signIn()`
|
`[verifymagiclink] missing redirectUrl reponse from signIn()`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof AuthError) {
|
if (error instanceof AuthError) {
|
||||||
console.error({ signInAuthError: error })
|
logger.error("signInAuthError", { signInAuthError: error })
|
||||||
} else {
|
} else {
|
||||||
console.error({ signInError: error })
|
logger.error("signInError", { signInError: error })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { useParams, useRouter, useSearchParams } from "next/navigation"
|
|||||||
import { startTransition, useEffect, useRef } from "react"
|
import { startTransition, useEffect, useRef } from "react"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { SESSION_EXPIRED } from "@scandic-hotels/trpc/errors"
|
import { SESSION_EXPIRED } from "@scandic-hotels/trpc/errors"
|
||||||
|
|
||||||
import { login } from "@/constants/routes/handleAuth"
|
import { login } from "@/constants/routes/handleAuth"
|
||||||
@@ -31,14 +32,13 @@ export default function Error({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!error) return
|
if (!error) return
|
||||||
|
|
||||||
console.error(error)
|
|
||||||
|
|
||||||
if (error.message === SESSION_EXPIRED) {
|
if (error.message === SESSION_EXPIRED) {
|
||||||
const loginUrl = login[params.lang]
|
const loginUrl = login[params.lang]
|
||||||
window.location.assign(loginUrl)
|
window.location.assign(loginUrl)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.error("(live)/error", error)
|
||||||
Sentry.captureException(error)
|
Sentry.captureException(error)
|
||||||
}, [error, params.lang])
|
}, [error, params.lang])
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
import * as Sentry from "@sentry/nextjs"
|
import * as Sentry from "@sentry/nextjs"
|
||||||
import { useEffect } from "react"
|
import { useEffect } from "react"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
export default function Error({
|
export default function Error({
|
||||||
error,
|
error,
|
||||||
}: {
|
}: {
|
||||||
@@ -11,7 +13,7 @@ export default function Error({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!error) return
|
if (!error) return
|
||||||
|
|
||||||
console.error(error)
|
logger.error("header", error)
|
||||||
Sentry.captureException(error)
|
Sentry.captureException(error)
|
||||||
}, [error])
|
}, [error])
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { notFound } from "next/navigation"
|
import { notFound } from "next/navigation"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { GetCurrentBlockPage } from "@scandic-hotels/trpc/graphql/Query/Current/CurrentBlockPage.graphql"
|
import { GetCurrentBlockPage } from "@scandic-hotels/trpc/graphql/Query/Current/CurrentBlockPage.graphql"
|
||||||
import { GetCurrentBlockPageTrackingData } from "@scandic-hotels/trpc/graphql/Query/Current/CurrentBlockPageTrackingData.graphql"
|
import { GetCurrentBlockPageTrackingData } from "@scandic-hotels/trpc/graphql/Query/Current/CurrentBlockPageTrackingData.graphql"
|
||||||
import { request } from "@scandic-hotels/trpc/graphql/request"
|
import { request } from "@scandic-hotels/trpc/graphql/request"
|
||||||
@@ -34,9 +35,12 @@ export default async function CurrentContentPage(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (!response.data?.all_current_blocks_page?.total) {
|
if (!response.data?.all_current_blocks_page?.total) {
|
||||||
console.log("#### DATA ####")
|
logger.debug(
|
||||||
console.log(response.data)
|
"#### DATA ####",
|
||||||
console.log("SearchParams URI: ", searchParams.uri)
|
response.data,
|
||||||
|
"SearchParams URI: ",
|
||||||
|
searchParams.uri
|
||||||
|
)
|
||||||
throw new Error("Not found")
|
throw new Error("Not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { cookies } from "next/headers"
|
|||||||
import { redirect } from "next/navigation"
|
import { redirect } from "next/navigation"
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { safeTry } from "@scandic-hotels/common/utils/safeTry"
|
import { safeTry } from "@scandic-hotels/common/utils/safeTry"
|
||||||
import { SAS_TOKEN_STORAGE_KEY } from "@scandic-hotels/trpc/constants/partnerSAS"
|
import { SAS_TOKEN_STORAGE_KEY } from "@scandic-hotels/trpc/constants/partnerSAS"
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ export async function GET(
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
console.error("[SAS] Invalid search params", result.error)
|
logger.error("[SAS] Invalid search params", result.error)
|
||||||
redirect(`/${lang}/sas-x-scandic/error?errorCode=invalid_query`)
|
redirect(`/${lang}/sas-x-scandic/error?errorCode=invalid_query`)
|
||||||
}
|
}
|
||||||
const { code, state } = result.data
|
const { code, state } = result.data
|
||||||
@@ -62,7 +63,7 @@ export async function GET(
|
|||||||
|
|
||||||
if (!tokenResponse.ok) {
|
if (!tokenResponse.ok) {
|
||||||
const error = await tokenResponse.text()
|
const error = await tokenResponse.text()
|
||||||
console.error("[SAS] Failed to get token", error)
|
logger.error("[SAS] Failed to get token", error)
|
||||||
redirect(`/${lang}/sas-x-scandic/error?errorCode=token_error`)
|
redirect(`/${lang}/sas-x-scandic/error?errorCode=token_error`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +91,7 @@ export async function GET(
|
|||||||
const caller = await serverClient()
|
const caller = await serverClient()
|
||||||
const [data, error] = await safeTry(caller.partner.sas.requestOtp())
|
const [data, error] = await safeTry(caller.partner.sas.requestOtp())
|
||||||
if (!data || error) {
|
if (!data || error) {
|
||||||
console.error("[SAS] Failed to request OTP", error)
|
logger.error("[SAS] Failed to request OTP", error)
|
||||||
redirect(`/${lang}/sas-x-scandic/error`)
|
redirect(`/${lang}/sas-x-scandic/error`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +108,7 @@ export async function GET(
|
|||||||
throw new Error(`Unhandled request OTP status ${data.status}`)
|
throw new Error(`Unhandled request OTP status ${data.status}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("[SAS] Request OTP response", data)
|
logger.debug("[SAS] Request OTP response", data)
|
||||||
|
|
||||||
const otpUrl = new URL(
|
const otpUrl = new URL(
|
||||||
`/${lang}/sas-x-scandic/otp`,
|
`/${lang}/sas-x-scandic/otp`,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import * as Sentry from "@sentry/nextjs"
|
|||||||
import { useEffect } from "react"
|
import { useEffect } from "react"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
import { GenericError } from "./components/GenericError"
|
import { GenericError } from "./components/GenericError"
|
||||||
@@ -19,7 +20,7 @@ export default function Error({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!error) return
|
if (!error) return
|
||||||
|
|
||||||
console.error(error)
|
logger.error("sas-x-scandic", error)
|
||||||
Sentry.captureException(error)
|
Sentry.captureException(error)
|
||||||
}, [error])
|
}, [error])
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { redirect } from "next/navigation"
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
import { myPages } from "@scandic-hotels/common/constants/routes/myPages"
|
import { myPages } from "@scandic-hotels/common/constants/routes/myPages"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { safeTry } from "@scandic-hotels/common/utils/safeTry"
|
import { safeTry } from "@scandic-hotels/common/utils/safeTry"
|
||||||
import {
|
import {
|
||||||
SAS_TOKEN_STORAGE_KEY,
|
SAS_TOKEN_STORAGE_KEY,
|
||||||
@@ -173,7 +174,7 @@ async function handleLinkAccount({
|
|||||||
const caller = await serverClient()
|
const caller = await serverClient()
|
||||||
const [res, error] = await safeTry(caller.partner.sas.linkAccount())
|
const [res, error] = await safeTry(caller.partner.sas.linkAccount())
|
||||||
if (!res || error) {
|
if (!res || error) {
|
||||||
console.error("[SAS] link account error", error)
|
logger.error("[SAS] link account error", error)
|
||||||
return {
|
return {
|
||||||
url: `/${lang}/sas-x-scandic/error`,
|
url: `/${lang}/sas-x-scandic/error`,
|
||||||
}
|
}
|
||||||
@@ -216,7 +217,7 @@ async function handleUnlinkAccount({
|
|||||||
const caller = await serverClient()
|
const caller = await serverClient()
|
||||||
const [res, error] = await safeTry(caller.partner.sas.unlinkAccount())
|
const [res, error] = await safeTry(caller.partner.sas.unlinkAccount())
|
||||||
if (!res || error) {
|
if (!res || error) {
|
||||||
console.error("[SAS] unlink account error", error)
|
logger.error("[SAS] unlink account error", error)
|
||||||
return {
|
return {
|
||||||
url: `/${lang}/sas-x-scandic/error`,
|
url: `/${lang}/sas-x-scandic/error`,
|
||||||
}
|
}
|
||||||
@@ -266,7 +267,7 @@ async function handleTransferPoints({
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (!res || error || res.transferState === "error") {
|
if (!res || error || res.transferState === "error") {
|
||||||
console.error("[SAS] transfer points error", error)
|
logger.error("[SAS] transfer points error", error)
|
||||||
return {
|
return {
|
||||||
url: `/${lang}/sas-x-scandic/error`,
|
url: `/${lang}/sas-x-scandic/error`,
|
||||||
type: "replace",
|
type: "replace",
|
||||||
@@ -274,14 +275,14 @@ async function handleTransferPoints({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (res.transferState === "notLinked") {
|
if (res.transferState === "notLinked") {
|
||||||
console.warn("[SAS] transfer points not linked")
|
logger.warn("[SAS] transfer points not linked")
|
||||||
return {
|
return {
|
||||||
url: `/${lang}/sas-x-scandic/link`,
|
url: `/${lang}/sas-x-scandic/link`,
|
||||||
type: "replace",
|
type: "replace",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("[SAS] transfer points response", res)
|
logger.debug("[SAS] transfer points response", res)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
url: `/${lang}/sas-x-scandic/transfer/success?p=${points}`,
|
url: `/${lang}/sas-x-scandic/transfer/success?p=${points}`,
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { notFound } from "next/navigation"
|
import { notFound } from "next/navigation"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import AccountPage from "@/components/Webviews/AccountPage"
|
import AccountPage from "@/components/Webviews/AccountPage"
|
||||||
import LoyaltyPage from "@/components/Webviews/LoyaltyPage"
|
import LoyaltyPage from "@/components/Webviews/LoyaltyPage"
|
||||||
|
|
||||||
@@ -22,7 +24,7 @@ export default async function ContentTypePage(
|
|||||||
return <AccountPage />
|
return <AccountPage />
|
||||||
default:
|
default:
|
||||||
const type: never = params.contentType
|
const type: never = params.contentType
|
||||||
console.error(`Unsupported content type given: ${type}`)
|
logger.error(`Unsupported content type given: ${type}`)
|
||||||
notFound()
|
notFound()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
import * as Sentry from "@sentry/nextjs"
|
||||||
import { headers } from "next/headers"
|
import { headers } from "next/headers"
|
||||||
import { redirect } from "next/navigation"
|
import { redirect } from "next/navigation"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import { getProfile } from "@/lib/trpc/memoizedRequests"
|
import { getProfile } from "@/lib/trpc/memoizedRequests"
|
||||||
|
|
||||||
import { getIntl } from "@/i18n"
|
import { getIntl } from "@/i18n"
|
||||||
@@ -17,7 +20,7 @@ export default async function Layout(
|
|||||||
const user = await getProfile()
|
const user = await getProfile()
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
console.log(`[webview:page] unable to load user`)
|
logger.debug(`[webview:page] unable to load user`)
|
||||||
return (
|
return (
|
||||||
<p>
|
<p>
|
||||||
{intl.formatMessage({
|
{intl.formatMessage({
|
||||||
@@ -35,7 +38,9 @@ export default async function Layout(
|
|||||||
const headersList = await headers()
|
const headersList = await headers()
|
||||||
const returnURL = `/${params.lang}/webview${headersList.get("x-pathname")!}`
|
const returnURL = `/${params.lang}/webview${headersList.get("x-pathname")!}`
|
||||||
const redirectURL = `/${params.lang}/webview/refresh?returnUrl=${encodeURIComponent(returnURL)}`
|
const redirectURL = `/${params.lang}/webview/refresh?returnUrl=${encodeURIComponent(returnURL)}`
|
||||||
console.log(`[webview:page] user error, redirecting to: ${redirectURL}`)
|
logger.debug(
|
||||||
|
`[webview:page] user error, redirecting to: ${redirectURL}`
|
||||||
|
)
|
||||||
redirect(redirectURL)
|
redirect(redirectURL)
|
||||||
case "notfound":
|
case "notfound":
|
||||||
return (
|
return (
|
||||||
@@ -55,7 +60,8 @@ export default async function Layout(
|
|||||||
)
|
)
|
||||||
default:
|
default:
|
||||||
const u: never = user
|
const u: never = user
|
||||||
console.log("[webview:page] unhandled user loading error", u)
|
logger.error("[webview:page] unhandled user loading error", u)
|
||||||
|
Sentry.captureMessage("[webview:page] unhandled user loading error", u)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { notFound } from "next/navigation"
|
import { notFound } from "next/navigation"
|
||||||
import { NextResponse } from "next/server"
|
import { NextResponse } from "next/server"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
|
|
||||||
import { auth } from "@/auth"
|
import { auth } from "@/auth"
|
||||||
@@ -11,6 +13,6 @@ export const GET = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const user = await auth()
|
const user = await auth()
|
||||||
console.log("[DEBUG] access-token", user?.token)
|
logger.debug("[DEBUG] access-token", user?.token)
|
||||||
return NextResponse.json(user)
|
return NextResponse.json(user)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { type NextRequest, NextResponse } from "next/server"
|
import { type NextRequest, NextResponse } from "next/server"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { languageSchema } from "@scandic-hotels/common/utils/languages"
|
import { languageSchema } from "@scandic-hotels/common/utils/languages"
|
||||||
|
|
||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
@@ -9,7 +10,7 @@ export const dynamic = "force-dynamic"
|
|||||||
|
|
||||||
export async function GET(request: NextRequest) {
|
export async function GET(request: NextRequest) {
|
||||||
if (!env.ENABLE_WARMUP_HOTEL) {
|
if (!env.ENABLE_WARMUP_HOTEL) {
|
||||||
console.log("[WARMUP] Warmup hotel data is disabled")
|
logger.info("[WARMUP] Warmup hotel data is disabled")
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ message: "Warmup hotel data is disabled" },
|
{ message: "Warmup hotel data is disabled" },
|
||||||
{ status: 200 }
|
{ status: 200 }
|
||||||
@@ -32,7 +33,7 @@ export async function GET(request: NextRequest) {
|
|||||||
})
|
})
|
||||||
return NextResponse.json(hotels)
|
return NextResponse.json(hotels)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[WARMUP] error", error)
|
logger.error("[WARMUP] error", error)
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{
|
{
|
||||||
error: "Failed to fetch all hotels",
|
error: "Failed to fetch all hotels",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
import { profile } from "@scandic-hotels/common/constants/routes/myPages"
|
import { profile } from "@scandic-hotels/common/constants/routes/myPages"
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
|
|
||||||
import { serverClient } from "@/lib/trpc/server"
|
import { serverClient } from "@/lib/trpc/server"
|
||||||
import { getPublicURL } from "@/server/utils"
|
import { getPublicURL } from "@/server/utils"
|
||||||
@@ -10,10 +11,12 @@ export async function GET(
|
|||||||
request: NextRequest,
|
request: NextRequest,
|
||||||
props: { params: Promise<{ lang: string }> }
|
props: { params: Promise<{ lang: string }> }
|
||||||
) {
|
) {
|
||||||
|
const addCardLogger = createLogger("add-card")
|
||||||
|
|
||||||
const params = await props.params
|
const params = await props.params
|
||||||
const publicURL = getPublicURL(request)
|
const publicURL = getPublicURL(request)
|
||||||
|
|
||||||
console.log(`[add-card] callback started`)
|
addCardLogger.debug(`[add-card] callback started`)
|
||||||
const lang = params.lang as Lang
|
const lang = params.lang as Lang
|
||||||
const returnUrl = new URL(`${publicURL}/${profile[lang ?? Lang.en]}`)
|
const returnUrl = new URL(`${publicURL}/${profile[lang ?? Lang.en]}`)
|
||||||
|
|
||||||
@@ -32,28 +35,28 @@ export async function GET(
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (saveCardSuccess) {
|
if (saveCardSuccess) {
|
||||||
console.log(`[add-card] planet success: card saved success`)
|
addCardLogger.debug(`[add-card] planet success: card saved success`)
|
||||||
returnUrl.searchParams.set("success", "true")
|
returnUrl.searchParams.set("success", "true")
|
||||||
} else {
|
} else {
|
||||||
console.log(`[add-card] planet success: card saved fail`)
|
addCardLogger.debug(`[add-card] planet success: card saved fail`)
|
||||||
returnUrl.searchParams.set("failure", "true")
|
returnUrl.searchParams.set("failure", "true")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log(`[add-card] planet success: missing datatransTrxId`)
|
addCardLogger.debug(`[add-card] planet success: missing datatransTrxId`)
|
||||||
returnUrl.searchParams.set("error", "true")
|
returnUrl.searchParams.set("error", "true")
|
||||||
}
|
}
|
||||||
} else if (failure) {
|
} else if (failure) {
|
||||||
console.log(`[add-card] planet fail`)
|
addCardLogger.debug(`[add-card] planet fail`)
|
||||||
returnUrl.searchParams.set("failure", "true")
|
returnUrl.searchParams.set("failure", "true")
|
||||||
} else if (cancel) {
|
} else if (cancel) {
|
||||||
console.log(`[add-card] planet cancel`)
|
addCardLogger.debug(`[add-card] planet cancel`)
|
||||||
returnUrl.searchParams.set("cancel", "true")
|
returnUrl.searchParams.set("cancel", "true")
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`[add-card] error saving credit card`, e)
|
addCardLogger.error(`[add-card] error saving credit card`, e)
|
||||||
returnUrl.searchParams.set("error", "true")
|
returnUrl.searchParams.set("error", "true")
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[add-card] redirecting to: ${returnUrl}`)
|
addCardLogger.debug(`[add-card] redirecting to: ${returnUrl}`)
|
||||||
return Response.redirect(returnUrl)
|
return Response.redirect(returnUrl)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { type NextRequest, NextResponse } from "next/server"
|
import { type NextRequest, NextResponse } from "next/server"
|
||||||
|
|
||||||
import { overview } from "@scandic-hotels/common/constants/routes/myPages"
|
import { overview } from "@scandic-hotels/common/constants/routes/myPages"
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
import * as api from "@scandic-hotels/trpc/api"
|
import * as api from "@scandic-hotels/trpc/api"
|
||||||
import { isValidSession } from "@scandic-hotels/trpc/utils/session"
|
import { isValidSession } from "@scandic-hotels/trpc/utils/session"
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ import { auth } from "@/auth"
|
|||||||
import { auth as dtmcAuth } from "@/auth.dtmc"
|
import { auth as dtmcAuth } from "@/auth.dtmc"
|
||||||
import { getLang } from "@/i18n/serverContext"
|
import { getLang } from "@/i18n/serverContext"
|
||||||
|
|
||||||
|
const dtmcLogger = createLogger("dtmc")
|
||||||
interface LinkEmployeeSuccessResult {
|
interface LinkEmployeeSuccessResult {
|
||||||
success: true
|
success: true
|
||||||
}
|
}
|
||||||
@@ -32,7 +34,7 @@ async function linkEmployeeToUser(
|
|||||||
employeeId: string,
|
employeeId: string,
|
||||||
accessToken: string
|
accessToken: string
|
||||||
): Promise<LinkEmployeeResult> {
|
): Promise<LinkEmployeeResult> {
|
||||||
console.log(`[dtmc] Linking employee ID ${employeeId}`)
|
dtmcLogger.debug(`Linking employee ID ${employeeId}`)
|
||||||
let response: Response
|
let response: Response
|
||||||
try {
|
try {
|
||||||
response = await api.post(
|
response = await api.post(
|
||||||
@@ -45,7 +47,7 @@ async function linkEmployeeToUser(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
} catch (networkError) {
|
} catch (networkError) {
|
||||||
console.error("[dtmc] Network error during API request:", networkError)
|
dtmcLogger.error("Network error during API request:", networkError)
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
statusCode: 0,
|
statusCode: 0,
|
||||||
@@ -53,17 +55,17 @@ async function linkEmployeeToUser(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
console.error(`[dtmc] API returned error status ${response.status}`)
|
dtmcLogger.error(`API returned error status ${response.status}`)
|
||||||
try {
|
try {
|
||||||
const errorResponse = await response.json()
|
const errorResponse = await response.json()
|
||||||
console.error(`[dtmc] API error response:`, errorResponse)
|
dtmcLogger.error(`API error response:`, errorResponse)
|
||||||
} catch (parseError) {
|
} catch (parseError) {
|
||||||
console.warn(`[dtmc] Could not parse API error response:`, parseError)
|
dtmcLogger.warn(`Could not parse API error response:`, parseError)
|
||||||
try {
|
try {
|
||||||
const errorText = await response.text()
|
const errorText = await response.text()
|
||||||
console.error(`[dtmc] Raw error response:`, errorText)
|
dtmcLogger.error(`Raw error response:`, errorText)
|
||||||
} catch {
|
} catch {
|
||||||
console.error(`[dtmc] Could not read error response body`)
|
dtmcLogger.error(`Could not read error response body`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,19 +89,19 @@ async function linkEmployeeToUser(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[dtmc] API call successful - Status: ${response.status}`)
|
dtmcLogger.debug(`API call successful - Status: ${response.status}`)
|
||||||
console.log(
|
dtmcLogger.debug(
|
||||||
`[dtmc] Response headers:`,
|
`Response headers:`,
|
||||||
Object.fromEntries(response.headers.entries())
|
Object.fromEntries(response.headers.entries())
|
||||||
)
|
)
|
||||||
try {
|
try {
|
||||||
const responseBody = await response.json()
|
const responseBody = await response.json()
|
||||||
console.log(`[dtmc] Response body:`, responseBody)
|
dtmcLogger.debug(`Response body:`, responseBody)
|
||||||
} catch (parseError) {
|
} catch (parseError) {
|
||||||
console.warn(`[dtmc] Could not parse success response body:`, parseError)
|
dtmcLogger.warn(`Could not parse success response body:`, parseError)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[dtmc] Successfully linked employee ID ${employeeId}`)
|
dtmcLogger.debug(`Successfully linked employee ID ${employeeId}`)
|
||||||
return { success: true }
|
return { success: true }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,20 +116,18 @@ export async function GET(request: NextRequest) {
|
|||||||
const dtmcSession = await dtmcAuth()
|
const dtmcSession = await dtmcAuth()
|
||||||
const session = await auth()
|
const session = await auth()
|
||||||
const baseUrl = getPublicURL(request)
|
const baseUrl = getPublicURL(request)
|
||||||
console.log("[dtmc] DTMC Callback handler - using baseUrl:", baseUrl)
|
dtmcLogger.debug("DTMC Callback handler - using baseUrl:", baseUrl)
|
||||||
|
|
||||||
if (!isValidSession(session)) {
|
if (!isValidSession(session)) {
|
||||||
console.error(
|
dtmcLogger.error("DTMC Callback handler - No valid user session found")
|
||||||
"[dtmc] DTMC Callback handler - No valid user session found"
|
|
||||||
)
|
|
||||||
const errorUrl = new URL(linkEmploymentError[lang], baseUrl)
|
const errorUrl = new URL(linkEmploymentError[lang], baseUrl)
|
||||||
errorUrl.searchParams.set("error", "no_session")
|
errorUrl.searchParams.set("error", "no_session")
|
||||||
return NextResponse.redirect(errorUrl)
|
return NextResponse.redirect(errorUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isValidSession(dtmcSession)) {
|
if (!isValidSession(dtmcSession)) {
|
||||||
console.error(
|
dtmcLogger.error(
|
||||||
"[dtmc] DTMC Callback handler - No valid entra id session found"
|
"DTMC Callback handler - No valid entra id session found"
|
||||||
)
|
)
|
||||||
const errorUrl = new URL(linkEmploymentError[lang], baseUrl)
|
const errorUrl = new URL(linkEmploymentError[lang], baseUrl)
|
||||||
errorUrl.searchParams.set("error", "no_entra_id_session")
|
errorUrl.searchParams.set("error", "no_entra_id_session")
|
||||||
@@ -136,40 +136,40 @@ export async function GET(request: NextRequest) {
|
|||||||
|
|
||||||
const employeeId = dtmcSession.employeeId
|
const employeeId = dtmcSession.employeeId
|
||||||
|
|
||||||
console.log(
|
dtmcLogger.debug(
|
||||||
"[dtmc] DTMC Callback handler - Extracted employeeId:",
|
"DTMC Callback handler - Extracted employeeId:",
|
||||||
employeeId
|
employeeId
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!employeeId) {
|
if (!employeeId) {
|
||||||
console.error("[dtmc] DTMC Callback handler - No employeeId in session")
|
dtmcLogger.error("DTMC Callback handler - No employeeId in session")
|
||||||
const errorUrl = new URL(linkEmploymentError[lang], baseUrl)
|
const errorUrl = new URL(linkEmploymentError[lang], baseUrl)
|
||||||
errorUrl.searchParams.set("error", "missing_employee_id")
|
errorUrl.searchParams.set("error", "missing_employee_id")
|
||||||
return NextResponse.redirect(errorUrl)
|
return NextResponse.redirect(errorUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
dtmcLogger.debug(
|
||||||
"[dtmc] DTMC Callback handler - Calling linkEmployeeToUser with ID:",
|
"DTMC Callback handler - Calling linkEmployeeToUser with ID:",
|
||||||
employeeId
|
employeeId
|
||||||
)
|
)
|
||||||
|
|
||||||
const accessToken = session.token.access_token
|
const accessToken = session.token.access_token
|
||||||
if (!accessToken) {
|
if (!accessToken) {
|
||||||
console.error("[dtmc] DTMC Callback handler - No access token in session")
|
dtmcLogger.error("DTMC Callback handler - No access token in session")
|
||||||
const errorUrl = new URL(linkEmploymentError[lang], baseUrl)
|
const errorUrl = new URL(linkEmploymentError[lang], baseUrl)
|
||||||
errorUrl.searchParams.set("error", "missing_access_token")
|
errorUrl.searchParams.set("error", "missing_access_token")
|
||||||
return NextResponse.redirect(errorUrl)
|
return NextResponse.redirect(errorUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await linkEmployeeToUser(employeeId, accessToken)
|
const result = await linkEmployeeToUser(employeeId, accessToken)
|
||||||
console.log(
|
dtmcLogger.debug(
|
||||||
"[dtmc] DTMC Callback handler - linkEmployeeToUser result:",
|
"DTMC Callback handler - linkEmployeeToUser result:",
|
||||||
result
|
result
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
console.error(
|
dtmcLogger.error(
|
||||||
"[dtmc] DTMC Callback handler - Failed to verify employment:",
|
"DTMC Callback handler - Failed to verify employment:",
|
||||||
`Status: ${result.statusCode}, Error: ${result.queryParam}`
|
`Status: ${result.statusCode}, Error: ${result.queryParam}`
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -182,21 +182,21 @@ export async function GET(request: NextRequest) {
|
|||||||
return NextResponse.redirect(errorUrl)
|
return NextResponse.redirect(errorUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
dtmcLogger.debug(
|
||||||
"[dtmc] DTMC Callback handler - Success! Employee linked with ID:",
|
"DTMC Callback handler - Success! Employee linked with ID:",
|
||||||
employeeId
|
employeeId
|
||||||
)
|
)
|
||||||
|
|
||||||
console.log("[dtmc] overview[lang]:", overview[lang])
|
dtmcLogger.debug("overview[lang]:", overview[lang])
|
||||||
const successUrl = new URL(overview[lang], baseUrl)
|
const successUrl = new URL(overview[lang], baseUrl)
|
||||||
successUrl.searchParams.set(DTMC_SUCCESS_BANNER_KEY, "true")
|
successUrl.searchParams.set(DTMC_SUCCESS_BANNER_KEY, "true")
|
||||||
console.log(
|
dtmcLogger.debug(
|
||||||
"[dtmc] DTMC Callback handler - Redirecting to success URL:",
|
"DTMC Callback handler - Redirecting to success URL:",
|
||||||
successUrl.toString()
|
successUrl.toString()
|
||||||
)
|
)
|
||||||
return NextResponse.redirect(successUrl)
|
return NextResponse.redirect(successUrl)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[dtmc] DTMC Callback handler - Error in handler:", error)
|
dtmcLogger.error("DTMC Callback handler - Error in handler:", error)
|
||||||
return internalServerError()
|
return internalServerError()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
import { generateHotelUrlTag } from "@scandic-hotels/trpc/utils/generateTag"
|
import { generateHotelUrlTag } from "@scandic-hotels/trpc/utils/generateTag"
|
||||||
|
|
||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
@@ -24,22 +25,25 @@ const validateJsonBody = z.object({
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const revalidateHotelLogger = createLogger("revalidate-hotel")
|
||||||
|
|
||||||
export async function POST(request: NextRequest) {
|
export async function POST(request: NextRequest) {
|
||||||
try {
|
try {
|
||||||
const headersList = await headers()
|
const headersList = await headers()
|
||||||
const secret = headersList.get("x-revalidate-secret")
|
const secret = headersList.get("x-revalidate-secret")
|
||||||
|
|
||||||
if (secret !== env.REVALIDATE_SECRET) {
|
if (secret !== env.REVALIDATE_SECRET) {
|
||||||
console.error(`Invalid Secret`)
|
revalidateHotelLogger.error(`Invalid Secret`, { secret })
|
||||||
console.error({ secret })
|
|
||||||
return badRequest({ revalidated: false, now: Date.now() })
|
return badRequest({ revalidated: false, now: Date.now() })
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await request.json()
|
const data = await request.json()
|
||||||
const validatedData = validateJsonBody.safeParse(data)
|
const validatedData = validateJsonBody.safeParse(data)
|
||||||
if (!validatedData.success) {
|
if (!validatedData.success) {
|
||||||
console.error("Bad validation for `validatedData` in hotel revalidation")
|
revalidateHotelLogger.error(
|
||||||
console.error(validatedData.error)
|
"Bad validation for `validatedData` in hotel revalidation",
|
||||||
|
validatedData.error
|
||||||
|
)
|
||||||
return internalServerError({ revalidated: false, now: Date.now() })
|
return internalServerError({ revalidated: false, now: Date.now() })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,21 +60,20 @@ export async function POST(request: NextRequest) {
|
|||||||
if (content_type.uid === "hotel_page") {
|
if (content_type.uid === "hotel_page") {
|
||||||
tag = generateHotelUrlTag(locale, entry.hotel_page_id)
|
tag = generateHotelUrlTag(locale, entry.hotel_page_id)
|
||||||
} else {
|
} else {
|
||||||
console.error(
|
revalidateHotelLogger.error(
|
||||||
`Invalid content_type, received ${content_type.uid}, expected "hotel_page"`
|
`Invalid content_type, received ${content_type.uid}, expected "hotel_page"`
|
||||||
)
|
)
|
||||||
return notFound({ revalidated: false, now: Date.now() })
|
return notFound({ revalidated: false, now: Date.now() })
|
||||||
}
|
}
|
||||||
|
|
||||||
console.info(`Revalidating hotel url tag: ${tag}`)
|
revalidateHotelLogger.info(`Revalidating hotel url tag: ${tag}`)
|
||||||
revalidateTag(tag)
|
revalidateTag(tag)
|
||||||
const cacheClient = await getCacheClient()
|
const cacheClient = await getCacheClient()
|
||||||
await cacheClient.deleteKey(tag, { fuzzy: true })
|
await cacheClient.deleteKey(tag, { fuzzy: true })
|
||||||
|
|
||||||
return Response.json({ revalidated: true, now: Date.now() })
|
return Response.json({ revalidated: true, now: Date.now() })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to revalidate tag(s) for hotel")
|
revalidateHotelLogger.error("Failed to revalidate tag(s) for hotel", error)
|
||||||
console.error(error)
|
|
||||||
return internalServerError({ revalidated: false, now: Date.now() })
|
return internalServerError({ revalidated: false, now: Date.now() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
import { generateLoyaltyConfigTag } from "@scandic-hotels/trpc/utils/generateTag"
|
import { generateLoyaltyConfigTag } from "@scandic-hotels/trpc/utils/generateTag"
|
||||||
|
|
||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
@@ -16,6 +17,8 @@ enum LoyaltyConfigContentTypes {
|
|||||||
reward = "reward",
|
reward = "reward",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loyaltyRevalidateLogger = createLogger("loyalty-revalidate")
|
||||||
|
|
||||||
const validateJsonBody = z.object({
|
const validateJsonBody = z.object({
|
||||||
data: z.object({
|
data: z.object({
|
||||||
content_type: z.object({
|
content_type: z.object({
|
||||||
@@ -35,18 +38,18 @@ export async function POST(request: NextRequest) {
|
|||||||
const secret = headersList.get("x-revalidate-secret")
|
const secret = headersList.get("x-revalidate-secret")
|
||||||
|
|
||||||
if (secret !== env.REVALIDATE_SECRET) {
|
if (secret !== env.REVALIDATE_SECRET) {
|
||||||
console.error(`Invalid Secret`)
|
loyaltyRevalidateLogger.error(`Invalid Secret`, { secret })
|
||||||
console.error({ secret })
|
|
||||||
return badRequest({ revalidated: false, now: Date.now() })
|
return badRequest({ revalidated: false, now: Date.now() })
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await request.json()
|
const data = await request.json()
|
||||||
const validatedData = validateJsonBody.safeParse(data)
|
const validatedData = validateJsonBody.safeParse(data)
|
||||||
if (!validatedData.success) {
|
if (!validatedData.success) {
|
||||||
console.error(
|
loyaltyRevalidateLogger.error(
|
||||||
"Bad validation for `validatedData` in loyaltyConfig revalidation"
|
"Bad validation for `validatedData` in loyaltyConfig revalidation",
|
||||||
|
validatedData.error
|
||||||
)
|
)
|
||||||
console.error(validatedData.error)
|
|
||||||
return internalServerError({ revalidated: false, now: Date.now() })
|
return internalServerError({ revalidated: false, now: Date.now() })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,11 +79,11 @@ export async function POST(request: NextRequest) {
|
|||||||
entry.reward_id
|
entry.reward_id
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
console.error("Invalid content_type")
|
loyaltyRevalidateLogger.error("Invalid content_type")
|
||||||
return notFound({ revalidated: false, now: Date.now() })
|
return notFound({ revalidated: false, now: Date.now() })
|
||||||
}
|
}
|
||||||
|
|
||||||
console.info(`Revalidating loyalty config tag: ${tag}`)
|
loyaltyRevalidateLogger.info(`Revalidating loyalty config tag: ${tag}`)
|
||||||
revalidateTag(tag)
|
revalidateTag(tag)
|
||||||
|
|
||||||
const cacheClient = await getCacheClient()
|
const cacheClient = await getCacheClient()
|
||||||
@@ -88,8 +91,10 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
return Response.json({ revalidated: true, now: Date.now() })
|
return Response.json({ revalidated: true, now: Date.now() })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to revalidate tag(s) for loyalty config")
|
loyaltyRevalidateLogger.error(
|
||||||
console.error(error)
|
"Failed to revalidate tag(s) for loyalty config",
|
||||||
|
error
|
||||||
|
)
|
||||||
return internalServerError({ revalidated: false, now: Date.now() })
|
return internalServerError({ revalidated: false, now: Date.now() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { revalidateTag } from "next/cache"
|
|||||||
import { headers } from "next/headers"
|
import { headers } from "next/headers"
|
||||||
|
|
||||||
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
import { generateTag } from "@scandic-hotels/trpc/utils/generateTag"
|
import { generateTag } from "@scandic-hotels/trpc/utils/generateTag"
|
||||||
|
|
||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
@@ -9,6 +10,7 @@ import { badRequest, internalServerError } from "@/server/errors/next"
|
|||||||
|
|
||||||
import type { Lang } from "@scandic-hotels/common/constants/language"
|
import type { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
|
|
||||||
|
const revalidateManuallyLogger = createLogger("revalidate-manually")
|
||||||
// This file is primarily to be used locally to test
|
// This file is primarily to be used locally to test
|
||||||
// purging your cache for new (and old) requests
|
// purging your cache for new (and old) requests
|
||||||
export async function POST() {
|
export async function POST() {
|
||||||
@@ -17,8 +19,7 @@ export async function POST() {
|
|||||||
const secret = headersList.get("x-revalidate-secret")
|
const secret = headersList.get("x-revalidate-secret")
|
||||||
|
|
||||||
if (secret !== env.REVALIDATE_SECRET) {
|
if (secret !== env.REVALIDATE_SECRET) {
|
||||||
console.error(`Invalid Secret`)
|
revalidateManuallyLogger.error(`Invalid Secret`, { secret })
|
||||||
console.error({ secret })
|
|
||||||
return badRequest({
|
return badRequest({
|
||||||
now: Date.now(),
|
now: Date.now(),
|
||||||
revalidated: false,
|
revalidated: false,
|
||||||
@@ -30,8 +31,8 @@ export async function POST() {
|
|||||||
const lang = headersList.get("x-lang")
|
const lang = headersList.get("x-lang")
|
||||||
|
|
||||||
if (!lang || !identifier) {
|
if (!lang || !identifier) {
|
||||||
console.info(`Missing lang and/or identifier`)
|
revalidateManuallyLogger.info(`Missing lang and/or identifier`)
|
||||||
console.info(`lang: ${lang}, identifier: ${identifier}`)
|
revalidateManuallyLogger.info(`lang: ${lang}, identifier: ${identifier}`)
|
||||||
return badRequest({
|
return badRequest({
|
||||||
now: Date.now(),
|
now: Date.now(),
|
||||||
revalidated: false,
|
revalidated: false,
|
||||||
@@ -42,18 +43,17 @@ export async function POST() {
|
|||||||
|
|
||||||
const tag = generateTag(lang as Lang, identifier, affix)
|
const tag = generateTag(lang as Lang, identifier, affix)
|
||||||
|
|
||||||
console.info(
|
revalidateManuallyLogger.info(
|
||||||
`Revalidated tag for [lang: ${lang}, identifier: ${identifier}${affix ? `, affix: ${affix}` : ""}]`
|
`Revalidated tag for [lang: ${lang}, identifier: ${identifier}${affix ? `, affix: ${affix}` : ""}]`
|
||||||
)
|
)
|
||||||
console.info(`Tag: ${tag}`)
|
revalidateManuallyLogger.info(`Tag: ${tag}`)
|
||||||
|
|
||||||
revalidateTag(tag)
|
revalidateTag(tag)
|
||||||
cacheClient.deleteKey(tag, { fuzzy: true })
|
cacheClient.deleteKey(tag, { fuzzy: true })
|
||||||
|
|
||||||
return Response.json({ revalidated: true, now: Date.now() })
|
return Response.json({ revalidated: true, now: Date.now() })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to revalidate tag(s)")
|
revalidateManuallyLogger.error("Failed to revalidate tag(s)", error)
|
||||||
console.error(error)
|
|
||||||
return internalServerError({ revalidated: false, now: Date.now() })
|
return internalServerError({ revalidated: false, now: Date.now() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
import { affix as breadcrumbsAffix } from "@scandic-hotels/trpc/routers/contentstack/breadcrumbs/utils"
|
import { affix as breadcrumbsAffix } from "@scandic-hotels/trpc/routers/contentstack/breadcrumbs/utils"
|
||||||
import { destinationCityPageDestinationSettingsSchema } from "@scandic-hotels/trpc/routers/contentstack/destinationCityPage/output"
|
import { destinationCityPageDestinationSettingsSchema } from "@scandic-hotels/trpc/routers/contentstack/destinationCityPage/output"
|
||||||
import { languageSwitcherAffix } from "@scandic-hotels/trpc/routers/contentstack/languageSwitcher/utils"
|
import { languageSwitcherAffix } from "@scandic-hotels/trpc/routers/contentstack/languageSwitcher/utils"
|
||||||
@@ -47,14 +48,14 @@ const validateJsonBody = z.object({
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const revalidateLogger = createLogger("revalidate")
|
||||||
export async function POST(request: NextRequest) {
|
export async function POST(request: NextRequest) {
|
||||||
try {
|
try {
|
||||||
const headersList = await headers()
|
const headersList = await headers()
|
||||||
const secret = headersList.get("x-revalidate-secret")
|
const secret = headersList.get("x-revalidate-secret")
|
||||||
|
|
||||||
if (secret !== env.REVALIDATE_SECRET) {
|
if (secret !== env.REVALIDATE_SECRET) {
|
||||||
console.error(`Invalid Secret`)
|
revalidateLogger.error(`Invalid Secret`, { secret })
|
||||||
console.error({ secret })
|
|
||||||
return badRequest({
|
return badRequest({
|
||||||
now: Date.now(),
|
now: Date.now(),
|
||||||
revalidated: false,
|
revalidated: false,
|
||||||
@@ -64,8 +65,10 @@ export async function POST(request: NextRequest) {
|
|||||||
const data = await request.json()
|
const data = await request.json()
|
||||||
const validatedData = validateJsonBody.safeParse(data)
|
const validatedData = validateJsonBody.safeParse(data)
|
||||||
if (!validatedData.success) {
|
if (!validatedData.success) {
|
||||||
console.error("Bad validation for `validatedData`")
|
revalidateLogger.error(
|
||||||
console.error(validatedData.error)
|
"Bad validation for `validatedData`",
|
||||||
|
validatedData.error
|
||||||
|
)
|
||||||
return internalServerError({ revalidated: false, now: Date.now() })
|
return internalServerError({ revalidated: false, now: Date.now() })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,37 +98,41 @@ export async function POST(request: NextRequest) {
|
|||||||
const cacheClient = await getCacheClient()
|
const cacheClient = await getCacheClient()
|
||||||
|
|
||||||
const contentTypeUidTag = generateTag(entryLocale, content_type.uid)
|
const contentTypeUidTag = generateTag(entryLocale, content_type.uid)
|
||||||
console.info(`Revalidating tag by content_type_uid: ${contentTypeUidTag}`)
|
revalidateLogger.info(
|
||||||
|
`Revalidating tag by content_type_uid: ${contentTypeUidTag}`
|
||||||
|
)
|
||||||
revalidateTag(contentTypeUidTag)
|
revalidateTag(contentTypeUidTag)
|
||||||
await cacheClient.deleteKey(contentTypeUidTag, { fuzzy: true })
|
await cacheClient.deleteKey(contentTypeUidTag, { fuzzy: true })
|
||||||
|
|
||||||
console.info(`Revalidating refsTag: ${refsTag}`)
|
revalidateLogger.info(`Revalidating refsTag: ${refsTag}`)
|
||||||
revalidateTag(refsTag)
|
revalidateTag(refsTag)
|
||||||
await cacheClient.deleteKey(refsTag, { fuzzy: true })
|
await cacheClient.deleteKey(refsTag, { fuzzy: true })
|
||||||
|
|
||||||
console.info(`Revalidating refTag: ${refTag}`)
|
revalidateLogger.info(`Revalidating refTag: ${refTag}`)
|
||||||
revalidateTag(refTag)
|
revalidateTag(refTag)
|
||||||
await cacheClient.deleteKey(refTag, { fuzzy: true })
|
await cacheClient.deleteKey(refTag, { fuzzy: true })
|
||||||
|
|
||||||
console.info(`Revalidating tag: ${tag}`)
|
revalidateLogger.info(`Revalidating tag: ${tag}`)
|
||||||
revalidateTag(tag)
|
revalidateTag(tag)
|
||||||
await cacheClient.deleteKey(tag, { fuzzy: true })
|
await cacheClient.deleteKey(tag, { fuzzy: true })
|
||||||
|
|
||||||
console.info(`Revalidating language switcher tag: ${languageSwitcherTag}`)
|
revalidateLogger.info(
|
||||||
|
`Revalidating language switcher tag: ${languageSwitcherTag}`
|
||||||
|
)
|
||||||
revalidateTag(languageSwitcherTag)
|
revalidateTag(languageSwitcherTag)
|
||||||
await cacheClient.deleteKey(languageSwitcherTag, { fuzzy: true })
|
await cacheClient.deleteKey(languageSwitcherTag, { fuzzy: true })
|
||||||
|
|
||||||
console.info(`Revalidating metadataTag: ${metadataTag}`)
|
revalidateLogger.info(`Revalidating metadataTag: ${metadataTag}`)
|
||||||
revalidateTag(metadataTag)
|
revalidateTag(metadataTag)
|
||||||
await cacheClient.deleteKey(metadataTag, { fuzzy: true })
|
await cacheClient.deleteKey(metadataTag, { fuzzy: true })
|
||||||
|
|
||||||
console.info(`Revalidating contentEntryTag: ${contentEntryTag}`)
|
revalidateLogger.info(`Revalidating contentEntryTag: ${contentEntryTag}`)
|
||||||
revalidateTag(contentEntryTag)
|
revalidateTag(contentEntryTag)
|
||||||
await cacheClient.deleteKey(contentEntryTag, { fuzzy: true })
|
await cacheClient.deleteKey(contentEntryTag, { fuzzy: true })
|
||||||
|
|
||||||
if (entry.url) {
|
if (entry.url) {
|
||||||
const resolveEntryTag = resolveEntryCacheKey(entryLocale, entry.url)
|
const resolveEntryTag = resolveEntryCacheKey(entryLocale, entry.url)
|
||||||
console.info(`Revalidating url: ${resolveEntryTag}`)
|
revalidateLogger.info(`Revalidating url: ${resolveEntryTag}`)
|
||||||
|
|
||||||
await cacheClient.deleteKey(resolveEntryTag, { fuzzy: true })
|
await cacheClient.deleteKey(resolveEntryTag, { fuzzy: true })
|
||||||
}
|
}
|
||||||
@@ -142,11 +149,13 @@ export async function POST(request: NextRequest) {
|
|||||||
breadcrumbsAffix
|
breadcrumbsAffix
|
||||||
)
|
)
|
||||||
|
|
||||||
console.info(`Revalidating breadcrumbsRefsTag: ${breadcrumbsRefsTag}`)
|
revalidateLogger.info(
|
||||||
|
`Revalidating breadcrumbsRefsTag: ${breadcrumbsRefsTag}`
|
||||||
|
)
|
||||||
revalidateTag(breadcrumbsRefsTag)
|
revalidateTag(breadcrumbsRefsTag)
|
||||||
await cacheClient.deleteKey(breadcrumbsRefsTag, { fuzzy: true })
|
await cacheClient.deleteKey(breadcrumbsRefsTag, { fuzzy: true })
|
||||||
|
|
||||||
console.info(`Revalidating breadcrumbsTag: ${breadcrumbsTag}`)
|
revalidateLogger.info(`Revalidating breadcrumbsTag: ${breadcrumbsTag}`)
|
||||||
revalidateTag(breadcrumbsTag)
|
revalidateTag(breadcrumbsTag)
|
||||||
await cacheClient.deleteKey(breadcrumbsTag, { fuzzy: true })
|
await cacheClient.deleteKey(breadcrumbsTag, { fuzzy: true })
|
||||||
}
|
}
|
||||||
@@ -158,7 +167,7 @@ export async function POST(request: NextRequest) {
|
|||||||
pageSettingsAffix
|
pageSettingsAffix
|
||||||
)
|
)
|
||||||
|
|
||||||
console.info(`Revalidating pageSettingsTag: ${pageSettingsTag}`)
|
revalidateLogger.info(`Revalidating pageSettingsTag: ${pageSettingsTag}`)
|
||||||
revalidateTag(pageSettingsTag)
|
revalidateTag(pageSettingsTag)
|
||||||
await cacheClient.deleteKey(pageSettingsTag, { fuzzy: true })
|
await cacheClient.deleteKey(pageSettingsTag, { fuzzy: true })
|
||||||
}
|
}
|
||||||
@@ -177,8 +186,7 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
return Response.json({ revalidated: true, now: Date.now() })
|
return Response.json({ revalidated: true, now: Date.now() })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to revalidate tag(s)")
|
revalidateLogger.error("Failed to revalidate tag(s)", error)
|
||||||
console.error(error)
|
|
||||||
return internalServerError({ revalidated: false, now: Date.now() })
|
return internalServerError({ revalidated: false, now: Date.now() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import { type NextRequest, NextResponse } from "next/server"
|
import { type NextRequest, NextResponse } from "next/server"
|
||||||
|
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
|
|
||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
|
|
||||||
import { warmup } from "@/services/warmup"
|
import { warmup } from "@/services/warmup"
|
||||||
import { isWarmupKey } from "@/services/warmup/warmupKeys"
|
import { isWarmupKey } from "@/services/warmup/warmupKeys"
|
||||||
import { createLogger } from "@/utils/logger"
|
|
||||||
|
|
||||||
export const dynamic = "force-dynamic"
|
export const dynamic = "force-dynamic"
|
||||||
|
|
||||||
const logger = createLogger("Warmup")
|
const logger = createLogger("warmup")
|
||||||
|
|
||||||
export async function GET(req: NextRequest) {
|
export async function GET(req: NextRequest) {
|
||||||
const url = new URL(req.url)
|
const url = new URL(req.url)
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
import * as Sentry from "@sentry/nextjs"
|
import * as Sentry from "@sentry/nextjs"
|
||||||
import { useEffect } from "react"
|
import { useEffect } from "react"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import Image from "@/components/Image"
|
import Image from "@/components/Image"
|
||||||
|
|
||||||
/* eslint-disable formatjs/no-literal-string-in-jsx */
|
/* eslint-disable formatjs/no-literal-string-in-jsx */
|
||||||
@@ -11,7 +13,7 @@ export default function GlobalError({
|
|||||||
}: {
|
}: {
|
||||||
error: Error & { digest?: string }
|
error: Error & { digest?: string }
|
||||||
}) {
|
}) {
|
||||||
console.log({ global_error: error })
|
logger.error("Global Error", { global_error: error })
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Sentry.captureException(error)
|
Sentry.captureException(error)
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
import { notFound } from "next/navigation"
|
import { notFound } from "next/navigation"
|
||||||
|
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
|
|
||||||
import { getSitemapDataById } from "@/utils/sitemap"
|
import { getSitemapDataById } from "@/utils/sitemap"
|
||||||
|
|
||||||
import type { NextRequest } from "next/server"
|
import type { NextRequest } from "next/server"
|
||||||
|
|
||||||
export const dynamic = "force-dynamic"
|
export const dynamic = "force-dynamic"
|
||||||
|
|
||||||
|
const sitemapLogger = createLogger("sitemap")
|
||||||
export async function GET(
|
export async function GET(
|
||||||
_request: NextRequest,
|
_request: NextRequest,
|
||||||
context: { params: Promise<{ sitemapId: string }> }
|
context: { params: Promise<{ sitemapId: string }> }
|
||||||
@@ -13,7 +16,7 @@ export async function GET(
|
|||||||
const params = await context.params
|
const params = await context.params
|
||||||
const sitemapId = params.sitemapId
|
const sitemapId = params.sitemapId
|
||||||
|
|
||||||
console.log("[SITEMAP] Fetching sitemap by ID", sitemapId)
|
sitemapLogger.debug("Fetching sitemap by ID", sitemapId)
|
||||||
|
|
||||||
if (!sitemapId) {
|
if (!sitemapId) {
|
||||||
return notFound()
|
return notFound()
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
|
|
||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
|
|
||||||
import { getLastUpdated, getSitemapIds } from "@/utils/sitemap"
|
import { getLastUpdated, getSitemapIds } from "@/utils/sitemap"
|
||||||
|
|
||||||
export const dynamic = "force-dynamic"
|
export const dynamic = "force-dynamic"
|
||||||
|
|
||||||
|
const sitemapLogger = createLogger("sitemap")
|
||||||
export async function GET() {
|
export async function GET() {
|
||||||
console.log(`[SITEMAP] Fetching sitemap`)
|
sitemapLogger.debug(`Fetching sitemap`)
|
||||||
|
|
||||||
const lastUpdated = await getLastUpdated()
|
const lastUpdated = await getLastUpdated()
|
||||||
|
|
||||||
@@ -15,7 +18,7 @@ export async function GET() {
|
|||||||
return new Response("No sitemaps found", { status: 404 })
|
return new Response("No sitemaps found", { status: 404 })
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[SITEMAP] Sitemaps retrieved: ${sitemaps.length}`)
|
sitemapLogger.debug(`Sitemaps retrieved: ${sitemaps.length}`)
|
||||||
|
|
||||||
const urls = sitemaps.map(
|
const urls = sitemaps.map(
|
||||||
(id) => `<sitemap>
|
(id) => `<sitemap>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import NextAuth, { type NextAuthConfig } from "next-auth"
|
import NextAuth, { type NextAuthConfig } from "next-auth"
|
||||||
import MicrosoftEntraID from "next-auth/providers/microsoft-entra-id"
|
import MicrosoftEntraID from "next-auth/providers/microsoft-entra-id"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
@@ -40,9 +42,9 @@ const config = {
|
|||||||
return session
|
return session
|
||||||
},
|
},
|
||||||
async redirect({ baseUrl, url }) {
|
async redirect({ baseUrl, url }) {
|
||||||
console.log(`[auth.dtmc] deciding redirect URL`, { baseUrl, url })
|
logger.debug(`[auth.dtmc] deciding redirect URL`, { baseUrl, url })
|
||||||
if (url.startsWith("/")) {
|
if (url.startsWith("/")) {
|
||||||
console.log(
|
logger.debug(
|
||||||
`[auth.dtmc] relative URL accepted, returning: ${baseUrl}${url}`
|
`[auth.dtmc] relative URL accepted, returning: ${baseUrl}${url}`
|
||||||
)
|
)
|
||||||
// Allows relative callback URLs
|
// Allows relative callback URLs
|
||||||
@@ -54,22 +56,24 @@ const config = {
|
|||||||
if (
|
if (
|
||||||
/\.scandichotels\.(dk|de|com|fi|no|se)$/.test(parsedUrl.hostname)
|
/\.scandichotels\.(dk|de|com|fi|no|se)$/.test(parsedUrl.hostname)
|
||||||
) {
|
) {
|
||||||
console.log(`[auth.dtmc] subdomain URL accepted, returning: ${url}`)
|
logger.debug(
|
||||||
|
`[auth.dtmc] subdomain URL accepted, returning: ${url}`
|
||||||
|
)
|
||||||
// Allows any subdomains on all top level domains above
|
// Allows any subdomains on all top level domains above
|
||||||
return url
|
return url
|
||||||
} else if (parsedUrl.origin === baseUrl) {
|
} else if (parsedUrl.origin === baseUrl) {
|
||||||
// Allows callback URLs on the same origin
|
// Allows callback URLs on the same origin
|
||||||
console.log(`[auth.dtmc] origin URL accepted, returning: ${url}`)
|
logger.debug(`[auth.dtmc] origin URL accepted, returning: ${url}`)
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(
|
logger.error(
|
||||||
`[auth.dtmc] error parsing incoming URL for redirection`,
|
`[auth.dtmc] error parsing incoming URL for redirection`,
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(`[auth.dtmc] URL denied, returning base URL: ${baseUrl}`)
|
logger.debug(`[auth.dtmc] URL denied, returning base URL: ${baseUrl}`)
|
||||||
return baseUrl
|
return baseUrl
|
||||||
},
|
},
|
||||||
async authorized() {
|
async authorized() {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import NextAuth, { type NextAuthConfig, type User } from "next-auth"
|
import NextAuth, { type NextAuthConfig, type User } from "next-auth"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { LoginTypeEnum } from "@scandic-hotels/trpc/types/loginType"
|
import { LoginTypeEnum } from "@scandic-hotels/trpc/types/loginType"
|
||||||
|
|
||||||
import { PRE_REFRESH_TIME_IN_SECONDS } from "@/constants/auth"
|
import { PRE_REFRESH_TIME_IN_SECONDS } from "@/constants/auth"
|
||||||
@@ -24,7 +25,7 @@ async function refreshTokens(token: JWT) {
|
|||||||
throw "Refresh token missing."
|
throw "Refresh token missing."
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("token-debug Access token expired, trying to refresh it.", {
|
logger.debug("token-debug Access token expired, trying to refresh it.", {
|
||||||
expires_at: token.expires_at,
|
expires_at: token.expires_at,
|
||||||
sub: token.sub,
|
sub: token.sub,
|
||||||
token: token.access_token,
|
token: token.access_token,
|
||||||
@@ -46,7 +47,7 @@ async function refreshTokens(token: JWT) {
|
|||||||
const new_tokens = await response.json()
|
const new_tokens = await response.json()
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
console.log("token-debug Token response was not ok", {
|
logger.debug("token-debug Token response was not ok", {
|
||||||
status: response.status,
|
status: response.status,
|
||||||
statusText: response.statusText,
|
statusText: response.statusText,
|
||||||
sub: token.sub,
|
sub: token.sub,
|
||||||
@@ -54,7 +55,7 @@ async function refreshTokens(token: JWT) {
|
|||||||
throw new_tokens
|
throw new_tokens
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("token-debug Successfully got new token(s)", {
|
logger.debug("token-debug Successfully got new token(s)", {
|
||||||
expires_at: new_tokens.expires_at,
|
expires_at: new_tokens.expires_at,
|
||||||
got_new_refresh_token: new_tokens.refresh_token !== token.refresh_token,
|
got_new_refresh_token: new_tokens.refresh_token !== token.refresh_token,
|
||||||
got_new_access_token: new_tokens.access_token !== token.access_token,
|
got_new_access_token: new_tokens.access_token !== token.access_token,
|
||||||
@@ -72,7 +73,7 @@ async function refreshTokens(token: JWT) {
|
|||||||
refresh_token: new_tokens.refresh_token,
|
refresh_token: new_tokens.refresh_token,
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("token-debug Error thrown when trying to refresh", {
|
logger.error("token-debug Error thrown when trying to refresh", {
|
||||||
error,
|
error,
|
||||||
sub: token.sub,
|
sub: token.sub,
|
||||||
})
|
})
|
||||||
@@ -141,9 +142,11 @@ const baseConfig = {
|
|||||||
return session
|
return session
|
||||||
},
|
},
|
||||||
async redirect({ baseUrl, url }) {
|
async redirect({ baseUrl, url }) {
|
||||||
console.log(`[auth] deciding redirect URL`, { baseUrl, url })
|
logger.debug(`[auth] deciding redirect URL`, { baseUrl, url })
|
||||||
if (url.startsWith("/")) {
|
if (url.startsWith("/")) {
|
||||||
console.log(`[auth] relative URL accepted, returning: ${baseUrl}${url}`)
|
logger.debug(
|
||||||
|
`[auth] relative URL accepted, returning: ${baseUrl}${url}`
|
||||||
|
)
|
||||||
// Allows relative callback URLs
|
// Allows relative callback URLs
|
||||||
return `${baseUrl}${url}`
|
return `${baseUrl}${url}`
|
||||||
} else {
|
} else {
|
||||||
@@ -153,19 +156,19 @@ const baseConfig = {
|
|||||||
if (
|
if (
|
||||||
/\.scandichotels\.(dk|de|com|fi|no|se)$/.test(parsedUrl.hostname)
|
/\.scandichotels\.(dk|de|com|fi|no|se)$/.test(parsedUrl.hostname)
|
||||||
) {
|
) {
|
||||||
console.log(`[auth] subdomain URL accepted, returning: ${url}`)
|
logger.debug(`[auth] subdomain URL accepted, returning: ${url}`)
|
||||||
// Allows any subdomains on all top level domains above
|
// Allows any subdomains on all top level domains above
|
||||||
return url
|
return url
|
||||||
} else if (parsedUrl.origin === baseUrl) {
|
} else if (parsedUrl.origin === baseUrl) {
|
||||||
// Allows callback URLs on the same origin
|
// Allows callback URLs on the same origin
|
||||||
console.log(`[auth] origin URL accepted, returning: ${url}`)
|
logger.debug(`[auth] origin URL accepted, returning: ${url}`)
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`[auth] error parsing incoming URL for redirection`, e)
|
logger.error(`[auth] error parsing incoming URL for redirection`, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(`[auth] URL denied, returning base URL: ${baseUrl}`)
|
logger.debug(`[auth] URL denied, returning base URL: ${baseUrl}`)
|
||||||
return baseUrl
|
return baseUrl
|
||||||
},
|
},
|
||||||
async authorized() {
|
async authorized() {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import { getFilteredJobs, getFiltersFromJobs } from "./utils"
|
import { getFilteredJobs, getFiltersFromJobs } from "./utils"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -55,7 +57,7 @@ export function reducer(state: State, action: Action) {
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
const unhandledActionType: never = type
|
const unhandledActionType: never = type
|
||||||
console.info(`Unhandled type: ${unhandledActionType}`)
|
logger.info(`Unhandled JobylonFeed type: ${unhandledActionType}`)
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
} from "react-aria-components"
|
} from "react-aria-components"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||||
import { trpc } from "@scandic-hotels/trpc/client"
|
import { trpc } from "@scandic-hotels/trpc/client"
|
||||||
|
|
||||||
@@ -177,7 +178,7 @@ function getRedeemFlow(reward: Reward, membershipNumber: string) {
|
|||||||
case "Tier":
|
case "Tier":
|
||||||
return <RedeemTier reward={reward} membershipNumber={membershipNumber} />
|
return <RedeemTier reward={reward} membershipNumber={membershipNumber} />
|
||||||
default:
|
default:
|
||||||
console.warn("Unsupported reward type for redeem:", rewardType)
|
logger.warn("Unsupported reward type for redeem:", rewardType)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import { createContext, useCallback, useContext, useEffect } from "react"
|
import { createContext, useCallback, useContext, useEffect } from "react"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { trpc } from "@scandic-hotels/trpc/client"
|
import { trpc } from "@scandic-hotels/trpc/client"
|
||||||
|
|
||||||
import { getFirstRedeemableCoupon } from "@/utils/rewards"
|
import { getFirstRedeemableCoupon } from "@/utils/rewards"
|
||||||
@@ -41,7 +42,7 @@ export default function useRedeemFlow() {
|
|||||||
setRedeemStep("redeemed")
|
setRedeemStep("redeemed")
|
||||||
},
|
},
|
||||||
onError(error) {
|
onError(error) {
|
||||||
console.error("Failed to redeem", error)
|
logger.error("Failed to redeem", error)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { useState } from "react"
|
|||||||
import { Button as ButtonRAC } from "react-aria-components"
|
import { Button as ButtonRAC } from "react-aria-components"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
import { PointOfInterestGroupEnum } from "@scandic-hotels/trpc/enums/pointOfInterest"
|
import { PointOfInterestGroupEnum } from "@scandic-hotels/trpc/enums/pointOfInterest"
|
||||||
|
|
||||||
@@ -120,7 +121,7 @@ export default function Sidebar({
|
|||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
const option: never = group
|
const option: never = group
|
||||||
console.warn(`Unsupported group given: ${option}`)
|
logger.warn(`Unsupported group given: ${option}`)
|
||||||
|
|
||||||
return intl.formatMessage({
|
return intl.formatMessage({
|
||||||
defaultMessage: "N/A",
|
defaultMessage: "N/A",
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import "dialogshift-webchat-sdk/bundles/dialogshift-webchat-sdk.min.css"
|
|||||||
|
|
||||||
import { useEffect, useRef } from "react"
|
import { useEffect, useRef } from "react"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import type { Lang } from "@scandic-hotels/common/constants/language"
|
import type { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
|
|
||||||
interface DialogshiftWidgetClientProps {
|
interface DialogshiftWidgetClientProps {
|
||||||
@@ -26,7 +28,7 @@ export default function DialogshiftWidgetClient({
|
|||||||
locale: language,
|
locale: language,
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to load Dialogshift chat:", error)
|
logger.error("Failed to load Dialogshift chat:", error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import { getIntl } from "@/i18n"
|
import { getIntl } from "@/i18n"
|
||||||
import { isFacilityCard, setFacilityCardGrids } from "@/utils/facilityCards"
|
import { isFacilityCard, setFacilityCardGrids } from "@/utils/facilityCards"
|
||||||
|
|
||||||
@@ -55,7 +57,7 @@ export default async function Facilities({
|
|||||||
defaultMessage: "Read more",
|
defaultMessage: "Read more",
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
console.warn(`Unsupported option given: ${text}`)
|
logger.warn(`Unsupported option given: ${text}`)
|
||||||
return intl.formatMessage({
|
return intl.formatMessage({
|
||||||
defaultMessage: "Read more",
|
defaultMessage: "Read more",
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import { getIntl } from "@/i18n"
|
import { getIntl } from "@/i18n"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -112,7 +114,7 @@ export async function translateWellnessDetails({
|
|||||||
.sort()
|
.sort()
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.warn(`Unsupported type given: ${type}`)
|
logger.warn(`Unsupported type given: ${type}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import type { Lang } from "@scandic-hotels/common/constants/language"
|
import type { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
import type { Hotel, HotelData } from "@scandic-hotels/trpc/types/hotel"
|
import type { Hotel, HotelData } from "@scandic-hotels/trpc/types/hotel"
|
||||||
import type { HotelPage } from "@scandic-hotels/trpc/types/hotelPage"
|
import type { HotelPage } from "@scandic-hotels/trpc/types/hotelPage"
|
||||||
@@ -83,7 +85,7 @@ export function translateWellnessType(type: string, intl: IntlShape) {
|
|||||||
defaultMessage: "Sauna",
|
defaultMessage: "Sauna",
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
console.warn(`Unsupported group given: ${type}`)
|
logger.warn(`Unsupported wellnessType: ${type}`)
|
||||||
return intl.formatMessage({
|
return intl.formatMessage({
|
||||||
defaultMessage: "Wellness",
|
defaultMessage: "Wellness",
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
import { usePathname } from "next/navigation"
|
import { usePathname } from "next/navigation"
|
||||||
import { useCallback, useEffect } from "react"
|
import { useCallback, useEffect } from "react"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import { webviews } from "@/constants/routes/webviews"
|
import { webviews } from "@/constants/routes/webviews"
|
||||||
|
|
||||||
export default function CookieBotConsent() {
|
export default function CookieBotConsent() {
|
||||||
@@ -20,7 +22,7 @@ export default function CookieBotConsent() {
|
|||||||
window.adobe.optIn.deny(window.adobe.OptInCategories.ANALYTICS, true)
|
window.adobe.optIn.deny(window.adobe.OptInCategories.ANALYTICS, true)
|
||||||
}
|
}
|
||||||
window.adobe.optIn.complete()
|
window.adobe.optIn.complete()
|
||||||
console.warn("window.load event explicitly dispatched.")
|
logger.warn("window.load event explicitly dispatched.")
|
||||||
window.dispatchEvent(new Event("load"))
|
window.dispatchEvent(new Event("load"))
|
||||||
}
|
}
|
||||||
}, [isWebview])
|
}, [isWebview])
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import List from "./List"
|
import List from "./List"
|
||||||
import Puffs from "./Puffs"
|
import Puffs from "./Puffs"
|
||||||
import Text from "./Text"
|
import Text from "./Text"
|
||||||
@@ -24,7 +26,7 @@ export default function Blocks({ blocks }: BlocksProps) {
|
|||||||
case BlocksTypenameEnum.CurrentBlocksPageBlocksText:
|
case BlocksTypenameEnum.CurrentBlocksPageBlocksText:
|
||||||
return <Text key={`${block.__typename}-${idx}`} {...block} />
|
return <Text key={`${block.__typename}-${idx}`} {...block} />
|
||||||
default:
|
default:
|
||||||
console.log(`Unknown type: (${type})`)
|
logger.error(`Unknown type: (${type})`)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
import { usePathname, useSearchParams } from "next/navigation"
|
import { usePathname, useSearchParams } from "next/navigation"
|
||||||
import { useEffect } from "react"
|
import { useEffect } from "react"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
SiteSectionObject,
|
SiteSectionObject,
|
||||||
TrackingData,
|
TrackingData,
|
||||||
@@ -82,7 +84,7 @@ export default function Tracking({ pageData }: TrackingProps) {
|
|||||||
window.adobe.optIn.deny(window.adobe.OptInCategories.ANALYTICS, true)
|
window.adobe.optIn.deny(window.adobe.OptInCategories.ANALYTICS, true)
|
||||||
}
|
}
|
||||||
window.adobe.optIn.complete()
|
window.adobe.optIn.complete()
|
||||||
console.warn("window.load event explicitly dispatched.")
|
logger.warn("window.load event explicitly dispatched.")
|
||||||
window.dispatchEvent(new Event("load"))
|
window.dispatchEvent(new Event("load"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import * as Sentry from "@sentry/nextjs"
|
import * as Sentry from "@sentry/nextjs"
|
||||||
import React from "react"
|
import React from "react"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
type ErrorBoundaryProps = {
|
type ErrorBoundaryProps = {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
fallback?: React.ReactNode
|
fallback?: React.ReactNode
|
||||||
@@ -21,7 +23,7 @@ class ErrorBoundary extends React.Component<
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
||||||
console.error("ErrorBoundary caught an error:", error, errorInfo)
|
logger.error("ErrorBoundary caught an error:", error, errorInfo)
|
||||||
Sentry.captureException(error, { extra: { errorInfo } })
|
Sentry.captureException(error, { extra: { errorInfo } })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { type ChangeEvent, type FormEvent, useId } from "react"
|
|||||||
import { useFormContext, useWatch } from "react-hook-form"
|
import { useFormContext, useWatch } from "react-hook-form"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { Button } from "@scandic-hotels/design-system/Button"
|
import { Button } from "@scandic-hotels/design-system/Button"
|
||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
@@ -78,7 +79,7 @@ export function Search({
|
|||||||
setValue("city", undefined)
|
setValue("city", undefined)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
console.error("Unhandled type:", selectedItem.type)
|
logger.error("Unhandled type:", selectedItem.type)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { FormProvider, useForm } from "react-hook-form"
|
|||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { profile } from "@scandic-hotels/common/constants/routes/myPages"
|
import { profile } from "@scandic-hotels/common/constants/routes/myPages"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { trpc } from "@scandic-hotels/trpc/client"
|
import { trpc } from "@scandic-hotels/trpc/client"
|
||||||
import { langToApiLang } from "@scandic-hotels/trpc/constants/apiLang"
|
import { langToApiLang } from "@scandic-hotels/trpc/constants/apiLang"
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ export default function Form({ user }: EditFormProps) {
|
|||||||
case Status.error:
|
case Status.error:
|
||||||
if (response.issues?.length) {
|
if (response.issues?.length) {
|
||||||
response.issues.forEach((issue) => {
|
response.issues.forEach((issue) => {
|
||||||
console.error(issue)
|
logger.error("Profile edit error:", issue)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
toast.error(response.message)
|
toast.error(response.message)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { useRouter } from "next/navigation"
|
|||||||
import { FormProvider, useForm } from "react-hook-form"
|
import { FormProvider, useForm } from "react-hook-form"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { Button } from "@scandic-hotels/design-system/Button"
|
import { Button } from "@scandic-hotels/design-system/Button"
|
||||||
import Checkbox from "@scandic-hotels/design-system/Form/Checkbox"
|
import Checkbox from "@scandic-hotels/design-system/Form/Checkbox"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
@@ -69,7 +70,7 @@ export default function SignupForm({ title }: SignUpFormProps) {
|
|||||||
defaultMessage: "Something went wrong!",
|
defaultMessage: "Something went wrong!",
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
console.error("Component Signup error:", error)
|
logger.error("Component Signup error:", error)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { createEvent } from "ics"
|
|||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { dt } from "@scandic-hotels/common/dt"
|
import { dt } from "@scandic-hotels/common/dt"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import { toast } from "@/components/TempDesignSystem/Toasts"
|
import { toast } from "@/components/TempDesignSystem/Toasts"
|
||||||
import useLang from "@/hooks/useLang"
|
import useLang from "@/hooks/useLang"
|
||||||
@@ -25,7 +26,7 @@ export default function AddToCalendar({
|
|||||||
|
|
||||||
createEvent(event, (error, value) => {
|
createEvent(event, (error, value) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error("ICS Error:", error)
|
logger.error("ICS Error:", error)
|
||||||
toast.error(
|
toast.error(
|
||||||
intl.formatMessage({
|
intl.formatMessage({
|
||||||
defaultMessage: "Failed to add to calendar",
|
defaultMessage: "Failed to add to calendar",
|
||||||
@@ -45,7 +46,7 @@ export default function AddToCalendar({
|
|||||||
URL.revokeObjectURL(url)
|
URL.revokeObjectURL(url)
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Download error:", error)
|
logger.error("Download error:", error)
|
||||||
toast.error(
|
toast.error(
|
||||||
intl.formatMessage({
|
intl.formatMessage({
|
||||||
defaultMessage: "Failed to add to calendar",
|
defaultMessage: "Failed to add to calendar",
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import "client-only"
|
import "client-only"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
export const glaStorageName = "gla-storage"
|
export const glaStorageName = "gla-storage"
|
||||||
|
|
||||||
type GlaSessionData = {
|
type GlaSessionData = {
|
||||||
@@ -15,7 +17,7 @@ export function readGlaFromSessionStorage(): GlaSessionData | null {
|
|||||||
if (!glaSessionData) return null
|
if (!glaSessionData) return null
|
||||||
return JSON.parse(glaSessionData)
|
return JSON.parse(glaSessionData)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error reading from session storage:", error)
|
logger.error("Error reading from session storage:", error)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,7 +39,7 @@ export function writeGlaToSessionStorage(
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error writing to session storage:", error)
|
logger.error("Error writing to session storage:", error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { useIntl } from "react-intl"
|
|||||||
|
|
||||||
import { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
|
import { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
|
||||||
import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation"
|
import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import Body from "@scandic-hotels/design-system/Body"
|
import Body from "@scandic-hotels/design-system/Body"
|
||||||
import { Button } from "@scandic-hotels/design-system/Button"
|
import { Button } from "@scandic-hotels/design-system/Button"
|
||||||
import Checkbox from "@scandic-hotels/design-system/Form/Checkbox"
|
import Checkbox from "@scandic-hotels/design-system/Form/Checkbox"
|
||||||
@@ -180,7 +181,7 @@ export default function PaymentClient({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
console.error("Error", error)
|
logger.error("Booking error", error)
|
||||||
handlePaymentError(error.message)
|
handlePaymentError(error.message)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -195,7 +196,7 @@ export default function PaymentClient({
|
|||||||
setPriceChangeData(null)
|
setPriceChangeData(null)
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
console.error("Error", error)
|
logger.error("Price change error", error)
|
||||||
setPriceChangeData(null)
|
setPriceChangeData(null)
|
||||||
handlePaymentError(error.message)
|
handlePaymentError(error.message)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
|
import { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import type { RoomState } from "@/types/stores/enter-details"
|
import type { RoomState } from "@/types/stores/enter-details"
|
||||||
|
|
||||||
@@ -63,7 +64,7 @@ export function readPaymentInfoFromSessionStorage():
|
|||||||
if (!paymentInfoSessionData) return undefined
|
if (!paymentInfoSessionData) return undefined
|
||||||
return JSON.parse(paymentInfoSessionData)
|
return JSON.parse(paymentInfoSessionData)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error reading from session storage:", error)
|
logger.error("Error reading from session storage:", error)
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,7 +82,7 @@ export function writePaymentInfoToSessionStorage(
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error writing to session storage:", error)
|
logger.error("Error writing to session storage:", error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import { sumPackages } from "@/components/HotelReservation/utils"
|
import { sumPackages } from "@/components/HotelReservation/utils"
|
||||||
|
|
||||||
import type { RoomState } from "@/types/stores/enter-details"
|
import type { RoomState } from "@/types/stores/enter-details"
|
||||||
@@ -133,7 +135,7 @@ export function mapToPrice(rooms: RoomState[], isMember: boolean) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error(room.roomRate)
|
logger.error("Unknown roomRate", room.roomRate)
|
||||||
throw new Error(`Unknown roomRate`)
|
throw new Error(`Unknown roomRate`)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { FormProvider, useForm } from "react-hook-form"
|
|||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { myStay } from "@scandic-hotels/common/constants/routes/myStay"
|
import { myStay } from "@scandic-hotels/common/constants/routes/myStay"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import Body from "@scandic-hotels/design-system/Body"
|
import Body from "@scandic-hotels/design-system/Body"
|
||||||
import Caption from "@scandic-hotels/design-system/Caption"
|
import Caption from "@scandic-hotels/design-system/Caption"
|
||||||
import { trpc } from "@scandic-hotels/trpc/client"
|
import { trpc } from "@scandic-hotels/trpc/client"
|
||||||
@@ -48,7 +49,7 @@ export default function FindMyBooking() {
|
|||||||
router.push(`${myStay[lang]}?RefId=${encodeURIComponent(result.refId)}`)
|
router.push(`${myStay[lang]}?RefId=${encodeURIComponent(result.refId)}`)
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
console.error("Failed to create ref id", error)
|
logger.error("Failed to create ref id", error)
|
||||||
toast.error(
|
toast.error(
|
||||||
intl.formatMessage({
|
intl.formatMessage({
|
||||||
defaultMessage: "Failed to submit form, please try again later.",
|
defaultMessage: "Failed to submit form, please try again later.",
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
Ancillary,
|
Ancillary,
|
||||||
SelectedAncillary,
|
SelectedAncillary,
|
||||||
@@ -59,7 +61,7 @@ export const getAncillarySessionData = ():
|
|||||||
const storedData = sessionStorage.getItem(ancillarySessionKey)
|
const storedData = sessionStorage.getItem(ancillarySessionKey)
|
||||||
return storedData ? JSON.parse(storedData) : undefined
|
return storedData ? JSON.parse(storedData) : undefined
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error reading from session storage:", error)
|
logger.error("Error reading from session storage:", error)
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,7 +98,7 @@ export function setAncillarySessionData({
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error writing to session storage:", error)
|
logger.error("Error writing to session storage:", error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useIntl } from "react-intl"
|
|||||||
|
|
||||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||||
import { dt } from "@scandic-hotels/common/dt"
|
import { dt } from "@scandic-hotels/common/dt"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import Body from "@scandic-hotels/design-system/Body"
|
import Body from "@scandic-hotels/design-system/Body"
|
||||||
import Caption from "@scandic-hotels/design-system/Caption"
|
import Caption from "@scandic-hotels/design-system/Caption"
|
||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||||
@@ -122,7 +123,7 @@ export default function SelectedRoomPanel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!selectedProduct) {
|
if (!selectedProduct) {
|
||||||
console.error("Selected product is unknown")
|
logger.error("Selected product is unknown")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { useEffect, useRef } from "react"
|
|||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { partnerSas } from "@scandic-hotels/common/constants/routes/myPages"
|
import { partnerSas } from "@scandic-hotels/common/constants/routes/myPages"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { trpc } from "@scandic-hotels/trpc/client"
|
import { trpc } from "@scandic-hotels/trpc/client"
|
||||||
|
|
||||||
import { TIER_TO_FRIEND_MAP } from "@/constants/membershipLevels"
|
import { TIER_TO_FRIEND_MAP } from "@/constants/membershipLevels"
|
||||||
@@ -42,7 +43,7 @@ export function SASLevelUpgradeCheck() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onError() {
|
onError() {
|
||||||
console.log("[sas] something went wrong")
|
logger.error("[sas] something went wrong")
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { Dialog, Modal, ModalOverlay } from "react-aria-components"
|
|||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { benefits } from "@scandic-hotels/common/constants/routes/myPages"
|
import { benefits } from "@scandic-hotels/common/constants/routes/myPages"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
import { trpc } from "@scandic-hotels/trpc/client"
|
import { trpc } from "@scandic-hotels/trpc/client"
|
||||||
|
|
||||||
@@ -91,7 +92,7 @@ export default function SurprisesNotification({
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
console.error("Failed to unwrap surprise", error)
|
logger.error("Failed to unwrap surprise", error)
|
||||||
toast.error(
|
toast.error(
|
||||||
<>
|
<>
|
||||||
{intl.formatMessage(
|
{intl.formatMessage(
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { headers } from "next/headers"
|
|||||||
import { redirect } from "next/navigation"
|
import { redirect } from "next/navigation"
|
||||||
|
|
||||||
import { overview } from "@scandic-hotels/common/constants/routes/myPages"
|
import { overview } from "@scandic-hotels/common/constants/routes/myPages"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { isValidSession } from "@scandic-hotels/trpc/utils/session"
|
import { isValidSession } from "@scandic-hotels/trpc/utils/session"
|
||||||
|
|
||||||
import { getProfile } from "@/lib/trpc/memoizedRequests"
|
import { getProfile } from "@/lib/trpc/memoizedRequests"
|
||||||
@@ -26,7 +27,9 @@ export async function ProtectedLayout({ children }: React.PropsWithChildren) {
|
|||||||
const redirectURL = `/${lang}/login?redirectTo=${redirectTo}`
|
const redirectURL = `/${lang}/login?redirectTo=${redirectTo}`
|
||||||
|
|
||||||
if (!isValidSession(session)) {
|
if (!isValidSession(session)) {
|
||||||
console.log(`[layout:protected] no session, redirecting to: ${redirectURL}`)
|
logger.debug(
|
||||||
|
`[layout:protected] no session, redirecting to: ${redirectURL}`
|
||||||
|
)
|
||||||
redirect(redirectURL)
|
redirect(redirectURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,27 +37,23 @@ export async function ProtectedLayout({ children }: React.PropsWithChildren) {
|
|||||||
|
|
||||||
if (user && "error" in user) {
|
if (user && "error" in user) {
|
||||||
// redirect(redirectURL)
|
// redirect(redirectURL)
|
||||||
console.error("[layout:protected] error in user", user)
|
logger.error("[layout:protected] error in user", user)
|
||||||
console.error(
|
|
||||||
"[layout:protected] full user: ",
|
|
||||||
JSON.stringify(user, null, 4)
|
|
||||||
)
|
|
||||||
switch (user.cause) {
|
switch (user.cause) {
|
||||||
case "unauthorized": // fall through
|
case "unauthorized": // fall through
|
||||||
case "forbidden": // fall through
|
case "forbidden": // fall through
|
||||||
case "token_expired":
|
case "token_expired":
|
||||||
console.error(
|
logger.error(
|
||||||
`[layout:protected] user error, redirecting to: ${redirectURL}`
|
`[layout:protected] user error, redirecting to: ${redirectURL}`
|
||||||
)
|
)
|
||||||
redirect(redirectURL)
|
redirect(redirectURL)
|
||||||
case "notfound":
|
case "notfound":
|
||||||
console.error(`[layout:protected] notfound user loading error`)
|
logger.error(`[layout:protected] notfound user loading error`)
|
||||||
break
|
break
|
||||||
case "unknown":
|
case "unknown":
|
||||||
console.error(`[layout:protected] unknown user loading error`)
|
logger.error(`[layout:protected] unknown user loading error`)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
console.error(`[layout:protected] unhandled user loading error`)
|
logger.error(`[layout:protected] unhandled user loading error`)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
@@ -67,7 +66,7 @@ export async function ProtectedLayout({ children }: React.PropsWithChildren) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
console.error(
|
logger.error(
|
||||||
"[layout:protected] no user found, redirecting to: ",
|
"[layout:protected] no user found, redirecting to: ",
|
||||||
redirectURL
|
redirectURL
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { useIntl } from "react-intl"
|
|||||||
import { useMediaQuery } from "usehooks-ts"
|
import { useMediaQuery } from "usehooks-ts"
|
||||||
|
|
||||||
import { dt } from "@scandic-hotels/common/dt"
|
import { dt } from "@scandic-hotels/common/dt"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { Select } from "@scandic-hotels/design-system/Select"
|
import { Select } from "@scandic-hotels/design-system/Select"
|
||||||
|
|
||||||
import useLang from "@/hooks/useLang"
|
import useLang from "@/hooks/useLang"
|
||||||
@@ -104,7 +105,7 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) {
|
|||||||
? parseDate(currentDateValue)
|
? parseDate(currentDateValue)
|
||||||
: null
|
: null
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn("Known error for parse date in DateSelect: ", error)
|
logger.warn("Known error for parse date in DateSelect: ", error)
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { phoneErrors } from "@scandic-hotels/common/utils/zod/phoneValidator"
|
import { phoneErrors } from "@scandic-hotels/common/utils/zod/phoneValidator"
|
||||||
import { signupErrors } from "@scandic-hotels/trpc/routers/user/schemas"
|
import { signupErrors } from "@scandic-hotels/trpc/routers/user/schemas"
|
||||||
|
|
||||||
@@ -182,7 +183,7 @@ export function getErrorMessage(intl: IntlShape, errorCode?: string) {
|
|||||||
"Reward nights can't be combined with codes or vouchers.",
|
"Reward nights can't be combined with codes or vouchers.",
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
console.warn("Error code not supported:", errorCode)
|
logger.warn("Error code not supported:", errorCode)
|
||||||
return errorCode
|
return errorCode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import type { IntlShape } from "react-intl/src/types"
|
import type { IntlShape } from "react-intl/src/types"
|
||||||
|
|
||||||
import { RoomLighting, SeatingType } from "@/types/enums/meetingRooms"
|
import { RoomLighting, SeatingType } from "@/types/enums/meetingRooms"
|
||||||
@@ -33,7 +35,7 @@ export function translateRoomLighting(option: string, intl: IntlShape) {
|
|||||||
defaultMessage: "Windows natural daylight and excellent view",
|
defaultMessage: "Windows natural daylight and excellent view",
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
console.warn(`Unsupported conference room ligthing option: ${option}`)
|
logger.warn(`Unsupported conference room ligthing option: ${option}`)
|
||||||
return intl.formatMessage({
|
return intl.formatMessage({
|
||||||
defaultMessage: "N/A",
|
defaultMessage: "N/A",
|
||||||
})
|
})
|
||||||
@@ -75,7 +77,7 @@ export function translateSeatingType(type: string, intl: IntlShape) {
|
|||||||
defaultMessage: "U-shape",
|
defaultMessage: "U-shape",
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
console.warn(`Unsupported conference room type : ${type}`)
|
logger.warn(`Unsupported conference room type : ${type}`)
|
||||||
return intl.formatMessage({
|
return intl.formatMessage({
|
||||||
defaultMessage: "N/A",
|
defaultMessage: "N/A",
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
type UseFromSubscribe,
|
type UseFromSubscribe,
|
||||||
} from "react-hook-form"
|
} from "react-hook-form"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { trpc } from "@scandic-hotels/trpc/client"
|
import { trpc } from "@scandic-hotels/trpc/client"
|
||||||
|
|
||||||
import useRouterTransitionStore from "@/stores/router-transition"
|
import useRouterTransitionStore from "@/stores/router-transition"
|
||||||
@@ -215,13 +216,13 @@ const trackPerformance = async ({
|
|||||||
try {
|
try {
|
||||||
pageLoadTime = await promiseWithTimeout(getPageLoadTimeEntry(), 3000)
|
pageLoadTime = await promiseWithTimeout(getPageLoadTimeEntry(), 3000)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error obtaining pageLoadTime:", error)
|
logger.error("Error obtaining pageLoadTime:", error)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
lcpTime = await promiseWithTimeout(getLCPTimeEntry(), 3000)
|
lcpTime = await promiseWithTimeout(getLCPTimeEntry(), 3000)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error obtaining lcpTime:", error)
|
logger.error("Error obtaining lcpTime:", error)
|
||||||
}
|
}
|
||||||
|
|
||||||
const trackingData = {
|
const trackingData = {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useCallback, useEffect, useState } from "react"
|
import { useCallback, useEffect, useState } from "react"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import {
|
import {
|
||||||
type AutoCompleteLocation,
|
type AutoCompleteLocation,
|
||||||
autoCompleteLocationSchema,
|
autoCompleteLocationSchema,
|
||||||
@@ -25,7 +26,7 @@ export function useSearchHistory() {
|
|||||||
|
|
||||||
return existingHistory
|
return existingHistory
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to parse search history:", error)
|
logger.error("Failed to parse search history:", error)
|
||||||
localStorage.removeItem(KEY)
|
localStorage.removeItem(KEY)
|
||||||
|
|
||||||
return []
|
return []
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
import { IntlProvider } from "react-intl"
|
import { IntlProvider } from "react-intl"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import type { ClientIntlProviderProps } from "@/types/i18n"
|
import type { ClientIntlProviderProps } from "@/types/i18n"
|
||||||
|
|
||||||
const logged: Record<string, boolean> = {}
|
const logged: Record<string, boolean> = {}
|
||||||
@@ -29,7 +31,7 @@ export default function ClientIntlProvider({
|
|||||||
|
|
||||||
if (!logged[msg]) {
|
if (!logged[msg]) {
|
||||||
logged[msg] = true
|
logged[msg] = true
|
||||||
console.warn(err)
|
logger.warn("IntlProvider", err)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// https://docs.lokalise.com/en/articles/3229161-structured-json
|
// https://docs.lokalise.com/en/articles/3229161-structured-json
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import type { LokaliseMessageDescriptor } from "@/types/intl"
|
import type { LokaliseMessageDescriptor } from "@/types/intl"
|
||||||
|
|
||||||
type TranslationEntry = {
|
type TranslationEntry = {
|
||||||
@@ -28,7 +30,7 @@ export function format(
|
|||||||
|
|
||||||
if (description) {
|
if (description) {
|
||||||
if (typeof description === "string") {
|
if (typeof description === "string") {
|
||||||
console.warn(
|
logger.warn(
|
||||||
`Unsupported type for description, expected 'object', got ${typeof context}. Skipping!`,
|
`Unsupported type for description, expected 'object', got ${typeof context}. Skipping!`,
|
||||||
msg
|
msg
|
||||||
)
|
)
|
||||||
@@ -39,7 +41,7 @@ export function format(
|
|||||||
if (typeof context === "string") {
|
if (typeof context === "string") {
|
||||||
entry.context = context
|
entry.context = context
|
||||||
} else {
|
} else {
|
||||||
console.warn(
|
logger.warn(
|
||||||
`Unsupported type for context, expected 'string', got ${typeof context}`,
|
`Unsupported type for context, expected 'string', got ${typeof context}`,
|
||||||
msg
|
msg
|
||||||
)
|
)
|
||||||
@@ -50,7 +52,7 @@ export function format(
|
|||||||
if (limit && typeof limit === "number") {
|
if (limit && typeof limit === "number") {
|
||||||
entry.limit = limit
|
entry.limit = limit
|
||||||
} else {
|
} else {
|
||||||
console.warn(
|
logger.warn(
|
||||||
`Unsupported type for limit, expected 'number', got ${typeof limit}`,
|
`Unsupported type for limit, expected 'number', got ${typeof limit}`,
|
||||||
msg
|
msg
|
||||||
)
|
)
|
||||||
@@ -64,7 +66,7 @@ export function format(
|
|||||||
entry.tags = tagArray
|
entry.tags = tagArray
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.warn(
|
logger.warn(
|
||||||
`Unsupported type for tags, expected Array, got ${typeof tags}`,
|
`Unsupported type for tags, expected Array, got ${typeof tags}`,
|
||||||
msg
|
msg
|
||||||
)
|
)
|
||||||
@@ -75,7 +77,7 @@ export function format(
|
|||||||
|
|
||||||
results[id] = entry
|
results[id] = entry
|
||||||
} else {
|
} else {
|
||||||
console.warn(
|
logger.warn(
|
||||||
`Skipping message, unsupported type for defaultMessage, expected string, got ${typeof defaultMessage}`,
|
`Skipping message, unsupported type for defaultMessage, expected string, got ${typeof defaultMessage}`,
|
||||||
{
|
{
|
||||||
id,
|
id,
|
||||||
|
|||||||
@@ -4,16 +4,12 @@ import { performance, PerformanceObserver } from "node:perf_hooks"
|
|||||||
import { LokaliseApi } from "@lokalise/node-api"
|
import { LokaliseApi } from "@lokalise/node-api"
|
||||||
import AdmZip from "adm-zip"
|
import AdmZip from "adm-zip"
|
||||||
|
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
|
|
||||||
const projectId = "4194150766ff28c418f010.39532200"
|
const projectId = "4194150766ff28c418f010.39532200"
|
||||||
const lokaliseApi = new LokaliseApi({ apiKey: process.env.LOKALISE_API_KEY })
|
const lokaliseApi = new LokaliseApi({ apiKey: process.env.LOKALISE_API_KEY })
|
||||||
|
|
||||||
function log(msg: string, ...args: any[]) {
|
const lokaliseLogger = createLogger("lokalise")
|
||||||
console.log(`[lokalise] ${msg}`, ...args)
|
|
||||||
}
|
|
||||||
|
|
||||||
function error(msg: string, ...args: any[]) {
|
|
||||||
console.error(`[lokalise] ${msg}`, ...args)
|
|
||||||
}
|
|
||||||
|
|
||||||
let resolvePerf: (value?: unknown) => void
|
let resolvePerf: (value?: unknown) => void
|
||||||
const performanceMetrics = new Promise((resolve) => {
|
const performanceMetrics = new Promise((resolve) => {
|
||||||
@@ -31,7 +27,9 @@ const perf = new PerformanceObserver((items) => {
|
|||||||
resolvePerf()
|
resolvePerf()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log(`[metrics] ${entry.name} completed in ${entry.duration} ms`)
|
lokaliseLogger.info(
|
||||||
|
`[metrics] ${entry.name} completed in ${entry.duration} ms`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
performance.clearMeasures()
|
performance.clearMeasures()
|
||||||
@@ -43,7 +41,7 @@ async function waitUntilUploadDone(processId: string) {
|
|||||||
try {
|
try {
|
||||||
performance.mark("waitUntilUploadDoneStart")
|
performance.mark("waitUntilUploadDoneStart")
|
||||||
|
|
||||||
log("Checking upload status...")
|
lokaliseLogger.debug("Checking upload status...")
|
||||||
|
|
||||||
performance.mark("getProcessStart")
|
performance.mark("getProcessStart")
|
||||||
const process = await lokaliseApi.queuedProcesses().get(processId, {
|
const process = await lokaliseApi.queuedProcesses().get(processId, {
|
||||||
@@ -56,7 +54,7 @@ async function waitUntilUploadDone(processId: string) {
|
|||||||
"getProcessEnd"
|
"getProcessEnd"
|
||||||
)
|
)
|
||||||
|
|
||||||
log(`Status: ${process.status}`)
|
lokaliseLogger.debug(`Status: ${process.status}`)
|
||||||
|
|
||||||
if (process.status === "finished") {
|
if (process.status === "finished") {
|
||||||
clearInterval(interval)
|
clearInterval(interval)
|
||||||
@@ -72,8 +70,8 @@ async function waitUntilUploadDone(processId: string) {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
clearInterval(interval)
|
clearInterval(interval)
|
||||||
error("An error occurred:", e)
|
lokaliseLogger.error("An error occurred:", e)
|
||||||
performance.mark("waitUntilUploadDoneEnd", { detail: error })
|
performance.mark("waitUntilUploadDoneEnd", { detail: e })
|
||||||
performance.measure(
|
performance.measure(
|
||||||
"Wait on upload",
|
"Wait on upload",
|
||||||
"waitUntilUploadDoneStart",
|
"waitUntilUploadDoneStart",
|
||||||
@@ -89,7 +87,7 @@ export async function upload(filepath: string) {
|
|||||||
perf.observe({ type: "measure" })
|
perf.observe({ type: "measure" })
|
||||||
|
|
||||||
try {
|
try {
|
||||||
log(`Uploading ${filepath}...`)
|
lokaliseLogger.debug(`Uploading ${filepath}...`)
|
||||||
|
|
||||||
performance.mark("uploadStart")
|
performance.mark("uploadStart")
|
||||||
|
|
||||||
@@ -130,9 +128,9 @@ export async function upload(filepath: string) {
|
|||||||
"lokaliseUploadEnd"
|
"lokaliseUploadEnd"
|
||||||
)
|
)
|
||||||
|
|
||||||
log("Upload successful")
|
lokaliseLogger.debug("Upload successful")
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error("Upload failed", e)
|
lokaliseLogger.error("Upload failed", e)
|
||||||
} finally {
|
} finally {
|
||||||
performance.mark("uploadEnd")
|
performance.mark("uploadEnd")
|
||||||
|
|
||||||
@@ -148,7 +146,7 @@ export async function download(extractPath: string, all: boolean = false) {
|
|||||||
perf.observe({ type: "measure" })
|
perf.observe({ type: "measure" })
|
||||||
|
|
||||||
try {
|
try {
|
||||||
log(
|
lokaliseLogger.debug(
|
||||||
all
|
all
|
||||||
? "Downloading all translations..."
|
? "Downloading all translations..."
|
||||||
: "Downloading filtered translations..."
|
: "Downloading filtered translations..."
|
||||||
@@ -199,12 +197,12 @@ export async function download(extractPath: string, all: boolean = false) {
|
|||||||
"unpackTranslationsEnd"
|
"unpackTranslationsEnd"
|
||||||
)
|
)
|
||||||
|
|
||||||
log("Download successful")
|
lokaliseLogger.debug("Download successful")
|
||||||
} else {
|
} else {
|
||||||
throw bundleResponse
|
throw bundleResponse
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error("Download failed", e)
|
lokaliseLogger.error("Download failed", e)
|
||||||
} finally {
|
} finally {
|
||||||
performance.mark("downloadEnd")
|
performance.mark("downloadEnd")
|
||||||
|
|
||||||
@@ -251,11 +249,13 @@ export async function deleteBulk(keyNames: string[]) {
|
|||||||
.keys()
|
.keys()
|
||||||
.bulk_delete(keysToDelete, { project_id: projectId })
|
.bulk_delete(keysToDelete, { project_id: projectId })
|
||||||
|
|
||||||
log(`Bulk delete successful, removed ${keysToDelete.length} keys`)
|
lokaliseLogger.debug(
|
||||||
|
`Bulk delete successful, removed ${keysToDelete.length} keys`
|
||||||
|
)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error("Bulk delete failed", e)
|
lokaliseLogger.error("Bulk delete failed", e)
|
||||||
} finally {
|
} finally {
|
||||||
performance.mark("bulkDeleteEnd")
|
performance.mark("bulkDeleteEnd")
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import { TRPCClientError } from "@trpc/client"
|
import { TRPCClientError } from "@trpc/client"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { SessionExpiredError } from "@scandic-hotels/trpc/errors"
|
import { SessionExpiredError } from "@scandic-hotels/trpc/errors"
|
||||||
import { TrpcProvider as InternalTrpcProvider } from "@scandic-hotels/trpc/Provider"
|
import { TrpcProvider as InternalTrpcProvider } from "@scandic-hotels/trpc/Provider"
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@ export default function TrpcProvider({
|
|||||||
onError={(error) => {
|
onError={(error) => {
|
||||||
if (error instanceof TRPCClientError) {
|
if (error instanceof TRPCClientError) {
|
||||||
const appError: TRPCClientError<AnyTRPCRouter> = error
|
const appError: TRPCClientError<AnyTRPCRouter> = error
|
||||||
console.log({ appError })
|
logger.error("trpc error", { appError })
|
||||||
if (appError.data?.code === "UNAUTHORIZED") {
|
if (appError.data?.code === "UNAUTHORIZED") {
|
||||||
if (appError.data?.cause instanceof SessionExpiredError) {
|
if (appError.data?.cause instanceof SessionExpiredError) {
|
||||||
const loginUrl = login[lang]
|
const loginUrl = login[lang]
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { cookies, headers } from "next/headers"
|
|||||||
import { redirect } from "next/navigation"
|
import { redirect } from "next/navigation"
|
||||||
|
|
||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
import { createContext } from "@scandic-hotels/trpc/context"
|
import { createContext } from "@scandic-hotels/trpc/context"
|
||||||
import {
|
import {
|
||||||
appServerClient,
|
appServerClient,
|
||||||
@@ -50,6 +51,7 @@ export async function createAppContext() {
|
|||||||
|
|
||||||
configureServerClient(createAppContext)
|
configureServerClient(createAppContext)
|
||||||
|
|
||||||
|
const serverClientLogger = createLogger("serverClient")
|
||||||
export async function serverClient() {
|
export async function serverClient() {
|
||||||
const ctx = await createAppContext()
|
const ctx = await createAppContext()
|
||||||
|
|
||||||
@@ -71,17 +73,18 @@ export async function serverClient() {
|
|||||||
|
|
||||||
if (webviews.includes(fullPathname)) {
|
if (webviews.includes(fullPathname)) {
|
||||||
const redirectUrl = `/${lang}/webview/refresh?returnurl=${encodeURIComponent(fullPathname)}`
|
const redirectUrl = `/${lang}/webview/refresh?returnurl=${encodeURIComponent(fullPathname)}`
|
||||||
console.error(
|
serverClientLogger.error(
|
||||||
"Unautorized in webview, redirecting to: ",
|
"Unautorized in webview, redirecting to: ",
|
||||||
redirectUrl
|
redirectUrl
|
||||||
)
|
)
|
||||||
|
|
||||||
console.log(`[serverClient] onError redirecting to: ${redirectUrl}`)
|
|
||||||
redirect(redirectUrl)
|
redirect(redirectUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
const redirectUrl = `${login[lang]}?redirectTo=${encodeURIComponent(`/${lang}/${pathname}`)}`
|
const redirectUrl = `${login[lang]}?redirectTo=${encodeURIComponent(`/${lang}/${pathname}`)}`
|
||||||
console.log(`[serverClient] onError redirecting to: ${redirectUrl}`)
|
serverClientLogger.error(
|
||||||
|
`[serverClient] onError redirecting to: ${redirectUrl}`
|
||||||
|
)
|
||||||
redirect(redirectUrl)
|
redirect(redirectUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import * as Sentry from "@sentry/nextjs"
|
|||||||
import { type NextMiddleware, NextResponse } from "next/server"
|
import { type NextMiddleware, NextResponse } from "next/server"
|
||||||
|
|
||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { findLang } from "@scandic-hotels/common/utils/languages"
|
import { findLang } from "@scandic-hotels/common/utils/languages"
|
||||||
|
|
||||||
import * as authRequired from "@/middlewares/authRequired"
|
import * as authRequired from "@/middlewares/authRequired"
|
||||||
@@ -92,7 +93,7 @@ export const middleware: NextMiddleware = async (request, event) => {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof NextResponse && e.status) {
|
if (e instanceof NextResponse && e.status) {
|
||||||
const cause = await e.json()
|
const cause = await e.json()
|
||||||
console.error(`NextResponse Error in middleware`, cause)
|
logger.error(`NextResponse Error in middleware`, cause)
|
||||||
Sentry.captureException(cause)
|
Sentry.captureException(cause)
|
||||||
|
|
||||||
return NextResponse.rewrite(
|
return NextResponse.rewrite(
|
||||||
@@ -107,7 +108,7 @@ export const middleware: NextMiddleware = async (request, event) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error(`Error in middleware`, e)
|
logger.error(`Error in middleware`, e)
|
||||||
Sentry.captureException(e)
|
Sentry.captureException(e)
|
||||||
|
|
||||||
return NextResponse.rewrite(
|
return NextResponse.rewrite(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { type NextMiddleware, NextResponse } from "next/server"
|
import { type NextMiddleware, NextResponse } from "next/server"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { findLang } from "@scandic-hotels/common/utils/languages"
|
import { findLang } from "@scandic-hotels/common/utils/languages"
|
||||||
|
|
||||||
import { authRequired, mfaRequired } from "@/constants/routes/authRequired"
|
import { authRequired, mfaRequired } from "@/constants/routes/authRequired"
|
||||||
@@ -89,7 +90,7 @@ export const middleware = auth(async (request) => {
|
|||||||
const redirectOpts = {
|
const redirectOpts = {
|
||||||
headers,
|
headers,
|
||||||
}
|
}
|
||||||
console.log(`[authRequired] redirecting to: ${redirectUrl}`, redirectOpts)
|
logger.debug(`[authRequired] redirecting to: ${redirectUrl}`, redirectOpts)
|
||||||
return NextResponse.redirect(redirectUrl, redirectOpts)
|
return NextResponse.redirect(redirectUrl, redirectOpts)
|
||||||
}) as unknown as NextMiddleware // See comment above
|
}) as unknown as NextMiddleware // See comment above
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
profile,
|
profile,
|
||||||
profileEdit,
|
profileEdit,
|
||||||
} from "@scandic-hotels/common/constants/routes/myPages"
|
} from "@scandic-hotels/common/constants/routes/myPages"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { findLang } from "@scandic-hotels/common/utils/languages"
|
import { findLang } from "@scandic-hotels/common/utils/languages"
|
||||||
import { resolve as resolveEntry } from "@scandic-hotels/trpc/utils/entry"
|
import { resolve as resolveEntry } from "@scandic-hotels/trpc/utils/entry"
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ export const middleware: NextMiddleware = async (request) => {
|
|||||||
const nextUrlPublic = getPublicNextURL(request)
|
const nextUrlPublic = getPublicNextURL(request)
|
||||||
const overviewUrl = overview[lang]
|
const overviewUrl = overview[lang]
|
||||||
const redirectUrl = new URL(overviewUrl, nextUrlPublic)
|
const redirectUrl = new URL(overviewUrl, nextUrlPublic)
|
||||||
console.log(`[myPages] redirecting to: ${redirectUrl}`)
|
logger.debug(`[myPages] redirecting to: ${redirectUrl}`)
|
||||||
return NextResponse.redirect(redirectUrl, {
|
return NextResponse.redirect(redirectUrl, {
|
||||||
status: 308,
|
status: 308,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { type NextMiddleware, NextResponse } from "next/server"
|
import { type NextMiddleware, NextResponse } from "next/server"
|
||||||
|
|
||||||
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { findLang } from "@scandic-hotels/common/utils/languages"
|
import { findLang } from "@scandic-hotels/common/utils/languages"
|
||||||
|
|
||||||
import { notFound } from "@/server/errors/next"
|
import { notFound } from "@/server/errors/next"
|
||||||
@@ -65,7 +66,7 @@ export const middleware: NextMiddleware = async (request) => {
|
|||||||
headers.set("x-continue", "1")
|
headers.set("x-continue", "1")
|
||||||
return NextResponse.next({ headers })
|
return NextResponse.next({ headers })
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Redirect error: ", e)
|
logger.error("Redirect error: ", e)
|
||||||
throw notFound()
|
throw notFound()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { type NextMiddleware, NextResponse } from "next/server"
|
import { type NextMiddleware, NextResponse } from "next/server"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { findLang } from "@scandic-hotels/common/utils/languages"
|
import { findLang } from "@scandic-hotels/common/utils/languages"
|
||||||
import { resolve as resolveEntry } from "@scandic-hotels/trpc/utils/entry"
|
import { resolve as resolveEntry } from "@scandic-hotels/trpc/utils/entry"
|
||||||
|
|
||||||
@@ -92,7 +93,7 @@ export const middleware: NextMiddleware = async (request) => {
|
|||||||
// Authorization header is required for webviews
|
// Authorization header is required for webviews
|
||||||
// It should be base64 encoded
|
// It should be base64 encoded
|
||||||
if (!authorizationToken) {
|
if (!authorizationToken) {
|
||||||
console.error("Authorization header is missing")
|
logger.error("Authorization header is missing")
|
||||||
return badRequest("Authorization header is missing")
|
return badRequest("Authorization header is missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +101,7 @@ export const middleware: NextMiddleware = async (request) => {
|
|||||||
// It should be base64 encoded
|
// It should be base64 encoded
|
||||||
const initializationVector = request.headers.get("X-AES-IV")!
|
const initializationVector = request.headers.get("X-AES-IV")!
|
||||||
if (!initializationVector) {
|
if (!initializationVector) {
|
||||||
console.error("initializationVector header is missing")
|
logger.error("initializationVector header is missing")
|
||||||
return badRequest("initializationVector header is missing")
|
return badRequest("initializationVector header is missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,8 +122,7 @@ export const middleware: NextMiddleware = async (request) => {
|
|||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error) {
|
if (e instanceof Error) {
|
||||||
console.error("Error in webView middleware")
|
logger.error(`Error in webView middleware - ${e.name}: ${e.message}`)
|
||||||
console.error(`${e.name}: ${e.message}`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return badRequest()
|
return badRequest()
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
|
|
||||||
import type { Lang } from "@scandic-hotels/common/constants/language"
|
import type { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
|
|
||||||
export async function warmupHotelDataOnLang(lang: Lang) {
|
export async function warmupHotelDataOnLang(lang: Lang) {
|
||||||
|
const warmupHotelDataOnLangLogger = createLogger("warmupHotelDataOnLang")
|
||||||
const PUBLIC_URL = Netlify.env.get("PUBLIC_URL")
|
const PUBLIC_URL = Netlify.env.get("PUBLIC_URL")
|
||||||
console.info(
|
|
||||||
|
warmupHotelDataOnLangLogger.info(
|
||||||
`[WARMUP] Started warmup cache hoteldata for language ${lang} at: ${new Date().toISOString()}!`
|
`[WARMUP] Started warmup cache hoteldata for language ${lang} at: ${new Date().toISOString()}!`
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -22,9 +26,11 @@ export async function warmupHotelDataOnLang(lang: Lang) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const hotels = await hotelsResponse.json()
|
const hotels = await hotelsResponse.json()
|
||||||
console.info(`[WARMUP] Retrieved ${hotels.length} hotels.`)
|
warmupHotelDataOnLangLogger.info(
|
||||||
|
`[WARMUP] Retrieved ${hotels.length} hotels.`
|
||||||
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(
|
warmupHotelDataOnLangLogger.error(
|
||||||
`[WARMUP] Error warming cache with hoteldata on language ${lang} with error: ${error}`
|
`[WARMUP] Error warming cache with hoteldata on language ${lang} with error: ${error}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { NextRequest } from "next/server"
|
import { NextRequest } from "next/server"
|
||||||
|
|
||||||
import { env } from "@/env/server"
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
|
import { env } from "@/env/server"
|
||||||
/**
|
/**
|
||||||
* Use this function when you want to create URLs that are public facing, for
|
* Use this function when you want to create URLs that are public facing, for
|
||||||
* example for redirects or redirectTo query parameters.
|
* example for redirects or redirectTo query parameters.
|
||||||
@@ -67,7 +68,7 @@ export function getInternalNextURL(request: NextRequest) {
|
|||||||
|
|
||||||
const originHeader = request.headers.get("x-sh-origin")
|
const originHeader = request.headers.get("x-sh-origin")
|
||||||
if (originHeader) {
|
if (originHeader) {
|
||||||
console.log(`[internalNextUrl] using x-sh-origin header`, {
|
logger.debug(`[internalNextUrl] using x-sh-origin header`, {
|
||||||
origin,
|
origin,
|
||||||
originHeader,
|
originHeader,
|
||||||
newOrigin: href.replace(origin, originHeader),
|
newOrigin: href.replace(origin, originHeader),
|
||||||
@@ -78,7 +79,7 @@ export function getInternalNextURL(request: NextRequest) {
|
|||||||
const hostHeader = request.headers.get("host")
|
const hostHeader = request.headers.get("host")
|
||||||
if (hostHeader) {
|
if (hostHeader) {
|
||||||
const inputHostOrigin = `${request.nextUrl.protocol}//${hostHeader}`
|
const inputHostOrigin = `${request.nextUrl.protocol}//${hostHeader}`
|
||||||
console.log(`[internalNextUrl] using host header`, {
|
logger.debug(`[internalNextUrl] using host header`, {
|
||||||
origin,
|
origin,
|
||||||
hostHeader,
|
hostHeader,
|
||||||
hostOrigin: inputHostOrigin,
|
hostOrigin: inputHostOrigin,
|
||||||
@@ -88,6 +89,6 @@ export function getInternalNextURL(request: NextRequest) {
|
|||||||
return new NextRequest(href.replace(origin, hostOrigin), request).nextUrl
|
return new NextRequest(href.replace(origin, hostOrigin), request).nextUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[internalNextUrl] falling back to incoming request`)
|
logger.debug(`[internalNextUrl] falling back to incoming request`)
|
||||||
return request.nextUrl
|
return request.nextUrl
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
import { getServiceToken } from "@scandic-hotels/common/tokenManager"
|
import { getServiceToken } from "@scandic-hotels/common/tokenManager"
|
||||||
import { safeTry } from "@scandic-hotels/common/utils/safeTry"
|
import { safeTry } from "@scandic-hotels/common/utils/safeTry"
|
||||||
import {
|
import {
|
||||||
@@ -10,6 +11,7 @@ import type { WarmupFunction, WarmupResult } from "."
|
|||||||
|
|
||||||
export const warmupHotelIdsByCountry =
|
export const warmupHotelIdsByCountry =
|
||||||
(): WarmupFunction => async (): Promise<WarmupResult> => {
|
(): WarmupFunction => async (): Promise<WarmupResult> => {
|
||||||
|
const warmupLogger = createLogger("warmupHotelIdsByCountry")
|
||||||
try {
|
try {
|
||||||
let serviceToken = await getServiceToken()
|
let serviceToken = await getServiceToken()
|
||||||
|
|
||||||
@@ -39,7 +41,7 @@ export const warmupHotelIdsByCountry =
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error(
|
warmupLogger.error(
|
||||||
`[Warmup]: Error fetching hotel IDs for ${countryName}:`,
|
`[Warmup]: Error fetching hotel IDs for ${countryName}:`,
|
||||||
error
|
error
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import isEqual from "fast-deep-equal"
|
|||||||
import { parsePhoneNumberFromString } from "libphonenumber-js"
|
import { parsePhoneNumberFromString } from "libphonenumber-js"
|
||||||
|
|
||||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { RateTypeEnum } from "@scandic-hotels/trpc/enums/rateType"
|
import { RateTypeEnum } from "@scandic-hotels/trpc/enums/rateType"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -279,7 +280,7 @@ export function readFromSessionStorage(): PersistedState | undefined {
|
|||||||
|
|
||||||
return parsedData
|
return parsedData
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error reading from session storage:", error)
|
logger.error("Error reading from session storage:", error)
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -292,7 +293,7 @@ export function writeToSessionStorage(state: PersistedState) {
|
|||||||
try {
|
try {
|
||||||
sessionStorage.setItem(detailsStorageName, JSON.stringify(state))
|
sessionStorage.setItem(detailsStorageName, JSON.stringify(state))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error writing to session storage:", error)
|
logger.error("Error writing to session storage:", error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import type { Session } from "next-auth"
|
import type { Session } from "next-auth"
|
||||||
|
|
||||||
export function isValidClientSession(session: Session | null) {
|
export function isValidClientSession(session: Session | null) {
|
||||||
@@ -5,16 +7,16 @@ export function isValidClientSession(session: Session | null) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (session.error) {
|
if (session.error) {
|
||||||
console.log(`Session error: ${session.error}`)
|
logger.error(`Session error: ${session.error}`)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session.token.error) {
|
if (session.token.error) {
|
||||||
console.log(`Session token error: ${session.token.error}`)
|
logger.error(`Session token error: ${session.token.error}`)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (session.token.expires_at && session.token.expires_at < Date.now()) {
|
if (session.token.expires_at && session.token.expires_at < Date.now()) {
|
||||||
console.log(`Session expired: ${session.token.expires_at}`)
|
logger.error(`Session expired: ${session.token.expires_at}`)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
export function createLogger(loggerPrefix: string | (() => Promise<string>)) {
|
|
||||||
const getLoggerPrefix: () => Promise<string> =
|
|
||||||
typeof loggerPrefix === "string" ? async () => loggerPrefix : loggerPrefix
|
|
||||||
|
|
||||||
return {
|
|
||||||
async debug(message: string, ...args: unknown[]): Promise<void> {
|
|
||||||
console.debug(`[${await getLoggerPrefix()}] ${message}`, ...args)
|
|
||||||
},
|
|
||||||
async warn(message: string, ...args: unknown[]): Promise<void> {
|
|
||||||
console.warn(`[${await getLoggerPrefix()}] Warning - ${message}`, ...args)
|
|
||||||
},
|
|
||||||
async error(message: string, ...args: unknown[]): Promise<void> {
|
|
||||||
console.error(`[${await getLoggerPrefix()}] Error - ${message}`, ...args)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
import parsePhoneNumberFromString, { type CountryCode } from "libphonenumber-js"
|
import parsePhoneNumberFromString, { type CountryCode } from "libphonenumber-js"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
export function formatPhoneNumber(
|
export function formatPhoneNumber(
|
||||||
phoneNumber: string,
|
phoneNumber: string,
|
||||||
phoneNumberCC?: string | null
|
phoneNumberCC?: string | null
|
||||||
@@ -16,7 +18,7 @@ export function formatPhoneNumber(
|
|||||||
: parsePhoneNumberFromString(normalized)
|
: parsePhoneNumberFromString(normalized)
|
||||||
|
|
||||||
if (!parsedPhonenumber?.isValid()) {
|
if (!parsedPhonenumber?.isValid()) {
|
||||||
console.warn(
|
logger.warn(
|
||||||
`Invalid phone number: ${phoneNumber} with country code: ${phoneNumberCC}`,
|
`Invalid phone number: ${phoneNumber} with country code: ${phoneNumberCC}`,
|
||||||
parsedPhonenumber
|
parsedPhonenumber
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
import { SESSION_ID_KEY_NAME } from "@/hooks/useSessionId"
|
import { SESSION_ID_KEY_NAME } from "@/hooks/useSessionId"
|
||||||
|
|
||||||
export function trackEvent(data: any) {
|
export function trackEvent(data: any) {
|
||||||
@@ -11,7 +13,7 @@ export function trackEvent(data: any) {
|
|||||||
try {
|
try {
|
||||||
sessionId = sessionStorage.getItem(SESSION_ID_KEY_NAME) ?? ""
|
sessionId = sessionStorage.getItem(SESSION_ID_KEY_NAME) ?? ""
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Error getting sessionId from sessionStorage", e)
|
logger.error("Error getting sessionId from sessionStorage", e)
|
||||||
}
|
}
|
||||||
|
|
||||||
data = { ...data, siteVersion: "new-web", sessionId }
|
data = { ...data, siteVersion: "new-web", sessionId }
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { BreakfastPackageEnum } from "@scandic-hotels/trpc/enums/breakfast"
|
import { BreakfastPackageEnum } from "@scandic-hotels/trpc/enums/breakfast"
|
||||||
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
|
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@ export function parseBookingWidgetSearchParams(
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[URL] Error parsing search params for booking widget:", error)
|
logger.error("[URL] Error parsing search params for booking widget:", error)
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,7 +119,7 @@ export function parseSelectHotelSearchParams(
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[URL] Error parsing search params for select hotel:", error)
|
logger.error("[URL] Error parsing search params for select hotel:", error)
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -168,7 +169,7 @@ export function parseSelectRateSearchParams(
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[URL] Error parsing search params for select rate:", error)
|
logger.error("[URL] Error parsing search params for select rate:", error)
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -216,7 +217,7 @@ export function parseDetailsSearchParams(
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[URL] Error parsing search params for details:", error)
|
logger.error("[URL] Error parsing search params for details:", error)
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,6 @@
|
|||||||
export const cacheLogger = {
|
import { createLogger } from "../logger/createLogger"
|
||||||
async debug(message: string, ...args: unknown[]): Promise<void> {
|
|
||||||
console.debug(`${await loggerPrefix()} ${message}`, ...args)
|
export const cacheLogger = createLogger(loggerPrefix)
|
||||||
},
|
|
||||||
async warn(message: string, ...args: unknown[]): Promise<void> {
|
|
||||||
console.warn(`${await loggerPrefix()} Warning - ${message}`, ...args)
|
|
||||||
},
|
|
||||||
async error(message: string, ...args: unknown[]): Promise<void> {
|
|
||||||
console.error(`${await loggerPrefix()} Error - ${message}`, ...args)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loggerPrefix() {
|
async function loggerPrefix() {
|
||||||
const instancePrefix = await getCachePrefix()
|
const instancePrefix = await getCachePrefix()
|
||||||
|
|||||||
44
packages/common/logger/createLogger.ts
Normal file
44
packages/common/logger/createLogger.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
export function createLogger(loggerPrefix: string | (() => Promise<string>)) {
|
||||||
|
const asyncWrapper: () => Promise<string> =
|
||||||
|
typeof loggerPrefix === "string" ? async () => loggerPrefix : loggerPrefix
|
||||||
|
|
||||||
|
const getLoggerPrefix = async () => {
|
||||||
|
const prefix = await asyncWrapper()
|
||||||
|
if (!prefix) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return `[${prefix}]`
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
async debug(message: string, ...args: unknown[]): Promise<void> {
|
||||||
|
// TODO: Make this configurable
|
||||||
|
if (process.env.NODE_ENV !== "development") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.debug(
|
||||||
|
"\x1b[36m%s\x1b[0m",
|
||||||
|
`${await getLoggerPrefix()} ${message}`.trim(),
|
||||||
|
...args
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
async info(message: string, ...args: unknown[]): Promise<void> {
|
||||||
|
console.info(`${await getLoggerPrefix()} ${message}`.trim(), ...args)
|
||||||
|
},
|
||||||
|
async warn(message: string, ...args: unknown[]): Promise<void> {
|
||||||
|
console.warn(
|
||||||
|
`${await getLoggerPrefix()} [warn] - ${message}`.trim(),
|
||||||
|
...args
|
||||||
|
)
|
||||||
|
},
|
||||||
|
async error(message: string, ...args: unknown[]): Promise<void> {
|
||||||
|
console.error(
|
||||||
|
`${await getLoggerPrefix()} [error] - ${message}`.trim(),
|
||||||
|
...args
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
3
packages/common/logger/index.ts
Normal file
3
packages/common/logger/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { createLogger } from "./createLogger"
|
||||||
|
|
||||||
|
export const logger = createLogger("")
|
||||||
@@ -16,6 +16,8 @@
|
|||||||
"./telemetry": "./telemetry/index.ts",
|
"./telemetry": "./telemetry/index.ts",
|
||||||
"./tokenManager": "./tokenManager/index.ts",
|
"./tokenManager": "./tokenManager/index.ts",
|
||||||
"./dt": "./dt/dt.ts",
|
"./dt": "./dt/dt.ts",
|
||||||
|
"./logger": "./logger/index.ts",
|
||||||
|
"./logger/*": "./logger/*.ts",
|
||||||
"./utils/isEdge": "./utils/isEdge.ts",
|
"./utils/isEdge": "./utils/isEdge.ts",
|
||||||
"./utils/safeTry": "./utils/safeTry.ts",
|
"./utils/safeTry": "./utils/safeTry.ts",
|
||||||
"./utils/url": "./utils/url.ts",
|
"./utils/url": "./utils/url.ts",
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ import {
|
|||||||
mapValues,
|
mapValues,
|
||||||
} from "lodash-es"
|
} from "lodash-es"
|
||||||
|
|
||||||
|
import { logger } from "../logger"
|
||||||
|
|
||||||
import type { ZodError } from "zod"
|
import type { ZodError } from "zod"
|
||||||
|
|
||||||
type AttributesInput = Record<string, unknown>
|
type AttributesInput = Record<string, unknown>
|
||||||
@@ -88,7 +90,7 @@ export function isValidAttributeValue(value: unknown): value is AttributeValue {
|
|||||||
* };
|
* };
|
||||||
*
|
*
|
||||||
* const sanitized = sanitize(input);
|
* const sanitized = sanitize(input);
|
||||||
* console.log(sanitized);
|
* logger.log(sanitized);
|
||||||
* // {
|
* // {
|
||||||
* // key1: "Example",
|
* // key1: "Example",
|
||||||
* // key2: 10,
|
* // key2: 10,
|
||||||
@@ -162,7 +164,7 @@ export function createCounter(meterName: string, counterName: string) {
|
|||||||
const finalAttrs = sanitize(mergedAttrs)
|
const finalAttrs = sanitize(mergedAttrs)
|
||||||
|
|
||||||
counter.add(1, finalAttrs)
|
counter.add(1, finalAttrs)
|
||||||
console.info(`[${fullName}] start:`, finalAttrs)
|
logger.info(`[${fullName}] start:`, finalAttrs)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -175,7 +177,7 @@ export function createCounter(meterName: string, counterName: string) {
|
|||||||
const finalAttrs = sanitize(mergedAttrs)
|
const finalAttrs = sanitize(mergedAttrs)
|
||||||
|
|
||||||
success.add(1, finalAttrs)
|
success.add(1, finalAttrs)
|
||||||
console.info(`[${fullName}] success:`, finalAttrs)
|
logger.info(`[${fullName}] success:`, finalAttrs)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -199,7 +201,7 @@ export function createCounter(meterName: string, counterName: string) {
|
|||||||
const finalAttrs = sanitize(mergedAttrs)
|
const finalAttrs = sanitize(mergedAttrs)
|
||||||
|
|
||||||
fail.add(1, finalAttrs)
|
fail.add(1, finalAttrs)
|
||||||
console.error(`[${fullName}] dataError:`, finalAttrs)
|
logger.error(`[${fullName}] dataError:`, finalAttrs)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -221,7 +223,7 @@ export function createCounter(meterName: string, counterName: string) {
|
|||||||
const finalAttrs = sanitize(mergedAttrs)
|
const finalAttrs = sanitize(mergedAttrs)
|
||||||
|
|
||||||
fail.add(1, finalAttrs)
|
fail.add(1, finalAttrs)
|
||||||
console.error(`[${fullName}] noDataError:`, finalAttrs)
|
logger.error(`[${fullName}] noDataError:`, finalAttrs)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -241,7 +243,7 @@ export function createCounter(meterName: string, counterName: string) {
|
|||||||
const finalAttrs = sanitize(mergedAttrs)
|
const finalAttrs = sanitize(mergedAttrs)
|
||||||
|
|
||||||
fail.add(1, finalAttrs)
|
fail.add(1, finalAttrs)
|
||||||
console.error(`[${fullName}] validationError:`, finalAttrs)
|
logger.error(`[${fullName}] validationError:`, finalAttrs)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -271,7 +273,7 @@ export function createCounter(meterName: string, counterName: string) {
|
|||||||
const finalAttrs = sanitize(mergedAttrs)
|
const finalAttrs = sanitize(mergedAttrs)
|
||||||
|
|
||||||
fail.add(1, finalAttrs)
|
fail.add(1, finalAttrs)
|
||||||
console.error(`[${fullName}] httpError:`, finalAttrs)
|
logger.error(`[${fullName}] httpError:`, finalAttrs)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -301,7 +303,7 @@ export function createCounter(meterName: string, counterName: string) {
|
|||||||
const finalAttrs = sanitize(mergedAttrs)
|
const finalAttrs = sanitize(mergedAttrs)
|
||||||
|
|
||||||
fail.add(1, finalAttrs)
|
fail.add(1, finalAttrs)
|
||||||
console.error(`[${fullName}] fail:`, finalAttrs)
|
logger.error(`[${fullName}] fail:`, finalAttrs)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { describe, expect, test } from "vitest"
|
import { beforeEach, describe, expect, test } from "vitest"
|
||||||
|
|
||||||
import { passwordValidator } from "./passwordValidator"
|
import { passwordValidator } from "./passwordValidator"
|
||||||
|
|
||||||
@@ -88,7 +88,6 @@ describe("Should validate password the same way as Curity", () => {
|
|||||||
curityPasswordRegex.lastIndex = 0
|
curityPasswordRegex.lastIndex = 0
|
||||||
})
|
})
|
||||||
test.each(testCases)("$description", ({ password }) => {
|
test.each(testCases)("$description", ({ password }) => {
|
||||||
console.log(password)
|
|
||||||
const curityResult = curityPasswordRegex.test(password)
|
const curityResult = curityPasswordRegex.test(password)
|
||||||
const zodResult = passwordValidator().safeParse(password)
|
const zodResult = passwordValidator().safeParse(password)
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import "server-only"
|
|||||||
import { ClientError, type GraphQLClient } from "graphql-request"
|
import { ClientError, type GraphQLClient } from "graphql-request"
|
||||||
|
|
||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
|
|
||||||
import { env } from "../../env/server"
|
import { env } from "../../env/server"
|
||||||
|
|
||||||
@@ -10,6 +11,7 @@ import type { DocumentNode } from "graphql"
|
|||||||
|
|
||||||
import type { Data } from "../types/requestData"
|
import type { Data } from "../types/requestData"
|
||||||
|
|
||||||
|
const requestLogger = createLogger("graphql-request")
|
||||||
export async function request<T>(
|
export async function request<T>(
|
||||||
client: GraphQLClient,
|
client: GraphQLClient,
|
||||||
query: string | DocumentNode,
|
query: string | DocumentNode,
|
||||||
@@ -41,13 +43,9 @@ export async function request<T>(
|
|||||||
/**
|
/**
|
||||||
* TODO: Send to Monitoring (Logging and Metrics)
|
* TODO: Send to Monitoring (Logging and Metrics)
|
||||||
*/
|
*/
|
||||||
console.log({
|
requestLogger.debug("complexity", {
|
||||||
complexityLimit: rawResponse.headers.get("x-query-complexity"),
|
complexityLimit: rawResponse.headers.get("x-query-complexity"),
|
||||||
})
|
|
||||||
console.log({
|
|
||||||
referenceDepth: rawResponse.headers.get("x-reference-depth"),
|
referenceDepth: rawResponse.headers.get("x-reference-depth"),
|
||||||
})
|
|
||||||
console.log({
|
|
||||||
resolverCost: rawResponse.headers.get("x-resolver-cost"),
|
resolverCost: rawResponse.headers.get("x-resolver-cost"),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -63,17 +61,17 @@ export async function request<T>(
|
|||||||
// @ts-expect-error: name does not exist (?)
|
// @ts-expect-error: name does not exist (?)
|
||||||
).name.value
|
).name.value
|
||||||
|
|
||||||
console.log(`[gql] Sending graphql request to ${env.CMS_URL}`, {
|
requestLogger.debug(`[gql] Sending graphql request to ${env.CMS_URL}`, {
|
||||||
operationName,
|
operationName,
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`[gql] Unable to extract operation name from query`, {
|
requestLogger.error(`[gql] Unable to extract operation name from query`, {
|
||||||
query,
|
query,
|
||||||
error: e,
|
error: e,
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(`[gql] Sending graphql request to ${env.CMS_URL}`, {
|
requestLogger.debug(`[gql] Sending graphql request to ${env.CMS_URL}`, {
|
||||||
operationName: "<Unable to extract>",
|
operationName: "<Unable to extract>",
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
@@ -94,18 +92,18 @@ export async function request<T>(
|
|||||||
// @ts-expect-error: name does not exist (?)
|
// @ts-expect-error: name does not exist (?)
|
||||||
).name.value
|
).name.value
|
||||||
|
|
||||||
console.log(`[gql] Response for ${env.CMS_URL}`, {
|
requestLogger.debug(`[gql] Response for ${env.CMS_URL}`, {
|
||||||
response,
|
response,
|
||||||
operationName,
|
operationName,
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`[gql] Unable to extract operation name from query`, {
|
requestLogger.error(`[gql] Unable to extract operation name from query`, {
|
||||||
query,
|
query,
|
||||||
error: e,
|
error: e,
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(`[gql] Response for ${env.CMS_URL}`, {
|
requestLogger.debug(`[gql] Response for ${env.CMS_URL}`, {
|
||||||
response,
|
response,
|
||||||
operationName: "<Unable to extract>",
|
operationName: "<Unable to extract>",
|
||||||
variables,
|
variables,
|
||||||
@@ -138,7 +136,7 @@ export async function request<T>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error(
|
requestLogger.error(
|
||||||
`[gql] Error sending graphql request to ${env.CMS_URL}`,
|
`[gql] Error sending graphql request to ${env.CMS_URL}`,
|
||||||
error
|
error
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import "server-only"
|
|||||||
import deepmerge from "deepmerge"
|
import deepmerge from "deepmerge"
|
||||||
import merge from "deepmerge"
|
import merge from "deepmerge"
|
||||||
|
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
|
|
||||||
import { request } from "./request"
|
import { request } from "./request"
|
||||||
|
|
||||||
import type { CacheTime } from "@scandic-hotels/common/dataCache"
|
import type { CacheTime } from "@scandic-hotels/common/dataCache"
|
||||||
@@ -18,6 +20,7 @@ export async function batchRequest<T>(
|
|||||||
}
|
}
|
||||||
})[]
|
})[]
|
||||||
): Promise<Data<T>> {
|
): Promise<Data<T>> {
|
||||||
|
const batchLogger = createLogger("graphql-batch-request")
|
||||||
try {
|
try {
|
||||||
const response = await Promise.allSettled(
|
const response = await Promise.allSettled(
|
||||||
queries.map((query) =>
|
queries.map((query) =>
|
||||||
@@ -37,15 +40,14 @@ export async function batchRequest<T>(
|
|||||||
|
|
||||||
if (reasons.length) {
|
if (reasons.length) {
|
||||||
reasons.forEach((reason) => {
|
reasons.forEach((reason) => {
|
||||||
console.error(`Batch request failed`, reason)
|
batchLogger.error(`Batch request failed`, reason)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return { data }
|
return { data }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error in batched graphql request")
|
batchLogger.error("Error in batched graphql request", error)
|
||||||
console.error(error)
|
throw error
|
||||||
throw new Error("Something went wrong")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
type CacheTime,
|
type CacheTime,
|
||||||
getCacheClient,
|
getCacheClient,
|
||||||
} from "@scandic-hotels/common/dataCache"
|
} from "@scandic-hotels/common/dataCache"
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
|
|
||||||
import { env } from "../../env/server"
|
import { env } from "../../env/server"
|
||||||
import { getPreviewHash, isPreviewByUid } from "../previewContext"
|
import { getPreviewHash, isPreviewByUid } from "../previewContext"
|
||||||
@@ -25,6 +26,8 @@ export async function request<T>(
|
|||||||
ttl: CacheTime
|
ttl: CacheTime
|
||||||
}
|
}
|
||||||
): Promise<Data<T>> {
|
): Promise<Data<T>> {
|
||||||
|
const requestLogger = createLogger("graphql-request")
|
||||||
|
|
||||||
const shouldUsePreview = variables?.uid
|
const shouldUsePreview = variables?.uid
|
||||||
? isPreviewByUid(variables.uid)
|
? isPreviewByUid(variables.uid)
|
||||||
: false
|
: false
|
||||||
@@ -33,12 +36,12 @@ export async function request<T>(
|
|||||||
internalRequest<T>(query, shouldUsePreview, variables, getPreviewHash())
|
internalRequest<T>(query, shouldUsePreview, variables, getPreviewHash())
|
||||||
|
|
||||||
if (!cacheOptions) {
|
if (!cacheOptions) {
|
||||||
console.warn("[NO CACHE] for query", query)
|
requestLogger.warn("[NO CACHE] for query", query)
|
||||||
return doCall()
|
return doCall()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldUsePreview) {
|
if (shouldUsePreview) {
|
||||||
console.log("[NO CACHE] [PREVIEW] for query", query)
|
requestLogger.debug("[NO CACHE] [PREVIEW] for query", query)
|
||||||
return doCall()
|
return doCall()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import * as Sentry from "@sentry/nextjs"
|
import * as Sentry from "@sentry/nextjs"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { getServiceToken } from "@scandic-hotels/common/tokenManager"
|
import { getServiceToken } from "@scandic-hotels/common/tokenManager"
|
||||||
|
|
||||||
import { env } from "../env/server"
|
import { env } from "../env/server"
|
||||||
@@ -68,10 +69,10 @@ export const protectedProcedure = baseProcedure.use(async function (opts) {
|
|||||||
const session = await opts.ctx.auth()
|
const session = await opts.ctx.auth()
|
||||||
|
|
||||||
if (!authRequired && env.NODE_ENV === "development") {
|
if (!authRequired && env.NODE_ENV === "development") {
|
||||||
console.info(
|
logger.debug(
|
||||||
`❌❌❌❌ You are opting out of authorization, if its done on purpose maybe you should use the publicProcedure instead. ❌❌❌❌`
|
`❌❌❌❌ You are opting out of authorization, if its done on purpose maybe you should use the publicProcedure instead. ❌❌❌❌`
|
||||||
)
|
)
|
||||||
console.info(`path: ${opts.path} | type: ${opts.type}`)
|
logger.debug(`path: ${opts.path} | type: ${opts.type}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
@@ -93,10 +94,10 @@ export const safeProtectedProcedure = baseProcedure.use(async function (opts) {
|
|||||||
const authRequired = opts.meta?.authRequired ?? true
|
const authRequired = opts.meta?.authRequired ?? true
|
||||||
let session = await opts.ctx.auth()
|
let session = await opts.ctx.auth()
|
||||||
if (!authRequired && env.NODE_ENV === "development") {
|
if (!authRequired && env.NODE_ENV === "development") {
|
||||||
console.info(
|
logger.debug(
|
||||||
`❌❌❌❌ You are opting out of authorization, if its done on purpose maybe you should use the publicProcedure instead. ❌❌❌❌`
|
`❌❌❌❌ You are opting out of authorization, if its done on purpose maybe you should use the publicProcedure instead. ❌❌❌❌`
|
||||||
)
|
)
|
||||||
console.info(`path: ${opts.path} | type: ${opts.type}`)
|
logger.debug(`path: ${opts.path} | type: ${opts.type}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!session || session.error === "RefreshAccessTokenError") {
|
if (!session || session.error === "RefreshAccessTokenError") {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
import { isDefined } from "@scandic-hotels/common/utils/isDefined"
|
import { isDefined } from "@scandic-hotels/common/utils/isDefined"
|
||||||
import { safeTry } from "@scandic-hotels/common/utils/safeTry"
|
import { safeTry } from "@scandic-hotels/common/utils/safeTry"
|
||||||
|
|
||||||
@@ -97,6 +98,7 @@ export async function getAutoCompleteDestinationsData({
|
|||||||
serviceToken: string
|
serviceToken: string
|
||||||
warmup?: boolean
|
warmup?: boolean
|
||||||
}) {
|
}) {
|
||||||
|
const autoCompleteLogger = createLogger("autocomplete-destinations")
|
||||||
const cacheClient = await getCacheClient()
|
const cacheClient = await getCacheClient()
|
||||||
return await cacheClient.cacheOrGet(
|
return await cacheClient.cacheOrGet(
|
||||||
`autocomplete:destinations:locations:${lang}`,
|
`autocomplete:destinations:locations:${lang}`,
|
||||||
@@ -110,7 +112,7 @@ export async function getAutoCompleteDestinationsData({
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (!countries) {
|
if (!countries) {
|
||||||
console.error("Unable to fetch countries")
|
autoCompleteLogger.error("Unable to fetch countries")
|
||||||
throw new Error("Unable to fetch countries")
|
throw new Error("Unable to fetch countries")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +148,7 @@ export async function getAutoCompleteDestinationsData({
|
|||||||
!cityUrls ||
|
!cityUrls ||
|
||||||
!countryUrls
|
!countryUrls
|
||||||
) {
|
) {
|
||||||
console.error("Unable to fetch location URLs")
|
autoCompleteLogger.error("Unable to fetch location URLs")
|
||||||
throw new Error("Unable to fetch location URLs")
|
throw new Error("Unable to fetch location URLs")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
import { createCounter } from "@scandic-hotels/common/telemetry"
|
import { createCounter } from "@scandic-hotels/common/telemetry"
|
||||||
|
|
||||||
import { router } from "../.."
|
import { router } from "../.."
|
||||||
@@ -19,6 +20,7 @@ import { bookingConfirmationSchema, createBookingSchema } from "./output"
|
|||||||
import { cancelBooking } from "./utils"
|
import { cancelBooking } from "./utils"
|
||||||
|
|
||||||
const refIdPlugin = createRefIdPlugin()
|
const refIdPlugin = createRefIdPlugin()
|
||||||
|
const bookingLogger = createLogger("trpc.booking")
|
||||||
|
|
||||||
export const bookingMutationRouter = router({
|
export const bookingMutationRouter = router({
|
||||||
create: safeProtectedServiceProcedure
|
create: safeProtectedServiceProcedure
|
||||||
@@ -173,10 +175,10 @@ export const bookingMutationRouter = router({
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.info(
|
bookingLogger.error(
|
||||||
`Cancelling booking failed for confirmationNumber: ${confirmationNumbers[idx]}`
|
`Cancelling booking failed for confirmationNumber: ${confirmationNumbers[idx]}`,
|
||||||
|
response.reason
|
||||||
)
|
)
|
||||||
console.error(response.reason)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cancelledRoomsSuccessfully.push(null)
|
cancelledRoomsSuccessfully.push(null)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { z, ZodError, ZodIssueCode } from "zod"
|
import { z, ZodError, ZodIssueCode } from "zod"
|
||||||
|
|
||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { removeMultipleSlashes } from "@scandic-hotels/common/utils/url"
|
import { removeMultipleSlashes } from "@scandic-hotels/common/utils/url"
|
||||||
|
|
||||||
import { AlertTypeEnum } from "../../../types/alertType"
|
import { AlertTypeEnum } from "../../../types/alertType"
|
||||||
@@ -541,7 +542,7 @@ export const headerRefsSchema = z
|
|||||||
})
|
})
|
||||||
.transform((data) => {
|
.transform((data) => {
|
||||||
if (!data.all_header.items.length) {
|
if (!data.all_header.items.length) {
|
||||||
console.info(`Zod Error - No header returned in refs request`)
|
logger.error(`Zod Error - No header returned in refs request`)
|
||||||
throw new ZodError([
|
throw new ZodError([
|
||||||
{
|
{
|
||||||
code: ZodIssueCode.custom,
|
code: ZodIssueCode.custom,
|
||||||
@@ -688,7 +689,7 @@ export const headerSchema = z
|
|||||||
})
|
})
|
||||||
.transform((data) => {
|
.transform((data) => {
|
||||||
if (!data.all_header.items.length) {
|
if (!data.all_header.items.length) {
|
||||||
console.info(`Zod Error - No header returned in request`)
|
logger.error(`Zod Error - No header returned in request`)
|
||||||
throw new ZodError([
|
throw new ZodError([
|
||||||
{
|
{
|
||||||
code: ZodIssueCode.custom,
|
code: ZodIssueCode.custom,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
import { createCounter } from "@scandic-hotels/common/telemetry"
|
import { createCounter } from "@scandic-hotels/common/telemetry"
|
||||||
import { removeTrailingSlash } from "@scandic-hotels/common/utils/url"
|
import { removeTrailingSlash } from "@scandic-hotels/common/utils/url"
|
||||||
|
|
||||||
@@ -68,6 +69,10 @@ export async function getUrlsOfAllLanguages(
|
|||||||
uid: string,
|
uid: string,
|
||||||
contentType: string
|
contentType: string
|
||||||
) {
|
) {
|
||||||
|
const languageSwitcherLogger = createLogger(
|
||||||
|
"trpc.contentstack.languageSwitcher"
|
||||||
|
)
|
||||||
|
|
||||||
const getLanguageSwitcherCounter = createCounter(
|
const getLanguageSwitcherCounter = createCounter(
|
||||||
"trpc.contentstack",
|
"trpc.contentstack",
|
||||||
"languageSwitcher.get"
|
"languageSwitcher.get"
|
||||||
@@ -143,8 +148,9 @@ export async function getUrlsOfAllLanguages(
|
|||||||
fiNoSvDocument = GetFiNoSvUrlsStartPage
|
fiNoSvDocument = GetFiNoSvUrlsStartPage
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
console.error(`type: [${contentType}]`)
|
languageSwitcherLogger.error(
|
||||||
console.error(`Trying to get a content type that is not supported`)
|
`Trying to get a content type that is not supported, ${contentType}`
|
||||||
|
)
|
||||||
throw internalServerError()
|
throw internalServerError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { toLang } from "@scandic-hotels/common/utils/languages"
|
import { toLang } from "@scandic-hotels/common/utils/languages"
|
||||||
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||||
|
|
||||||
@@ -115,7 +116,7 @@ function getRate(rate: RateDefinition) {
|
|||||||
case "NotCancellable":
|
case "NotCancellable":
|
||||||
return RateEnum.save
|
return RateEnum.save
|
||||||
default:
|
default:
|
||||||
console.info(
|
logger.warn(
|
||||||
`Unknown cancellationRule [${rate.cancellationRule}]. This should never happen!`
|
`Unknown cancellationRule [${rate.cancellationRule}]. This should never happen!`
|
||||||
)
|
)
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
||||||
import { dt } from "@scandic-hotels/common/dt"
|
import { dt } from "@scandic-hotels/common/dt"
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
import { createCounter } from "@scandic-hotels/common/telemetry"
|
import { createCounter } from "@scandic-hotels/common/telemetry"
|
||||||
|
|
||||||
import { env } from "../../../env/server"
|
import { env } from "../../../env/server"
|
||||||
@@ -79,6 +80,8 @@ import type {
|
|||||||
import type { CityLocation } from "../../types/locations"
|
import type { CityLocation } from "../../types/locations"
|
||||||
import type { Room } from "../../types/room"
|
import type { Room } from "../../types/room"
|
||||||
|
|
||||||
|
const hotelQueryLogger = createLogger("hotelQueryRouter")
|
||||||
|
|
||||||
export const hotelQueryRouter = router({
|
export const hotelQueryRouter = router({
|
||||||
availability: router({
|
availability: router({
|
||||||
hotelsByCity: safeProtectedServiceProcedure
|
hotelsByCity: safeProtectedServiceProcedure
|
||||||
@@ -189,8 +192,10 @@ export const hotelQueryRouter = router({
|
|||||||
const selectedRooms = []
|
const selectedRooms = []
|
||||||
for (const [idx, room] of availability.entries()) {
|
for (const [idx, room] of availability.entries()) {
|
||||||
if (!room || "error" in room) {
|
if (!room || "error" in room) {
|
||||||
console.info(`Availability failed: ${room.error}`)
|
hotelQueryLogger.error(
|
||||||
console.error(room.details)
|
`Availability failed: ${room.error}`,
|
||||||
|
room.details
|
||||||
|
)
|
||||||
selectedRooms.push(null)
|
selectedRooms.push(null)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -203,7 +208,7 @@ export const hotelQueryRouter = router({
|
|||||||
ctx.userPoints
|
ctx.userPoints
|
||||||
)
|
)
|
||||||
if (!selected) {
|
if (!selected) {
|
||||||
console.error("Unable to find selected room")
|
hotelQueryLogger.error("Unable to find selected room")
|
||||||
selectedRooms.push(null)
|
selectedRooms.push(null)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -347,7 +352,7 @@ export const hotelQueryRouter = router({
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (!selected) {
|
if (!selected) {
|
||||||
console.error("Unable to find selected room")
|
hotelQueryLogger.error("Unable to find selected room")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -895,13 +900,13 @@ export const hotelQueryRouter = router({
|
|||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
|
|
||||||
if (data.status !== "OK") {
|
if (data.status !== "OK") {
|
||||||
console.error(`Geocode error: ${data.status}`)
|
hotelQueryLogger.error(`Geocode error: ${data.status}`)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const location = data.results[0]?.geometry?.location
|
const location = data.results[0]?.geometry?.location
|
||||||
if (!location) {
|
if (!location) {
|
||||||
console.error("No location found in geocode response")
|
hotelQueryLogger.error("No location found in geocode response")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import stringify from "json-stable-stringify-without-jsonify"
|
|||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation"
|
import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation"
|
||||||
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
import { createCounter } from "@scandic-hotels/common/telemetry"
|
import { createCounter } from "@scandic-hotels/common/telemetry"
|
||||||
import { chunk } from "@scandic-hotels/common/utils/chunk"
|
import { chunk } from "@scandic-hotels/common/utils/chunk"
|
||||||
|
|
||||||
@@ -64,6 +65,8 @@ import type {
|
|||||||
import type { Cities } from "./output"
|
import type { Cities } from "./output"
|
||||||
export const locationsAffix = "locations"
|
export const locationsAffix = "locations"
|
||||||
|
|
||||||
|
const hotelUtilsLogger = createLogger("hotelUtils")
|
||||||
|
|
||||||
export async function getCitiesByCountry({
|
export async function getCitiesByCountry({
|
||||||
countries,
|
countries,
|
||||||
lang,
|
lang,
|
||||||
@@ -101,8 +104,11 @@ export async function getCitiesByCountry({
|
|||||||
const countryJson = await countryResponse.json()
|
const countryJson = await countryResponse.json()
|
||||||
const citiesByCountry = citiesByCountrySchema.safeParse(countryJson)
|
const citiesByCountry = citiesByCountrySchema.safeParse(countryJson)
|
||||||
if (!citiesByCountry.success) {
|
if (!citiesByCountry.success) {
|
||||||
console.error(`Unable to parse cities by country ${country}`)
|
hotelUtilsLogger.error(
|
||||||
console.error(citiesByCountry.error)
|
`Unable to parse cities by country ${country}`,
|
||||||
|
citiesByCountry.error
|
||||||
|
)
|
||||||
|
|
||||||
throw new Error(`Unable to parse cities by country ${country}`)
|
throw new Error(`Unable to parse cities by country ${country}`)
|
||||||
}
|
}
|
||||||
return { ...citiesByCountry.data, country }
|
return { ...citiesByCountry.data, country }
|
||||||
@@ -160,8 +166,10 @@ export async function getCountries({
|
|||||||
const countriesJson = await countryResponse.json()
|
const countriesJson = await countryResponse.json()
|
||||||
const countries = countriesSchema.safeParse(countriesJson)
|
const countries = countriesSchema.safeParse(countriesJson)
|
||||||
if (!countries.success) {
|
if (!countries.success) {
|
||||||
console.info(`Validation for countries failed`)
|
hotelUtilsLogger.error(
|
||||||
console.error(countries.error)
|
`Validation for countries failed`,
|
||||||
|
countries.error
|
||||||
|
)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,8 +455,10 @@ export async function getLocations({
|
|||||||
const apiJson = await apiResponse.json()
|
const apiJson = await apiResponse.json()
|
||||||
const verifiedLocations = locationsSchema.safeParse(apiJson)
|
const verifiedLocations = locationsSchema.safeParse(apiJson)
|
||||||
if (!verifiedLocations.success) {
|
if (!verifiedLocations.success) {
|
||||||
console.info(`Locations Verification Failed`)
|
hotelUtilsLogger.error(
|
||||||
console.error(verifiedLocations.error)
|
`Locations Verification Failed`,
|
||||||
|
verifiedLocations.error
|
||||||
|
)
|
||||||
throw new Error("Unable to parse locations")
|
throw new Error("Unable to parse locations")
|
||||||
}
|
}
|
||||||
const chunkedLocations = chunk(verifiedLocations.data.data, 10)
|
const chunkedLocations = chunk(verifiedLocations.data.data, 10)
|
||||||
@@ -471,10 +481,10 @@ export async function getLocations({
|
|||||||
country,
|
country,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.info(
|
hotelUtilsLogger.error(
|
||||||
`Location cannot be found in any of the countries cities`
|
`Location cannot be found in any of the countries cities`,
|
||||||
|
location
|
||||||
)
|
)
|
||||||
console.info(location)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (location.type === "hotels") {
|
} else if (location.type === "hotels") {
|
||||||
@@ -614,9 +624,10 @@ export async function getCity({
|
|||||||
const cityJson = await cityResponse.json()
|
const cityJson = await cityResponse.json()
|
||||||
const city = citiesSchema.safeParse(cityJson)
|
const city = citiesSchema.safeParse(cityJson)
|
||||||
if (!city.success) {
|
if (!city.success) {
|
||||||
console.info(`Validation of city failed`)
|
hotelUtilsLogger.error(`Validation of city failed`, {
|
||||||
console.info(`cityUrl: ${cityUrl}`)
|
error: city.error,
|
||||||
console.error(city.error)
|
cityUrl,
|
||||||
|
})
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import * as Sentry from "@sentry/nextjs"
|
import * as Sentry from "@sentry/nextjs"
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
||||||
|
|
||||||
import * as api from "../../../api"
|
import * as api from "../../../api"
|
||||||
import { protectedProcedure } from "../../../procedures"
|
import { protectedProcedure } from "../../../procedures"
|
||||||
import { getOTPState } from "./otp/getOTPState"
|
import { getOTPState } from "./otp/getOTPState"
|
||||||
@@ -18,13 +20,14 @@ const outputSchema = z.object({
|
|||||||
]),
|
]),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const sasLogger = createLogger("SAS")
|
||||||
export const linkAccount = protectedProcedure
|
export const linkAccount = protectedProcedure
|
||||||
.output(outputSchema)
|
.output(outputSchema)
|
||||||
.mutation(async function ({ ctx }) {
|
.mutation(async function ({ ctx }) {
|
||||||
const sasAuthToken = await getSasToken()
|
const sasAuthToken = await getSasToken()
|
||||||
const { referenceId } = await getOTPState()
|
const { referenceId } = await getOTPState()
|
||||||
|
|
||||||
console.log("[SAS] link account")
|
sasLogger.debug("[SAS] link account")
|
||||||
|
|
||||||
const apiResponse = await api.post(api.endpoints.v1.Profile.link, {
|
const apiResponse = await api.post(api.endpoints.v1.Profile.link, {
|
||||||
headers: {
|
headers: {
|
||||||
@@ -47,7 +50,7 @@ export const linkAccount = protectedProcedure
|
|||||||
linkedAndBoosted || linkedWithoutBoost || linkedWithUnknownBoost
|
linkedAndBoosted || linkedWithoutBoost || linkedWithUnknownBoost
|
||||||
|
|
||||||
if (linked) {
|
if (linked) {
|
||||||
console.log("[SAS] link account done")
|
sasLogger.debug("[SAS] link account done")
|
||||||
return { linkingState: "linked" }
|
return { linkingState: "linked" }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,12 +59,12 @@ export const linkAccount = protectedProcedure
|
|||||||
const data = badRequestSchema.safeParse(result)
|
const data = badRequestSchema.safeParse(result)
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
const linkAccountBadRequestSchemaError = `[SAS] failed to parse link account bad request schema ${JSON.stringify(data.error)}`
|
const linkAccountBadRequestSchemaError = `[SAS] failed to parse link account bad request schema ${JSON.stringify(data.error)}`
|
||||||
console.error(linkAccountBadRequestSchemaError)
|
sasLogger.error(linkAccountBadRequestSchemaError)
|
||||||
Sentry.captureMessage(linkAccountBadRequestSchemaError)
|
Sentry.captureMessage(linkAccountBadRequestSchemaError)
|
||||||
return { linkingState: "error" }
|
return { linkingState: "error" }
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("[SAS] link account error with response", result)
|
sasLogger.error("[SAS] link account error with response", result)
|
||||||
|
|
||||||
const { errors } = data.data
|
const { errors } = data.data
|
||||||
|
|
||||||
@@ -89,7 +92,7 @@ export const linkAccount = protectedProcedure
|
|||||||
}
|
}
|
||||||
|
|
||||||
const errorMessage = `[SAS] link account error with status code ${apiResponse.status} and response ${await apiResponse.text()}`
|
const errorMessage = `[SAS] link account error with status code ${apiResponse.status} and response ${await apiResponse.text()}`
|
||||||
console.warn(errorMessage)
|
sasLogger.error(errorMessage)
|
||||||
Sentry.captureMessage(errorMessage)
|
Sentry.captureMessage(errorMessage)
|
||||||
return { linkingState: "error" }
|
return { linkingState: "error" }
|
||||||
})
|
})
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user