Merged in feat/sw-3125-move-client-trpc-setup (pull request #2493)

feat(SW-3125): Move client trpc setup

* Move client trpc to package

* Client setup in partner-sas

* Add todo


Approved-by: Linus Flood
This commit is contained in:
Anton Gunnarsson
2025-07-01 12:41:28 +00:00
parent 481044346c
commit be25be7bb5
57 changed files with 247 additions and 154 deletions

View File

@@ -0,0 +1,20 @@
/* eslint-disable formatjs/no-literal-string-in-jsx */
"use client"
import { Lang } from "@scandic-hotels/common/constants/language"
import { trpc } from "@scandic-hotels/trpc/client"
export function ClientComponent() {
const { data, isLoading } = trpc.autocomplete.destinations.useQuery({
lang: Lang.en,
includeTypes: ["hotels"],
query: "Malmö",
})
return (
<div>
<p>client component</p>
<p>Data: {JSON.stringify(data?.hits?.hotels[0]?.name)}</p>
<p>Is loading: {isLoading ? "Yes" : "No"}</p>
</div>
)
}

View File

@@ -0,0 +1,16 @@
import { fetchRequestHandler } from "@trpc/server/adapters/fetch"
import { appRouter } from "@scandic-hotels/trpc/routers/appRouter"
import { createAppContext } from "@/lib/trpc"
async function handler(req: Request) {
return fetchRequestHandler({
createContext: createAppContext,
endpoint: "/api/web/trpc",
req,
router: appRouter,
})
}
export { handler as GET, handler as POST }

View File

@@ -1,3 +1,2 @@
body {
background: rebeccapurple;
}

View File

@@ -3,6 +3,8 @@ import "@scandic-hotels/design-system/fonts.css"
import "@/public/_static/css/design-system-new-deprecated.css"
import "./globals.css"
import { TrpcProvider } from "@scandic-hotels/trpc/Provider"
import type { Metadata } from "next"
export const metadata: Metadata = {
@@ -23,7 +25,10 @@ export default function RootLayout({
{/* eslint-disable-next-line @next/next/no-css-tags */}
<link rel="stylesheet" href="/_static/css/scandic.css" />
</head>
<body className="scandic">{children}</body>
<body className="scandic">
{/* TODO handle onError */}
<TrpcProvider>{children}</TrpcProvider>
</body>
</html>
)
}

View File

@@ -1,7 +1,4 @@
.page {
color: white;
width: 500px;
height: 500px;
padding-left: 200px;
padding-top: 200px;
}

View File

@@ -4,6 +4,8 @@ import { Typography } from "@scandic-hotels/design-system/Typography"
import { serverClient } from "@/lib/trpc"
import { ClientComponent } from "./ClientComponent"
import styles from "./page.module.css"
export default async function Home() {
@@ -22,6 +24,9 @@ export default async function Home() {
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<p>hello world with data: {hotel}</p>
</Typography>
<hr />
<ClientComponent />
<hr />
<Typography>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<p>from booking-flow package:</p>

View File

@@ -18,6 +18,7 @@
"@netlify/plugin-nextjs": "^5.11.2",
"@scandic-hotels/booking-flow": "workspace:*",
"@scandic-hotels/design-system": "workspace:*",
"@scandic-hotels/trpc": "workspace:*",
"@sentry/nextjs": "^8.41.0",
"next": "15.3.4",
"react": "^19.0.0",

View File

@@ -8,8 +8,7 @@ import { useIntl } from "react-intl"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import Link from "@/components/TempDesignSystem/Link"

View File

@@ -3,7 +3,7 @@
import { keepPreviousData } from "@tanstack/react-query"
import { useState } from "react"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import LoadingSpinner from "@/components/LoadingSpinner"
import Pagination from "@/components/MyPages/Pagination"

View File

@@ -2,10 +2,10 @@
import { useRef, useState } from "react"
import { trpc } from "@scandic-hotels/trpc/client"
import { type Reward } from "@scandic-hotels/trpc/types/rewards"
import { REWARDS_PER_PAGE } from "@/constants/rewards"
import { trpc } from "@/lib/trpc/client"
import { RewardIcon } from "@/components/Blocks/DynamicContent/Rewards/RewardIcon"
import ScriptedRewardText from "@/components/Blocks/DynamicContent/Rewards/ScriptedRewardText"

View File

@@ -11,8 +11,7 @@ import {
import { useIntl } from "react-intl"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import Button from "@/components/TempDesignSystem/Button"
import useLang from "@/hooks/useLang"

View File

@@ -2,7 +2,7 @@
import { createContext, useCallback, useContext, useEffect } from "react"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import { getFirstRedeemableCoupon } from "@/utils/rewards"

View File

@@ -1,6 +1,6 @@
"use client"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import LoadingSpinner from "@/components/LoadingSpinner"
import Grids from "@/components/TempDesignSystem/Grids"

View File

@@ -1,6 +1,6 @@
"use client"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import LoadingSpinner from "@/components/LoadingSpinner"
import Grids from "@/components/TempDesignSystem/Grids"

View File

@@ -7,9 +7,9 @@ import { FormProvider, useForm } from "react-hook-form"
import { dt } from "@scandic-hotels/common/dt"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { trpc } from "@scandic-hotels/trpc/client"
import { SEARCH_TYPE_REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import { trpc } from "@/lib/trpc/client"
import { StickyElementNameEnum } from "@/stores/sticky-position"
import Form, {

View File

@@ -2,7 +2,7 @@
import { usePathname } from "next/navigation"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import SkeletonShimmer from "@/components/SkeletonShimmer"
import useLang from "@/hooks/useLang"

View File

@@ -6,8 +6,7 @@ import { useDebounceValue } from "usehooks-ts"
import { Divider } from "@scandic-hotels/design-system/Divider"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"

View File

@@ -6,11 +6,11 @@ import { FormProvider, useForm } from "react-hook-form"
import { useIntl } from "react-intl"
import { profile } from "@scandic-hotels/common/constants/routes/myPages"
import { trpc } from "@scandic-hotels/trpc/client"
import { langToApiLang } from "@scandic-hotels/trpc/constants/apiLang"
import { getDefaultCountryFromLang } from "@/constants/languages"
import { logout } from "@/constants/routes/handleAuth"
import { trpc } from "@/lib/trpc/client"
import { editProfile } from "@/actions/editProfile"
import Dialog from "@/components/Dialog"

View File

@@ -8,6 +8,7 @@ import { useIntl } from "react-intl"
import { Button } from "@scandic-hotels/design-system/Button"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { trpc } from "@scandic-hotels/trpc/client"
import {
type SignUpSchema,
signUpSchema,
@@ -18,7 +19,6 @@ import {
membershipTermsAndConditions,
privacyPolicy,
} from "@/constants/webHrefs"
import { trpc } from "@/lib/trpc/client"
import Checkbox from "@/components/TempDesignSystem/Form/Checkbox"
import CountrySelect from "@/components/TempDesignSystem/Form/Country"

View File

@@ -5,9 +5,9 @@ import { useIntl } from "react-intl"
import { Divider } from "@scandic-hotels/design-system/Divider"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { trpc } from "@scandic-hotels/trpc/client"
import { logout } from "@/constants/routes/handleAuth"
import { trpc } from "@/lib/trpc/client"
import Link from "@/components/TempDesignSystem/Link"
import Caption from "@/components/TempDesignSystem/Text/Caption"

View File

@@ -4,8 +4,7 @@ import { useSession } from "next-auth/react"
import { useIntl } from "react-intl"
import { MembershipLevelEnum } from "@scandic-hotels/common/constants/membershipLevels"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import LoginButton from "@/components/LoginButton"
import useLang from "@/hooks/useLang"

View File

@@ -4,8 +4,8 @@ import { useEffect } from "react"
import { useIntl } from "react-intl"
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import { trpc } from "@scandic-hotels/trpc/client"
import { trpc } from "@/lib/trpc/client"
import { useBookingConfirmationStore } from "@/stores/booking-confirmation"
import useLang from "@/hooks/useLang"

View File

@@ -12,6 +12,7 @@ import { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMetho
import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation"
import { Button } from "@scandic-hotels/design-system/Button"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { trpc } from "@scandic-hotels/trpc/client"
import { bedTypeMap } from "@scandic-hotels/trpc/constants/bedTypeMap"
import { SEARCH_TYPE_REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import { BookingStatusEnum } from "@scandic-hotels/trpc/enums/bookingStatus"
@@ -20,7 +21,6 @@ import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
import { PAYMENT_METHOD_TITLES } from "@/constants/booking"
import { bookingConfirmation } from "@/constants/routes/hotelReservation"
import { env } from "@/env/client"
import { trpc } from "@/lib/trpc/client"
import { useEnterDetailsStore } from "@/stores/enter-details"
import PaymentOption from "@/components/HotelReservation/PaymentOption"

View File

@@ -6,9 +6,9 @@ import { FormProvider, useForm } from "react-hook-form"
import { useIntl } from "react-intl"
import { myStay } from "@scandic-hotels/common/constants/routes/myStay"
import { trpc } from "@scandic-hotels/trpc/client"
import { customerService } from "@/constants/webHrefs"
import { trpc } from "@/lib/trpc/client"
import Button from "@/components/TempDesignSystem/Button"
import Input from "@/components/TempDesignSystem/Form/Input"

View File

@@ -10,11 +10,11 @@ import { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMetho
import { dt } from "@scandic-hotels/common/dt"
import { Divider } from "@scandic-hotels/design-system/Divider"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { trpc } from "@scandic-hotels/trpc/client"
import { BreakfastPackageEnum } from "@scandic-hotels/trpc/enums/breakfast"
import { guaranteeCallback } from "@/constants/routes/hotelReservation"
import { env } from "@/env/client"
import { trpc } from "@/lib/trpc/client"
import {
AncillaryStepEnum,
type BreakfastData,

View File

@@ -2,8 +2,7 @@ import { useRouter } from "next/navigation"
import { useIntl } from "react-intl"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import Dialog from "@/components/Dialog"
import Button from "@/components/TempDesignSystem/Button"

View File

@@ -3,7 +3,7 @@
import { useRouter } from "next/navigation"
import { useEffect } from "react"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import {
clearAncillarySessionData,

View File

@@ -9,9 +9,9 @@ import { useIntl } from "react-intl"
import { profileEdit } from "@scandic-hotels/common/constants/routes/myPages"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { trpc } from "@scandic-hotels/trpc/client"
import { isWebview } from "@/constants/routes/webviews"
import { trpc } from "@/lib/trpc/client"
import MembershipLevelIcon from "@/components/Levels/Icon"
import Modal from "@/components/Modal"

View File

@@ -3,8 +3,8 @@ import { useWatch } from "react-hook-form"
import { useIntl } from "react-intl"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { trpc } from "@scandic-hotels/trpc/client"
import { trpc } from "@/lib/trpc/client"
import { useMyStayStore } from "@/stores/my-stay"
import Modal from "@/components/HotelReservation/MyStay/Modal"

View File

@@ -3,9 +3,9 @@ import { useIntl } from "react-intl"
import { dt } from "@scandic-hotels/common/dt"
import { Divider } from "@scandic-hotels/design-system/Divider"
import { trpc } from "@scandic-hotels/trpc/client"
import { longDateWithYearFormat } from "@/constants/dateFormats"
import { trpc } from "@/lib/trpc/client"
import { useMyStayStore } from "@/stores/my-stay"
import Modal from "@/components/HotelReservation/MyStay/Modal"

View File

@@ -4,8 +4,8 @@ import { useState } from "react"
import { useIntl } from "react-intl"
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import { trpc } from "@scandic-hotels/trpc/client"
import { trpc } from "@/lib/trpc/client"
import { useMyStayStore } from "@/stores/my-stay"
import { sumPackages } from "@/components/HotelReservation/utils"

View File

@@ -17,9 +17,9 @@ import { ChipButton } from "@scandic-hotels/design-system/ChipButton"
import { IconButton } from "@scandic-hotels/design-system/IconButton"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { trpc } from "@scandic-hotels/trpc/client"
import { RateTypeEnum } from "@scandic-hotels/trpc/enums/rateType"
import { trpc } from "@/lib/trpc/client"
import { useRatesStore } from "@/stores/select-rate"
import { useRoomContext } from "@/contexts/SelectRate/Room"

View File

@@ -5,8 +5,8 @@ import { useIntl } from "react-intl"
import { Button } from "@scandic-hotels/design-system/Button"
import { Divider } from "@scandic-hotels/design-system/Divider"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { trpc } from "@scandic-hotels/trpc/client"
import { trpc } from "@/lib/trpc/client"
import { useRatesStore } from "@/stores/select-rate"
import { useRoomContext } from "@/contexts/SelectRate/Room"

View File

@@ -4,8 +4,8 @@ import { useMediaQuery } from "usehooks-ts"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { trpc } from "@scandic-hotels/trpc/client"
import { trpc } from "@/lib/trpc/client"
import { useRatesStore } from "@/stores/select-rate"
import { useRoomContext } from "@/contexts/SelectRate/Room"

View File

@@ -3,11 +3,10 @@
import { notFound, useSearchParams } from "next/navigation"
import { useIntl } from "react-intl"
import { trpc } from "@scandic-hotels/trpc/client"
import { selectRateRoomsAvailabilityInputSchema } from "@scandic-hotels/trpc/routers/hotels/input"
import { AlertTypeEnum } from "@scandic-hotels/trpc/types/alertType"
import { trpc } from "@/lib/trpc/client"
import Alert from "@/components/TempDesignSystem/Alert"
import useLang from "@/hooks/useLang"
import RatesProvider from "@/providers/RatesProvider"

View File

@@ -2,7 +2,8 @@
import { useEffect } from "react"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import useSidePeekStore from "@/stores/sidepeek"
import HotelSidePeek from "@/components/SidePeeks/HotelSidePeek"

View File

@@ -7,9 +7,9 @@ import { useIntl } from "react-intl"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { trpc } from "@scandic-hotels/trpc/client"
import { languages } from "@/constants/languages"
import { trpc } from "@/lib/trpc/client"
import useDropdownStore from "@/stores/main-menu"
import useClickOutside from "@/hooks/useClickOutside"

View File

@@ -5,9 +5,9 @@ import { useEffect, useRef } from "react"
import { useIntl } from "react-intl"
import { partnerSas } from "@scandic-hotels/common/constants/routes/myPages"
import { trpc } from "@scandic-hotels/trpc/client"
import { TIER_TO_FRIEND_MAP } from "@/constants/membershipLevels"
import { trpc } from "@/lib/trpc/client"
import { toast } from "@/components/TempDesignSystem/Toasts"
import useLang from "@/hooks/useLang"

View File

@@ -8,13 +8,13 @@ import { useIntl } from "react-intl"
import { benefits } from "@scandic-hotels/common/constants/routes/myPages"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { trpc } from "@scandic-hotels/trpc/client"
import {
benefits as webviewBenefits,
myPagesWebviews,
} from "@/constants/routes/webviews"
import { customerService } from "@/constants/webHrefs"
import { trpc } from "@/lib/trpc/client"
import Link from "@/components/TempDesignSystem/Link"
import { toast } from "@/components/TempDesignSystem/Toasts"

View File

@@ -5,8 +5,7 @@ import { useEffect, useRef } from "react"
import { useIntl } from "react-intl"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import Button from "@/components/TempDesignSystem/Button"
import { toast } from "@/components/TempDesignSystem/Toasts"

View File

@@ -2,7 +2,7 @@
import React from "react"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import CreditCardRow from "../CreditCardRow"

View File

@@ -2,8 +2,7 @@
import { useIntl } from "react-intl"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import Dialog from "@/components/Dialog"
import Button from "@/components/TempDesignSystem/Button"

View File

@@ -3,8 +3,7 @@
import { useIntl } from "react-intl"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import Button from "@/components/TempDesignSystem/Button"
import { toast } from "@/components/TempDesignSystem/Toasts"

View File

@@ -2,9 +2,9 @@
import { useCallback, useRef } from "react"
import { trpc } from "@scandic-hotels/trpc/client"
import { AlertTypeEnum } from "@scandic-hotels/trpc/types/alertType"
import { trpc } from "@/lib/trpc/client"
import { StickyElementNameEnum } from "@/stores/sticky-position"
import Alert from "@/components/TempDesignSystem/Alert"

View File

@@ -15,7 +15,8 @@ import {
type UseFromSubscribe,
} from "react-hook-form"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import useRouterTransitionStore from "@/stores/router-transition"
import useTrackingStore from "@/stores/tracking"

View File

@@ -2,10 +2,9 @@ import { useRouter } from "next/navigation"
import { useCallback, useEffect, useState } from "react"
import { useIntl } from "react-intl"
import { trpc } from "@scandic-hotels/trpc/client"
import { BookingStatusEnum } from "@scandic-hotels/trpc/enums/bookingStatus"
import { trpc } from "@/lib/trpc/client"
import { toast } from "@/components/TempDesignSystem/Toasts"
import { useHandleBookingStatus } from "@/hooks/booking/useHandleBookingStatus"
import { trackEvent } from "@/utils/tracking/base"

View File

@@ -2,7 +2,7 @@
import { useRef } from "react"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import useLang from "@/hooks/useLang"

View File

@@ -1,101 +1,39 @@
"use client"
import {
QueryCache,
QueryClient,
QueryClientProvider,
} from "@tanstack/react-query"
import { httpLink, loggerLink, TRPCClientError } from "@trpc/client"
import { useState } from "react"
import { TRPCClientError } from "@trpc/client"
import { SessionExpiredError } from "@scandic-hotels/trpc/errors"
import { transformer } from "@scandic-hotels/trpc/transformer"
import { TrpcProvider as InternalTrpcProvider } from "@scandic-hotels/trpc/Provider"
import { login } from "@/constants/routes/handleAuth"
import { env } from "@/env/client"
import useLang from "@/hooks/useLang"
import { trpc } from "./client"
import type { AnyTRPCRouter } from "@trpc/server"
function initializeTrpcClient() {
// Locally we set nextjs to run on port to 3000 so that we always guarantee
// that trpc and next are running on the same port.
return trpc.createClient({
links: [
loggerLink({
enabled: (opts) =>
(env.NEXT_PUBLIC_NODE_ENV === "development" &&
typeof window !== "undefined") ||
(opts.direction === "down" && opts.result instanceof Error),
}),
httpLink({
transformer,
/**
* This is locally in Next.js
*/
url: `/api/web/trpc`,
}),
],
})
}
export default function TrpcProvider({ children }: React.PropsWithChildren) {
export default function TrpcProvider({
children,
}: {
children: React.ReactNode
}) {
const lang = useLang()
const [queryClient] = useState(
() =>
new QueryClient({
queryCache: new QueryCache({
async onError(error) {
if (error instanceof TRPCClientError) {
const appError: TRPCClientError<AnyTRPCRouter> = error
console.log({ appError })
if (appError.data?.code === "UNAUTHORIZED") {
if (appError.data?.cause instanceof SessionExpiredError) {
const loginUrl = login[lang]
window.location.assign(loginUrl)
}
}
}
},
}),
defaultOptions: {
queries: {
staleTime: 60 * 1000,
retry(failureCount, error) {
if (error instanceof TRPCClientError) {
const appError: TRPCClientError<AnyTRPCRouter> = error
// Do not retry query requests that got UNAUTHORIZED error.
// It won't make a difference sending the same request again.
if (appError.data?.code) {
if (
[
"UNAUTHORIZED",
"INTERNAL_SERVER_ERROR",
"FORBIDDEN",
].includes(appError.data.code)
) {
return false
}
}
}
// Retry all client requests that fail (and are not handled above)
// at most 3 times.
return failureCount < 3
},
},
},
})
)
const [trpcClient] = useState(() => initializeTrpcClient())
return (
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</trpc.Provider>
<InternalTrpcProvider
onError={(error) => {
if (error instanceof TRPCClientError) {
const appError: TRPCClientError<AnyTRPCRouter> = error
console.log({ appError })
if (appError.data?.code === "UNAUTHORIZED") {
if (appError.data?.cause instanceof SessionExpiredError) {
const loginUrl = login[lang]
window.location.assign(loginUrl)
}
}
}
}}
>
{children}
</InternalTrpcProvider>
)
}

View File

@@ -1,9 +0,0 @@
import { createTRPCReact } from "@trpc/react-query"
import type { AppRouter } from "@scandic-hotels/trpc/routers/appRouter"
import type { inferRouterInputs, inferRouterOutputs } from "@trpc/server"
export const trpc = createTRPCReact<AppRouter>()
export type RouterInput = inferRouterInputs<AppRouter>
export type RouterOutput = inferRouterOutputs<AppRouter>

View File

@@ -3,7 +3,8 @@ import { notFound } from "next/navigation"
import { use, useRef } from "react"
import { useIntl } from "react-intl"
import { trpc } from "@/lib/trpc/client"
import { trpc } from "@scandic-hotels/trpc/client"
import { createMyStayStore } from "@/stores/my-stay"
import { MyStaySkeleton } from "@/components/HotelReservation/MyStay/myStaySkeleton"

View File

@@ -1,7 +1,6 @@
import type { RouterOutput } from "@scandic-hotels/trpc/client"
import type { EventAttributes } from "ics"
import type { RouterOutput } from "@/lib/trpc/client"
export interface AddToCalendarProps {
checkInDate: NonNullable<
RouterOutput["booking"]["get"]

View File

@@ -1,3 +1,3 @@
import type { RouterOutput } from "@/lib/trpc/client"
import type { RouterOutput } from "@scandic-hotels/trpc/client"
export type SafeUser = RouterOutput["user"]["getSafely"]

21
packages/trpc/env/client.ts vendored Normal file
View File

@@ -0,0 +1,21 @@
import { createEnv } from "@t3-oss/env-nextjs"
import { z } from "zod"
export const env = createEnv({
client: {
NEXT_PUBLIC_NODE_ENV: z.enum(["development", "test", "production"]),
// NEXT_PUBLIC_PORT: z.string().default("3000"),
// NEXT_PUBLIC_SENTRY_ENVIRONMENT: z.string().default("development"),
// NEXT_PUBLIC_SENTRY_CLIENT_SAMPLERATE: z.coerce.number().default(0.001),
// NEXT_PUBLIC_PUBLIC_URL: z.string().optional(),
},
emptyStringAsUndefined: true,
runtimeEnv: {
NEXT_PUBLIC_NODE_ENV: process.env.NODE_ENV,
// NEXT_PUBLIC_PORT: process.env.NEXT_PUBLIC_PORT,
// NEXT_PUBLIC_SENTRY_ENVIRONMENT: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT,
// NEXT_PUBLIC_SENTRY_CLIENT_SAMPLERATE:
// process.env.NEXT_PUBLIC_SENTRY_CLIENT_SAMPLERATE,
// NEXT_PUBLIC_PUBLIC_URL: process.env.NEXT_PUBLIC_PUBLIC_URL,
},
})

View File

@@ -0,0 +1,92 @@
"use client"
import {
QueryCache,
QueryClient,
QueryClientProvider,
} from "@tanstack/react-query"
import { httpLink, loggerLink, TRPCClientError } from "@trpc/client"
import { useState } from "react"
import { trpc } from "@scandic-hotels/trpc/client"
import { transformer } from "@scandic-hotels/trpc/transformer"
import { env } from "../env/client"
import type { AnyTRPCRouter } from "@trpc/server"
function initializeTrpcClient() {
// Locally we set nextjs to run on port to 3000 so that we always guarantee
// that trpc and next are running on the same port.
return trpc.createClient({
links: [
loggerLink({
enabled: (opts) =>
(env.NEXT_PUBLIC_NODE_ENV === "development" &&
typeof window !== "undefined") ||
(opts.direction === "down" && opts.result instanceof Error),
}),
httpLink({
transformer,
/**
* This is locally in Next.js
*/
url: `/api/web/trpc`,
}),
],
})
}
export function TrpcProvider({
onError,
children,
}: {
onError?: (error: Error) => void
children: React.ReactNode
}) {
const [queryClient] = useState(
() =>
new QueryClient({
queryCache: new QueryCache({
async onError(error) {
onError?.(error)
},
}),
defaultOptions: {
queries: {
staleTime: 60 * 1000,
retry(failureCount, error) {
if (error instanceof TRPCClientError) {
const appError: TRPCClientError<AnyTRPCRouter> = error
// Do not retry query requests that got UNAUTHORIZED error.
// It won't make a difference sending the same request again.
if (appError.data?.code) {
if (
[
"UNAUTHORIZED",
"INTERNAL_SERVER_ERROR",
"FORBIDDEN",
].includes(appError.data.code)
) {
return false
}
}
}
// Retry all client requests that fail (and are not handled above)
// at most 3 times.
return failureCount < 3
},
},
},
})
)
const [trpcClient] = useState(() => initializeTrpcClient())
return (
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</trpc.Provider>
)
}

View File

@@ -0,0 +1,9 @@
import { createTRPCReact } from "@trpc/react-query"
import type { inferRouterOutputs } from "@trpc/server"
import type { AppRouter } from "./routers/appRouter"
export const trpc = createTRPCReact<AppRouter>()
export type RouterOutput = inferRouterOutputs<AppRouter>

View File

@@ -18,6 +18,8 @@
"./procedures": "./lib/procedures.ts",
"./transformer": "./lib/transformer.ts",
"./serverClient": "./lib/serverClient.ts",
"./client": "./lib/client.ts",
"./Provider": "./lib/Provider.tsx",
"./utils/generateTag": "./lib/utils/generateTag.ts",
"./graphql/request": "./lib/graphql/request.ts",
"./graphql/batchRequest": "./lib/graphql/batchRequest.ts",
@@ -48,6 +50,8 @@
"@scandic-hotels/common": "workspace:*",
"@sentry/nextjs": "^8.41.0",
"@t3-oss/env-nextjs": "^0.13.4",
"@trpc/client": "^11.1.2",
"@trpc/react-query": "^11.1.2",
"@trpc/server": "^11.1.2",
"dayjs": "^1.11.13",
"deepmerge": "^4.3.1",

View File

@@ -6897,6 +6897,7 @@ __metadata:
"@scandic-hotels/booking-flow": "workspace:*"
"@scandic-hotels/common": "workspace:*"
"@scandic-hotels/design-system": "workspace:*"
"@scandic-hotels/trpc": "workspace:*"
"@scandic-hotels/typescript-config": "workspace:*"
"@sentry/nextjs": "npm:^8.41.0"
"@types/node": "npm:^20"
@@ -7080,7 +7081,7 @@ __metadata:
languageName: unknown
linkType: soft
"@scandic-hotels/trpc@workspace:packages/trpc":
"@scandic-hotels/trpc@workspace:*, @scandic-hotels/trpc@workspace:packages/trpc":
version: 0.0.0-use.local
resolution: "@scandic-hotels/trpc@workspace:packages/trpc"
dependencies:
@@ -7091,6 +7092,8 @@ __metadata:
"@scandic-hotels/typescript-config": "workspace:*"
"@sentry/nextjs": "npm:^8.41.0"
"@t3-oss/env-nextjs": "npm:^0.13.4"
"@trpc/client": "npm:^11.1.2"
"@trpc/react-query": "npm:^11.1.2"
"@trpc/server": "npm:^11.1.2"
"@types/lodash-es": "npm:^4"
"@types/react": "npm:19.1.0"