diff --git a/.changeset/sweet-socks-juggle.md b/.changeset/sweet-socks-juggle.md deleted file mode 100644 index fd48e574d7..0000000000 --- a/.changeset/sweet-socks-juggle.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"@blitzjs/next": major -"@blitzjs/rpc": major -"blitz": major -"@blitzjs/auth": major -"@blitzjs/codemod": major -"@blitzjs/config": major -"@blitzjs/generator": major ---- - -TODO: Upgrade @tanstack/react-query to v5.1.1 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 113ff0ee39..d116b8cfad 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -148,7 +148,7 @@ jobs: - name: Install playwright if: matrix.folder != 'next-13-app-dir' || matrix.os != 'windows-latest' run: | - pnpx playwright@1.49.1 install --with-deps + pnpx playwright@1.28.0 install --with-deps shell: bash - name: Build diff --git a/.github/workflows/pr-release.yml b/.github/workflows/pr-release.yml index e25e971e0c..280f622969 100644 --- a/.github/workflows/pr-release.yml +++ b/.github/workflows/pr-release.yml @@ -29,7 +29,7 @@ jobs: run: | pr="$(gh api repos/${{ github.repository }}/pulls/${{ github.event.issue.number }})" head_sha="$(echo "$pr" | jq -r .head.sha)" - + echo "head_sha=$head_sha" >> $GITHUB_OUTPUT - uses: actions/checkout@v4 @@ -39,7 +39,7 @@ jobs: - name: Setup PNPM uses: pnpm/action-setup@646cdf48217256a3d0b80361c5a50727664284f2 with: - version: 8.6.6 + version: 8.9.0 - name: Setup Node uses: actions/setup-node@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c08e988015..5931008bf4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,7 +37,7 @@ jobs: - name: Pre-publish uses: pnpm/action-setup@646cdf48217256a3d0b80361c5a50727664284f2 with: - version: 8.6.6 + version: 8.9.0 - run: pnpm install env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 diff --git a/apps/next13/package.json b/apps/next13/package.json index 4a95146f37..c5e9021482 100644 --- a/apps/next13/package.json +++ b/apps/next13/package.json @@ -19,7 +19,7 @@ "@hookform/error-message": "2.0.0", "@hookform/resolvers": "2.9.10", "@prisma/client": "^4.5.0", - "@tanstack/react-query": "5.51.1", + "@tanstack/react-query": "4.0.10", "blitz": "2.2.1", "flatted": "3.2.7", "next": "15.0.1", diff --git a/apps/next13/src/app/loading.tsx b/apps/next13/src/app/loading.tsx deleted file mode 100644 index 2a20138001..0000000000 --- a/apps/next13/src/app/loading.tsx +++ /dev/null @@ -1,4 +0,0 @@ -export default function Loading() { - // You can add any UI inside Loading, including a Skeleton. - return "Loading..." -} diff --git a/apps/next13/src/app/react-query.tsx b/apps/next13/src/app/react-query.tsx index c12a61b4da..aeadd4868d 100644 --- a/apps/next13/src/app/react-query.tsx +++ b/apps/next13/src/app/react-query.tsx @@ -1,6 +1,6 @@ "use client" -import {useQuery, useMutation, useSuspenseQuery} from "@blitzjs/rpc" +import {useQuery, useMutation} from "@blitzjs/rpc" import logout from "../auth/mutations/logout" import getCurrentUser from "../users/queries/getCurrentUser" import {useTransition} from "react" @@ -8,7 +8,7 @@ import {useRouter} from "next/navigation" export default function Test() { const router = useRouter() - const [user] = useSuspenseQuery(getCurrentUser, null) + const [user] = useQuery(getCurrentUser, null) const [isPending, startTransition] = useTransition() const [logoutMutation] = useMutation(logout) console.log(user) diff --git a/apps/toolkit-app-passportjs/next-env.d.ts b/apps/toolkit-app-passportjs/next-env.d.ts index a4a7b3f5cf..4f11a03dc6 100644 --- a/apps/toolkit-app-passportjs/next-env.d.ts +++ b/apps/toolkit-app-passportjs/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/apps/toolkit-app/next.config.js b/apps/toolkit-app/next.config.js index 8fb0eda0ab..8840fb33b3 100644 --- a/apps/toolkit-app/next.config.js +++ b/apps/toolkit-app/next.config.js @@ -1,3 +1,4 @@ +const { withNextAuthAdapter } = require("@blitzjs/auth/next-auth") const { withBlitz } = require("@blitzjs/next") /** @@ -10,4 +11,4 @@ const config = { }, } -module.exports = withBlitz(config) +module.exports = withBlitz(withNextAuthAdapter(config)) diff --git a/apps/toolkit-app/src/pages/api/auth/[...nextauth].ts b/apps/toolkit-app/src/pages/api/auth/[...nextauth].ts new file mode 100644 index 0000000000..5f9a90f21a --- /dev/null +++ b/apps/toolkit-app/src/pages/api/auth/[...nextauth].ts @@ -0,0 +1,48 @@ +import { api } from "src/blitz-server" +import GithubProvider from "next-auth/providers/github" +import EmailProvider from "next-auth/providers/email" +import { NextAuthAdapter, BlitzNextAuthOptions } from "@blitzjs/auth/next-auth" +import db, { User } from "db" +import { Role } from "types" + +// Has to be defined separately for `profile` to be correctly typed below +const providers = [ + GithubProvider({ + clientId: process.env.GITHUB_CLIENT_ID as string, + clientSecret: process.env.GITHUB_CLIENT_SECRET as string, + }), + EmailProvider({ + from: process.env.GITHUB_CLIENT_ID as string, + server: process.env.GITHUB_CLIENT_SECRET as string, + }), +] + +export default api( + NextAuthAdapter({ + successRedirectUrl: "/", + errorRedirectUrl: "/error", + providers, + callback: async (user, account, profile, session) => { + console.log("USER SIDE PROFILE_DATA", { user, account, profile }) + let newUser: User + try { + newUser = await db.user.findFirstOrThrow({ where: { name: { equals: user.name } } }) + } catch (e) { + newUser = await db.user.create({ + data: { + email: user.email as string, + name: user.name as string, + role: "USER", + }, + }) + } + const publicData = { + userId: newUser.id, + role: newUser.role as Role, + source: "github", + } + await session.$create(publicData) + return { redirectUrl: "/" } + }, + }) +) diff --git a/apps/toolkit-app/src/pages/index.tsx b/apps/toolkit-app/src/pages/index.tsx index 03435b61bd..58e6730bc8 100644 --- a/apps/toolkit-app/src/pages/index.tsx +++ b/apps/toolkit-app/src/pages/index.tsx @@ -44,6 +44,11 @@ const UserInfo = () => { Login + + + Sign in with GitHub + + ) } diff --git a/apps/web/next-env.d.ts b/apps/web/next-env.d.ts index a4a7b3f5cf..4f11a03dc6 100644 --- a/apps/web/next-env.d.ts +++ b/apps/web/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/apps/web/src/pages/api/auth/[...auth].ts b/apps/web/src/pages/api/auth/[...auth].ts new file mode 100644 index 0000000000..1a7d874e06 --- /dev/null +++ b/apps/web/src/pages/api/auth/[...auth].ts @@ -0,0 +1,44 @@ +import {passportAuth} from "@blitzjs/auth" +import {api} from "src/blitz-server" +import db from "db" +import {Strategy as TwitterStrategy} from "passport-twitter" + +export default api( + passportAuth({ + successRedirectUrl: "/", + errorRedirectUrl: "/", + strategies: [ + { + strategy: new TwitterStrategy( + { + consumerKey: process.env.TWITTER_CONSUMER_KEY as string, + consumerSecret: process.env.TWITTER_CONSUMER_SECRET as string, + accessTokenURL: "https://api.twitter.com/oauth/access_token", + callbackURL: "http://127.0.0.1:3000/api/auth/twitter/callback", + includeEmail: true, + }, + async function (_token, _tokenSecret, profile, done) { + const email = profile.emails?.[0]?.value ?? "blitz@test.com" + + const user = await db.user.upsert({ + where: {email}, + create: { + email, + name: profile.displayName, + }, + update: {email}, + }) + + const publicData = { + userId: user.id, + roles: [user.role], + source: "twitter", + } + + done(undefined, {publicData}) + }, + ), + }, + ], + }), +) diff --git a/apps/web/src/pages/page-with-inf-prefetch.tsx b/apps/web/src/pages/page-with-inf-prefetch.tsx index 23d0946478..ca48f2408f 100644 --- a/apps/web/src/pages/page-with-inf-prefetch.tsx +++ b/apps/web/src/pages/page-with-inf-prefetch.tsx @@ -1,4 +1,4 @@ -import {useSuspenseInfiniteQuery} from "@blitzjs/rpc" +import {useInfiniteQuery} from "@blitzjs/rpc" import {gSSP} from "src/blitz-server" import getInfiniteUsers from "src/queries/getInfiniteUsers" @@ -10,14 +10,9 @@ export const getServerSideProps = gSSP(async ({ctx}) => { }) function PageWithPrefetchInfiniteQuery(props) { - const [usersPages] = useSuspenseInfiniteQuery( - getInfiniteUsers, - (page = {take: 3, skip: 0}) => page, - { - getNextPageParam: (lastPage) => lastPage.nextPage, - initialPageParam: {take: 3, skip: 0}, - }, - ) + const [usersPages] = useInfiniteQuery(getInfiniteUsers, (page = {take: 3, skip: 0}) => page, { + getNextPageParam: (lastPage) => lastPage.nextPage, + }) return (
{usersPages.map((usersPage) => diff --git a/apps/web/src/pages/page-with-prefetch.tsx b/apps/web/src/pages/page-with-prefetch.tsx index c6e0bff679..1b9da771a6 100644 --- a/apps/web/src/pages/page-with-prefetch.tsx +++ b/apps/web/src/pages/page-with-prefetch.tsx @@ -1,4 +1,4 @@ -import {useSuspenseQuery} from "@blitzjs/rpc" +import {useQuery} from "@blitzjs/rpc" import {gSSP} from "src/blitz-server" import getUsers from "src/queries/getUsers" @@ -10,7 +10,7 @@ export const getServerSideProps = gSSP(async ({ctx}) => { }) function PageWithPrefetch(props) { - const [users] = useSuspenseQuery(getUsers, {}) + const [users] = useQuery(getUsers, {}) return (
{users.map((u) => ( diff --git a/apps/web/src/pages/users.tsx b/apps/web/src/pages/users.tsx index b04844e551..487c6e6fe4 100644 --- a/apps/web/src/pages/users.tsx +++ b/apps/web/src/pages/users.tsx @@ -7,7 +7,7 @@ function UsersPage() {
Users:
    - {users?.map((user) => ( + {users.map((user) => (
  • {user.name} - {user.email}
  • diff --git a/integration-tests/auth-with-rpc/next-env.d.ts b/integration-tests/auth-with-rpc/next-env.d.ts index a4a7b3f5cf..4f11a03dc6 100644 --- a/integration-tests/auth-with-rpc/next-env.d.ts +++ b/integration-tests/auth-with-rpc/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/integration-tests/auth-with-rpc/package.json b/integration-tests/auth-with-rpc/package.json index a47160b9ab..ba9df6499d 100644 --- a/integration-tests/auth-with-rpc/package.json +++ b/integration-tests/auth-with-rpc/package.json @@ -49,7 +49,7 @@ "husky": "8.0.2", "jsdom": "20.0.3", "lint-staged": "13.0.3", - "playwright": "1.49.1", + "playwright": "1.28.0", "prettier": "^2.7.1", "prettier-plugin-prisma": "4.4.0", "pretty-quick": "3.1.3", diff --git a/integration-tests/auth-with-rpc/src/pages/authenticated-query.tsx b/integration-tests/auth-with-rpc/src/pages/authenticated-query.tsx index a48556d78c..32d61d4e0b 100644 --- a/integration-tests/auth-with-rpc/src/pages/authenticated-query.tsx +++ b/integration-tests/auth-with-rpc/src/pages/authenticated-query.tsx @@ -1,14 +1,13 @@ -import {QueryClient, useMutation, useQuery} from "@blitzjs/rpc" +import {useMutation, useQuery} from "@blitzjs/rpc" import logout from "../mutations/logout" import getAuthenticatedBasic from "../queries/getAuthenticatedBasic" +import {Suspense} from "react" function Content() { - const [result, {isLoading, isError, error}] = useQuery(getAuthenticatedBasic, undefined) + const [result] = useQuery(getAuthenticatedBasic, undefined) const [logoutMutation] = useMutation(logout) - if (isError) throw error - if (isLoading || !result) return
    Loading...
    return ( - <> +
    {result}
    - +
    ) } function AuthenticatedQuery() { return (
    - + + +
    ) } diff --git a/integration-tests/auth-with-rpc/src/pages/layout-authenticate-redirect.tsx b/integration-tests/auth-with-rpc/src/pages/layout-authenticate-redirect.tsx index 97d8cfe28a..2beb50a154 100644 --- a/integration-tests/auth-with-rpc/src/pages/layout-authenticate-redirect.tsx +++ b/integration-tests/auth-with-rpc/src/pages/layout-authenticate-redirect.tsx @@ -1,4 +1,4 @@ -import {useMutation, useSuspenseQuery} from "@blitzjs/rpc" +import {useMutation, useQuery} from "@blitzjs/rpc" import {BlitzPage} from "@blitzjs/next" import AuthenticateRedirectLayout from "../layouts/AuthenticateRedirectLayout" import logout from "../mutations/logout" @@ -6,7 +6,7 @@ import getAuthenticatedBasic from "../queries/getAuthenticatedBasic" import {Suspense} from "react" function Content() { - const [result] = useSuspenseQuery(getAuthenticatedBasic, undefined) + const [result] = useQuery(getAuthenticatedBasic, undefined) const [logoutMutation] = useMutation(logout) return (
    diff --git a/integration-tests/auth-with-rpc/src/pages/login.tsx b/integration-tests/auth-with-rpc/src/pages/login.tsx index b2998ee778..20d64e2737 100644 --- a/integration-tests/auth-with-rpc/src/pages/login.tsx +++ b/integration-tests/auth-with-rpc/src/pages/login.tsx @@ -1,5 +1,5 @@ import {useRouter} from "next/router" -import {useMutation, useSuspenseQuery} from "@blitzjs/rpc" +import {useMutation, useQuery} from "@blitzjs/rpc" import login from "../mutations/login" import logout from "../mutations/logout" import getCurrentUser from "../queries/getCurrentUser" @@ -8,7 +8,7 @@ import {Suspense, useState} from "react" function Content() { const router = useRouter() const [error, setError] = useState(null) - const [userId] = useSuspenseQuery(getCurrentUser, null) + const [userId] = useQuery(getCurrentUser, null) const [loginMutation] = useMutation(login) const [logoutMutation] = useMutation(logout) diff --git a/integration-tests/auth-with-rpc/src/pages/noauth-query.tsx b/integration-tests/auth-with-rpc/src/pages/noauth-query.tsx index 3b45207baa..42f2a5c887 100644 --- a/integration-tests/auth-with-rpc/src/pages/noauth-query.tsx +++ b/integration-tests/auth-with-rpc/src/pages/noauth-query.tsx @@ -1,9 +1,9 @@ -import {useSuspenseQuery} from "@blitzjs/rpc" +import {useQuery} from "@blitzjs/rpc" import getNoauthBasic from "../queries/getNoauthBasic" import {Suspense} from "react" function Content() { - const [result] = useSuspenseQuery(getNoauthBasic, undefined) + const [result] = useQuery(getNoauthBasic, undefined) return
    {result}
    } diff --git a/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-redirect.tsx b/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-redirect.tsx index 749ff02259..457609abbe 100644 --- a/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-redirect.tsx +++ b/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-redirect.tsx @@ -1,11 +1,11 @@ -import {useMutation, useSuspenseQuery} from "@blitzjs/rpc" +import {useMutation, useQuery} from "@blitzjs/rpc" import {BlitzPage} from "@blitzjs/next" import logout from "../mutations/logout" import getAuthenticatedBasic from "../queries/getAuthenticatedBasic" import {Suspense} from "react" function Content() { - const [result] = useSuspenseQuery(getAuthenticatedBasic, undefined) + const [result] = useQuery(getAuthenticatedBasic, undefined) const [logoutMutation] = useMutation(logout) return (
    diff --git a/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-role-redirect-stay.tsx b/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-role-redirect-stay.tsx index 25be46a783..a4b9cb5fb5 100644 --- a/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-role-redirect-stay.tsx +++ b/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-role-redirect-stay.tsx @@ -1,11 +1,11 @@ -import {useMutation, useSuspenseQuery} from "@blitzjs/rpc" +import {useMutation, useQuery} from "@blitzjs/rpc" import {BlitzPage} from "@blitzjs/next" import logout from "../mutations/logout" import getAuthenticatedBasic from "../queries/getAuthenticatedBasic" import {Suspense} from "react" function Content() { - const [result] = useSuspenseQuery(getAuthenticatedBasic, undefined) + const [result] = useQuery(getAuthenticatedBasic, undefined) const [logoutMutation] = useMutation(logout) return (
    diff --git a/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-role-redirect.tsx b/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-role-redirect.tsx index fa76850c33..59f64fc5e4 100644 --- a/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-role-redirect.tsx +++ b/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-role-redirect.tsx @@ -1,11 +1,11 @@ -import {useMutation, useSuspenseQuery} from "@blitzjs/rpc" +import {useMutation, useQuery} from "@blitzjs/rpc" import {BlitzPage} from "@blitzjs/next" import logout from "../mutations/logout" import getAuthenticatedBasic from "../queries/getAuthenticatedBasic" import {Suspense} from "react" function Content() { - const [result] = useSuspenseQuery(getAuthenticatedBasic, undefined) + const [result] = useQuery(getAuthenticatedBasic, undefined) const [logoutMutation] = useMutation(logout) return (
    diff --git a/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-role-working.tsx b/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-role-working.tsx index 1cf83dcb6a..df3ffcdf3a 100644 --- a/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-role-working.tsx +++ b/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-role-working.tsx @@ -1,11 +1,11 @@ -import {useMutation, useSuspenseQuery} from "@blitzjs/rpc" +import {useMutation, useQuery} from "@blitzjs/rpc" import {BlitzPage} from "@blitzjs/next" import logout from "../mutations/logout" import getAuthenticatedBasic from "../queries/getAuthenticatedBasic" import {Suspense} from "react" function Content() { - const [result] = useSuspenseQuery(getAuthenticatedBasic, undefined) + const [result] = useQuery(getAuthenticatedBasic, undefined) const [logoutMutation] = useMutation(logout) return (
    diff --git a/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-role.tsx b/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-role.tsx index 10212669e8..c67446e0c2 100644 --- a/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-role.tsx +++ b/integration-tests/auth-with-rpc/src/pages/page-dot-authenticate-role.tsx @@ -1,11 +1,11 @@ -import {useMutation, useSuspenseQuery} from "@blitzjs/rpc" +import {useMutation, useQuery} from "@blitzjs/rpc" import {BlitzPage} from "@blitzjs/next" import logout from "../mutations/logout" import getAuthenticatedBasic from "../queries/getAuthenticatedBasic" import {Suspense} from "react" function Content() { - const [result] = useSuspenseQuery(getAuthenticatedBasic, undefined) + const [result] = useQuery(getAuthenticatedBasic, undefined) const [logoutMutation] = useMutation(logout) return (
    diff --git a/integration-tests/auth-with-rpc/src/pages/prefetching.tsx b/integration-tests/auth-with-rpc/src/pages/prefetching.tsx index d7a8b50734..ce418cc871 100644 --- a/integration-tests/auth-with-rpc/src/pages/prefetching.tsx +++ b/integration-tests/auth-with-rpc/src/pages/prefetching.tsx @@ -32,9 +32,9 @@ type Props = { } export const getServerSideProps = gSSP(async ({ctx}) => { - await getQueryClient().prefetchQuery({ - queryKey: getQueryKey(getNoauthBasic), - }) + await getQueryClient().prefetchQuery(getQueryKey(getNoauthBasic, null), () => + getNoauthBasic(null, ctx), + ) return { props: { dehydratedState: dehydrate(queryClient), diff --git a/integration-tests/auth-with-rpc/src/pages/set-public-data.tsx b/integration-tests/auth-with-rpc/src/pages/set-public-data.tsx index b3048cd8dd..8971d80121 100644 --- a/integration-tests/auth-with-rpc/src/pages/set-public-data.tsx +++ b/integration-tests/auth-with-rpc/src/pages/set-public-data.tsx @@ -1,10 +1,10 @@ -import {invalidateQuery, useMutation, useSuspenseQuery} from "@blitzjs/rpc" +import {invalidateQuery, useMutation, useQuery} from "@blitzjs/rpc" import changeRole from "../mutations/changeRole" import getPublicDataForUser from "../queries/getPublicDataForUser" import {Suspense} from "react" function Content() { - const [publicData] = useSuspenseQuery(getPublicDataForUser, {userId: 1}) + const [publicData] = useQuery(getPublicDataForUser, {userId: 1}) return (
    <> diff --git a/integration-tests/auth/next-env.d.ts b/integration-tests/auth/next-env.d.ts index a4a7b3f5cf..4f11a03dc6 100644 --- a/integration-tests/auth/next-env.d.ts +++ b/integration-tests/auth/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/integration-tests/auth/package.json b/integration-tests/auth/package.json index 4f9cf77ea1..3694c94ec2 100644 --- a/integration-tests/auth/package.json +++ b/integration-tests/auth/package.json @@ -42,7 +42,7 @@ "fs-extra": "10.0.1", "get-port": "6.1.2", "node-fetch": "3.2.3", - "playwright": "1.49.1", + "playwright": "1.28.0", "ts-node": "10.9.1", "typescript": "^4.8.4" } diff --git a/integration-tests/get-initial-props/next-env.d.ts b/integration-tests/get-initial-props/next-env.d.ts index 725dd6f245..4f11a03dc6 100644 --- a/integration-tests/get-initial-props/next-env.d.ts +++ b/integration-tests/get-initial-props/next-env.d.ts @@ -1,6 +1,5 @@ /// /// -/// // NOTE: This file should not be edited -// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/integration-tests/get-initial-props/tsconfig.json b/integration-tests/get-initial-props/tsconfig.json index b3f2aed3d2..f391da135f 100644 --- a/integration-tests/get-initial-props/tsconfig.json +++ b/integration-tests/get-initial-props/tsconfig.json @@ -1,16 +1,10 @@ { "extends": "@blitzjs/config/tsconfig.nextjs.json", - "include": ["**/*.ts", "**/*.tsx", "next-env.d.ts", "types", ".next/types/**/*.ts"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "types"], "compilerOptions": { "paths": { "react": ["./node_modules/@types/react"] - }, - "plugins": [ - { - "name": "next" - } - ], - "strictNullChecks": true + } }, "exclude": ["node_modules"], "baseUrl": "." diff --git a/integration-tests/middleware/next-env.d.ts b/integration-tests/middleware/next-env.d.ts index 725dd6f245..fd36f9494e 100644 --- a/integration-tests/middleware/next-env.d.ts +++ b/integration-tests/middleware/next-env.d.ts @@ -3,4 +3,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/integration-tests/next-13-app-dir/app/react-query/query.tsx b/integration-tests/next-13-app-dir/app/react-query/query.tsx index cc3f0582b5..d2cbd8628d 100644 --- a/integration-tests/next-13-app-dir/app/react-query/query.tsx +++ b/integration-tests/next-13-app-dir/app/react-query/query.tsx @@ -1,10 +1,10 @@ "use client" -import {getQueryData, useSuspenseQuery} from "@blitzjs/rpc" +import {getQueryData, useQuery} from "@blitzjs/rpc" import {Suspense, useState} from "react" import getBasic from "../../src/queries/getBasic" function Content() { - const [data] = useSuspenseQuery(getBasic, undefined) + const [data] = useQuery(getBasic, undefined) const [newData, setNewData] = useState() return (
    diff --git a/integration-tests/next-13-app-dir/package.json b/integration-tests/next-13-app-dir/package.json index 492ce7132d..1577c8786a 100644 --- a/integration-tests/next-13-app-dir/package.json +++ b/integration-tests/next-13-app-dir/package.json @@ -43,7 +43,7 @@ "fs-extra": "10.0.1", "get-port": "6.1.2", "node-fetch": "3.2.3", - "playwright": "1.49.1", + "playwright": "1.28.0", "ts-node": "10.9.1", "typescript": "^4.9.5" } diff --git a/integration-tests/no-suspense/next-env.d.ts b/integration-tests/no-suspense/next-env.d.ts index 725dd6f245..4f11a03dc6 100644 --- a/integration-tests/no-suspense/next-env.d.ts +++ b/integration-tests/no-suspense/next-env.d.ts @@ -1,6 +1,5 @@ /// /// -/// // NOTE: This file should not be edited -// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/integration-tests/no-suspense/tsconfig.json b/integration-tests/no-suspense/tsconfig.json index b3f2aed3d2..f391da135f 100644 --- a/integration-tests/no-suspense/tsconfig.json +++ b/integration-tests/no-suspense/tsconfig.json @@ -1,16 +1,10 @@ { "extends": "@blitzjs/config/tsconfig.nextjs.json", - "include": ["**/*.ts", "**/*.tsx", "next-env.d.ts", "types", ".next/types/**/*.ts"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "types"], "compilerOptions": { "paths": { "react": ["./node_modules/@types/react"] - }, - "plugins": [ - { - "name": "next" - } - ], - "strictNullChecks": true + } }, "exclude": ["node_modules"], "baseUrl": "." diff --git a/integration-tests/qm/package.json b/integration-tests/qm/package.json index adb503927f..39ed74b00a 100644 --- a/integration-tests/qm/package.json +++ b/integration-tests/qm/package.json @@ -13,7 +13,7 @@ "@blitzjs/next": "2.2.1", "@blitzjs/rpc": "2.2.1", "@prisma/client": "6.1.0", - "@tanstack/react-query": "5.51.1", + "@tanstack/react-query": "4.0.10", "blitz": "2.2.1", "next": "15.0.1", "prisma": "6.1.0", diff --git a/integration-tests/qm/test/__snapshots__/use-query.test.tsx.snap b/integration-tests/qm/test/__snapshots__/use-query.test.tsx.snap index 9666036a0c..d5ffa3c0bc 100644 --- a/integration-tests/qm/test/__snapshots__/use-query.test.tsx.snap +++ b/integration-tests/qm/test/__snapshots__/use-query.test.tsx.snap @@ -3,7 +3,3 @@ exports[`useQuery > a "query" that converts the string parameter to uppercase > shouldn't work with mutation function 1`] = `"\\"useQuery\\" was expected to be called with a query but was called with a \\"mutation\\""`; exports[`useQuery > a "query" that converts the string parameter to uppercase > shouldn't work with regular functions 1`] = `"Either the file path to your resolver is incorrect (must be in a \\"queries\\" or \\"mutations\\" folder that isn't nested inside \\"pages\\" or \\"api\\") or you are trying to use Blitz's useQuery to fetch from third-party APIs (to do that, import useQuery directly from \\"@tanstack/react-query\\")."`; - -exports[`useSuspenseQuery > a "query" that converts the string parameter to uppercase > shouldn't work with mutation function 1`] = `"\\"useQuery\\" was expected to be called with a query but was called with a \\"mutation\\""`; - -exports[`useSuspenseQuery > a "query" that converts the string parameter to uppercase > shouldn't work with regular functions 1`] = `"Either the file path to your resolver is incorrect (must be in a \\"queries\\" or \\"mutations\\" folder that isn't nested inside \\"pages\\" or \\"api\\") or you are trying to use Blitz's useQuery to fetch from third-party APIs (to do that, import useQuery directly from \\"@tanstack/react-query\\")."`; diff --git a/integration-tests/qm/test/use-query.test.tsx b/integration-tests/qm/test/use-query.test.tsx index 7031aa43ed..05c2a933f6 100644 --- a/integration-tests/qm/test/use-query.test.tsx +++ b/integration-tests/qm/test/use-query.test.tsx @@ -1,12 +1,6 @@ import {describe, it, expect, beforeAll, vi} from "vitest" import {act, screen, waitForElementToBeRemoved} from "@testing-library/react" -import { - useSuspenseQuery, - useQuery, - useSuspenseInfiniteQuery, - BlitzRpcPlugin, - BlitzProvider, -} from "@blitzjs/rpc" +import {useQuery, useInfiniteQuery, BlitzRpcPlugin, BlitzProvider} from "@blitzjs/rpc" import React from "react" import delay from "delay" import {buildMutationRpc, buildQueryRpc, mockRouter, render} from "../../utils/blitz-test-utils" @@ -17,18 +11,19 @@ beforeAll(() => { globalThis.IS_REACT_ACT_ENVIRONMENT = true }) -describe("useSuspenseQuery", () => { +describe("useQuery", () => { const setupHook = ( ID: string, params: any, queryFn: (...args: any) => any, - options: Parameters[2] = {} as any, + options: Parameters[2] = {} as any, ): [{data?: any; setQueryData?: any}, Function] => { let res = {} const qc = BlitzRpcPlugin({}) - function TestSuspenseHarness() { - const [data, {setQueryData}] = useSuspenseQuery(queryFn, params, { + function TestHarness() { + const [data, {setQueryData}] = useQuery(queryFn, params, { + suspense: true, ...(options as any), } as any) @@ -43,7 +38,7 @@ describe("useSuspenseQuery", () => { const ui = () => ( - + ) @@ -95,101 +90,6 @@ describe("useSuspenseQuery", () => { expect(() => setupHook("5", "test", buildMutationRpc(upcase))).toThrowErrorMatchingSnapshot() }) - it("works with options other than enabled & suspense without type error", () => { - const Demo = () => { - useSuspenseQuery(buildQueryRpc(upcase), undefined, {refetchInterval: 10000}) - return
    - } - const ui = () => - - const {rerender} = render(ui(), { - wrapper: ({children}) => ( - - {children} - - ), - }) - }) - }) -}) - -describe("useQuery", () => { - const setupHook = ( - ID: string, - params: any, - queryFn: (...args: any) => any, - options: Parameters[2] = {} as any, - ): [{data?: any; setQueryData?: any}, Function] => { - let res = {} - const qc = BlitzRpcPlugin({}) - - function TestHarness() { - const [data, {setQueryData, isLoading}] = useQuery(queryFn, params, { - ...(options as any), - } as any) - - Object.assign(res, {data, setQueryData}) - if (isLoading) { - return
    Loading...
    - } - return ( -
    - {data ? `Ready${ID}` : "No data"} - {data} -
    - ) - } - - const ui = () => - - const {rerender} = render(ui(), { - wrapper: ({children}) => ( - - {children} - - ), - }) - return [res, () => rerender(ui())] - } - - describe('a "query" that converts the string parameter to uppercase', () => { - const upcase = async (args: string) => { - await delay(500) - return args.toUpperCase() - } - - it("should work with Blitz queries", async () => { - const [res] = setupHook("2", "test", buildQueryRpc(upcase)) - await waitForElementToBeRemoved(() => screen.getByText("Loading...")) - await act(async () => { - await screen.queryAllByText("Ready2")[0] - expect(res.data).toBe("TEST") - }) - }) - - it("should be able to change the data with setQueryData", async () => { - const [res] = setupHook("3", "fooBar", buildQueryRpc(upcase)) - await waitForElementToBeRemoved(() => screen.getByText("Loading...")) - await act(async () => { - await screen.queryAllByText("Ready3")[0] - expect(res.data).toBe("FOOBAR") - res.setQueryData((p: string) => p.substr(3, 3), {refetch: false}) - await delay(100) - }) - - expect(res.data).toBe("BAR") - }) - - it("shouldn't work with regular functions", () => { - console.error = vi.fn() - expect(() => setupHook("4", "test", upcase)).toThrowErrorMatchingSnapshot() - }) - - it("shouldn't work with mutation function", () => { - console.error = vi.fn() - expect(() => setupHook("5", "test", buildMutationRpc(upcase))).toThrowErrorMatchingSnapshot() - }) - it("suspense disabled if enabled is false", async () => { setupHook("6", "test", buildQueryRpc(upcase), {enabled: false}) await screen.findByText("No data") @@ -200,9 +100,17 @@ describe("useQuery", () => { await screen.findByText("No data") }) + // it("suspense disabled if enabled is false and suspense set", async () => { + // setupHook("8", "test", buildQueryRpc(upcase), { + // enabled: false, + // suspense: true, + // }) + // await screen.findByText("No data") + // }) + it("works with options other than enabled & suspense without type error", () => { const Demo = () => { - useSuspenseQuery(buildQueryRpc(upcase), undefined, {refetchInterval: 10000}) + useQuery(buildQueryRpc(upcase), undefined, {refetchInterval: 10000}) return
    } const ui = () => @@ -218,7 +126,7 @@ describe("useQuery", () => { }) }) -describe("useSuspenseInfiniteQuery", () => { +describe("useInfiniteQuery", () => { const setupHook = ( ID: string, params: (arg?: any) => any, @@ -230,7 +138,7 @@ describe("useSuspenseInfiniteQuery", () => { function TestHarness() { // TODO - fix typing //@ts-ignore - const [groupedData] = useSuspenseInfiniteQuery(queryFn, params, { + const [groupedData] = useInfiniteQuery(queryFn, params, { suspense: true, getNextPageParam: () => {}, }) diff --git a/integration-tests/react-query-utils/next-env.d.ts b/integration-tests/react-query-utils/next-env.d.ts index 725dd6f245..fd36f9494e 100644 --- a/integration-tests/react-query-utils/next-env.d.ts +++ b/integration-tests/react-query-utils/next-env.d.ts @@ -3,4 +3,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/integration-tests/react-query-utils/pages/page-with-get-query-data.tsx b/integration-tests/react-query-utils/pages/page-with-get-query-data.tsx index 091188a299..6e737bfe59 100644 --- a/integration-tests/react-query-utils/pages/page-with-get-query-data.tsx +++ b/integration-tests/react-query-utils/pages/page-with-get-query-data.tsx @@ -1,9 +1,9 @@ -import {getQueryData, useSuspenseQuery} from "@blitzjs/rpc" +import {getQueryData, useQuery} from "@blitzjs/rpc" import {Suspense, useState} from "react" import getBasic from "../app/queries/getBasic" function Content() { - const [data] = useSuspenseQuery(getBasic, undefined) + const [data] = useQuery(getBasic, undefined) const [newData, setNewData] = useState() return (
    diff --git a/integration-tests/react-query-utils/pages/page-with-invalidate.tsx b/integration-tests/react-query-utils/pages/page-with-invalidate.tsx index 308c0e8370..01d254ddb8 100644 --- a/integration-tests/react-query-utils/pages/page-with-invalidate.tsx +++ b/integration-tests/react-query-utils/pages/page-with-invalidate.tsx @@ -1,9 +1,9 @@ import React, {Suspense} from "react" import {BlitzPage} from "@blitzjs/next" -import {invalidateQuery, useSuspenseQuery} from "@blitzjs/rpc" +import {invalidateQuery, useQuery} from "@blitzjs/rpc" import getSequence from "../app/queries/getSequence" -const useSuspenseQueryOptions = { +const useQueryOptions = { refetchInterval: 0, refetchOnMount: false, refetchOnReconnect: false, @@ -11,16 +11,8 @@ const useSuspenseQueryOptions = { } const PageWithInvalidateQuery: React.FC = () => { - const [query1, {isFetching: isQ1Fetching}] = useSuspenseQuery( - getSequence, - "query1", - useSuspenseQueryOptions, - ) - const [query2, {isFetching: isQ2Fetching}] = useSuspenseQuery( - getSequence, - "query2", - useSuspenseQueryOptions, - ) + const [query1, {isFetching: isQ1Fetching}] = useQuery(getSequence, "query1", useQueryOptions) + const [query2, {isFetching: isQ2Fetching}] = useQuery(getSequence, "query2", useQueryOptions) const isFetching = isQ1Fetching || isQ2Fetching diff --git a/integration-tests/react-query-utils/pages/page-with-monorepo-query.tsx b/integration-tests/react-query-utils/pages/page-with-monorepo-query.tsx index 6f73038f88..5cb431b1ae 100644 --- a/integration-tests/react-query-utils/pages/page-with-monorepo-query.tsx +++ b/integration-tests/react-query-utils/pages/page-with-monorepo-query.tsx @@ -1,9 +1,9 @@ -import {getQueryData, useSuspenseQuery} from "@blitzjs/rpc" +import {getQueryData, useQuery} from "@blitzjs/rpc" import {Suspense, useState} from "react" import getNoSuspenseBasic from "../../no-suspense/app/queries/getNoSuspenseBasic" function Content() { - const [data] = useSuspenseQuery(getNoSuspenseBasic, undefined) + const [data] = useQuery(getNoSuspenseBasic, undefined) const [newData, setNewData] = useState() return (
    diff --git a/integration-tests/react-query-utils/pages/page-with-prefetch-inf-query.tsx b/integration-tests/react-query-utils/pages/page-with-prefetch-inf-query.tsx index 0b0981ff8f..622ecfa879 100644 --- a/integration-tests/react-query-utils/pages/page-with-prefetch-inf-query.tsx +++ b/integration-tests/react-query-utils/pages/page-with-prefetch-inf-query.tsx @@ -1,4 +1,4 @@ -import {useSuspenseInfiniteQuery} from "@blitzjs/rpc" +import {useInfiniteQuery} from "@blitzjs/rpc" import {gSSP} from "../app/blitz-server" import testQuery from "../app/queries/getInfiniteData" @@ -12,12 +12,12 @@ export const getServerSideProps = gSSP(async ({ctx}) => { }) const PageWithPrefetchInfQuery = () => { - const [data] = useSuspenseInfiniteQuery( + const [data] = useInfiniteQuery( testQuery, (pageParams) => ({...pageParams, name: "hello world"}), { + suspense: false, getNextPageParam: (lastPage) => lastPage, - initialPageParam: {name: "hello world"}, }, ) return
    {data ? data : "no-data"}
    diff --git a/integration-tests/react-query-utils/test/index.test.ts b/integration-tests/react-query-utils/test/index.test.ts index c73053497b..7423ec1cc8 100644 --- a/integration-tests/react-query-utils/test/index.test.ts +++ b/integration-tests/react-query-utils/test/index.test.ts @@ -51,22 +51,22 @@ const runTests = () => { ) }) - // describe("prefetch infinite query", () => { - // it( - // "should work", - // async () => { - // const browser = await webdriver(appPort, "/page-with-prefetch-inf-query") - - // browser.waitForElementByCss("#data", 0) - // const newText = await browser.elementByCss("#data").text() - // expect(newText).not.toMatch("no-data") - // expect(newText).toMatch("thanks") - - // if (browser) await browser.close() - // }, - // 5000 * 60 * 2, - // ) - // }) + describe("prefetch infinite query", () => { + it( + "should work", + async () => { + const browser = await webdriver(appPort, "/page-with-prefetch-inf-query") + + browser.waitForElementByCss("#data", 0) + const newText = await browser.elementByCss("#data").text() + expect(newText).not.toMatch("no-data") + expect(newText).toMatch("thanks") + + if (browser) await browser.close() + }, + 5000 * 60 * 2, + ) + }) describe("invalidate query", () => { it( diff --git a/integration-tests/trailing-slash/next-env.d.ts b/integration-tests/trailing-slash/next-env.d.ts index 725dd6f245..4f11a03dc6 100644 --- a/integration-tests/trailing-slash/next-env.d.ts +++ b/integration-tests/trailing-slash/next-env.d.ts @@ -1,6 +1,5 @@ /// /// -/// // NOTE: This file should not be edited -// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/integration-tests/trailing-slash/pages/use-query.tsx b/integration-tests/trailing-slash/pages/use-query.tsx index 51ead85c0c..2fee1c3d98 100644 --- a/integration-tests/trailing-slash/pages/use-query.tsx +++ b/integration-tests/trailing-slash/pages/use-query.tsx @@ -1,9 +1,9 @@ import getBasic from "../app/queries/getBasic" -import {useSuspenseQuery} from "@blitzjs/rpc" +import {useQuery} from "@blitzjs/rpc" import {Suspense} from "react" function Content() { - const [result] = useSuspenseQuery(getBasic, undefined) + const [result] = useQuery(getBasic, undefined) return
    {result}
    } diff --git a/integration-tests/trailing-slash/tsconfig.json b/integration-tests/trailing-slash/tsconfig.json index e39f5a770e..f391da135f 100644 --- a/integration-tests/trailing-slash/tsconfig.json +++ b/integration-tests/trailing-slash/tsconfig.json @@ -1,16 +1,10 @@ { "extends": "@blitzjs/config/tsconfig.nextjs.json", - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "types", ".next/types/**/*.ts"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "types"], "compilerOptions": { "paths": { "react": ["./node_modules/@types/react"] - }, - "plugins": [ - { - "name": "next" - } - ], - "strictNullChecks": true + } }, "exclude": ["node_modules"], "baseUrl": "." diff --git a/integration-tests/utils/package.json b/integration-tests/utils/package.json index 2af3351bc5..d5604e9d63 100644 --- a/integration-tests/utils/package.json +++ b/integration-tests/utils/package.json @@ -22,7 +22,7 @@ "get-port": "6.1.2", "node-fetch": "3.2.3", "pkg-dir": "5.0.0", - "playwright-chromium": "1.49.1", + "playwright-chromium": "1.28.0", "react": "19.0.0", "react-dom": "19.0.0", "resolve-cwd": "3.0.0", diff --git a/package.json b/package.json index bad343bf42..bfd68be590 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,9 @@ ] }, "pnpm": { + "patchedDependencies": { + "next-auth@4.24.7": "patches/next-auth@4.24.7.patch" + }, "overrides": { "@types/mime": "3.0.4", "next": "15.0.1", diff --git a/packages/blitz-auth/src/client/index.tsx b/packages/blitz-auth/src/client/index.tsx index 6190cd610a..246d1aff43 100644 --- a/packages/blitz-auth/src/client/index.tsx +++ b/packages/blitz-auth/src/client/index.tsx @@ -152,7 +152,7 @@ export interface UseSessionOptions { } export const useSession = (options: UseSessionOptions = {}): ClientSession => { - const suspense = options?.suspense ?? true + const suspense = options?.suspense ?? Boolean(globalThis.__BLITZ_SUSPENSE_ENABLED) let initialState: ClientSession if (options.initialPublicData) { diff --git a/packages/blitz-auth/src/global.ts b/packages/blitz-auth/src/global.ts index 0916eba0ff..c4def8d920 100644 --- a/packages/blitz-auth/src/global.ts +++ b/packages/blitz-auth/src/global.ts @@ -5,5 +5,6 @@ import type {SessionConfigMethods} from "./shared" declare global { var sessionConfig: AuthPluginOptions & SessionConfigMethods var __BLITZ_SESSION_COOKIE_PREFIX: string | undefined + var __BLITZ_SUSPENSE_ENABLED: boolean var __BLITZ_GET_RSC_CONTEXT: () => Promise } diff --git a/packages/blitz-next/src/index-server.ts b/packages/blitz-next/src/index-server.ts index 5be8137274..a3af4c8528 100644 --- a/packages/blitz-next/src/index-server.ts +++ b/packages/blitz-next/src/index-server.ts @@ -123,15 +123,11 @@ const prefetchQueryFactory = ( } if (infinite) { - await queryClient.prefetchQuery({ - queryKey: getInfiniteQueryKey(fn, input), - queryFn: () => fn(input, ctx), - }) + await queryClient.prefetchInfiniteQuery(getInfiniteQueryKey(fn, input), () => + fn(input, ctx), + ) } else { - await queryClient.prefetchQuery({ - queryKey: getQueryKey(fn, input), - queryFn: () => fn(input, ctx), - }) + await queryClient.prefetchQuery(getQueryKey(fn, input), () => fn(input, ctx)) } }, } @@ -247,6 +243,7 @@ export interface BlitzConfig extends NextConfig { } } + export function withBlitz(nextConfig: BlitzConfig = {}): NextConfig { if ( process.env.NODE_ENV !== "production" && diff --git a/packages/blitz-next/src/provider.tsx b/packages/blitz-next/src/provider.tsx index 51f18693d6..ba414b3162 100644 --- a/packages/blitz-next/src/provider.tsx +++ b/packages/blitz-next/src/provider.tsx @@ -1,4 +1,4 @@ -import {QueryClientProvider, HydrationBoundary} from "@blitzjs/rpc" +import {QueryClientProvider, Hydrate} from "@blitzjs/rpc" import type {QueryClient, HydrateOptions} from "@blitzjs/rpc" import React from "react" @@ -12,16 +12,20 @@ export type BlitzProviderProps = { export const BlitzProvider = ({ client = globalThis.queryClient, + contextSharing = false, dehydratedState, hydrateOptions, children, }: BlitzProviderProps) => { if (client) { return ( - - + + {children} - + ) } diff --git a/packages/blitz-rpc/package.json b/packages/blitz-rpc/package.json index bb3d0aaf7f..08c9612386 100644 --- a/packages/blitz-rpc/package.json +++ b/packages/blitz-rpc/package.json @@ -27,7 +27,7 @@ ], "dependencies": { "@swc/core": "1.3.7", - "@tanstack/react-query": "5.51.1", + "@tanstack/react-query": "4.24.4", "b64-lite": "1.4.0", "bad-behavior": "1.0.1", "chalk": "^4.1.0", @@ -36,7 +36,7 @@ "supports-color": "8.1.1" }, "peerDependencies": { - "@tanstack/query-core": "5.51.1", + "@tanstack/query-core": "4.24.4", "blitz": "2.2.1", "next": "*", "react": "*" @@ -44,7 +44,7 @@ "devDependencies": { "@blitzjs/auth": "2.2.1", "@blitzjs/config": "2.2.1", - "@tanstack/query-core": "5.51.1", + "@tanstack/query-core": "4.24.4", "@types/debug": "4.1.7", "@types/react": "npm:types-react@19.0.0", "@types/react-dom": "npm:types-react-dom@19.0.0", diff --git a/packages/blitz-rpc/src/global.ts b/packages/blitz-rpc/src/global.ts index 9b4f11c9b6..950669f38e 100644 --- a/packages/blitz-rpc/src/global.ts +++ b/packages/blitz-rpc/src/global.ts @@ -4,6 +4,7 @@ import type {Ctx} from "blitz" declare global { var queryClient: QueryClient + var __BLITZ_SUSPENSE_ENABLED: boolean var blitzRpcRpcLoggerOptions: RpcLoggerOptions | undefined var __BLITZ_GET_RSC_CONTEXT: () => Promise } diff --git a/packages/blitz-rpc/src/index-browser.tsx b/packages/blitz-rpc/src/index-browser.tsx index ed6f648eb6..a134bcde90 100644 --- a/packages/blitz-rpc/src/index-browser.tsx +++ b/packages/blitz-rpc/src/index-browser.tsx @@ -15,8 +15,6 @@ export { useMutation, usePaginatedQuery, useQuery, - useSuspenseInfiniteQuery, - useSuspenseQuery, } from "./query/react-query" export type { DefaultOptions, @@ -30,6 +28,5 @@ export type { export * from "./query/utils" import {reactQueryClientReExports} from "./query/react-query" -const {QueryClientProvider, HydrationBoundary, useQueryErrorResetBoundary} = - reactQueryClientReExports -export {QueryClientProvider, HydrationBoundary, useQueryErrorResetBoundary} +const {QueryClientProvider, Hydrate, useQueryErrorResetBoundary} = reactQueryClientReExports +export {QueryClientProvider, Hydrate, useQueryErrorResetBoundary} diff --git a/packages/blitz-rpc/src/query/react-query/index.ts b/packages/blitz-rpc/src/query/react-query/index.ts index ec1bec1097..e7aa4d0f0a 100644 --- a/packages/blitz-rpc/src/query/react-query/index.ts +++ b/packages/blitz-rpc/src/query/react-query/index.ts @@ -28,6 +28,11 @@ export const BlitzRpcPlugin = createClientPlugin< >((options?: BlitzRpcOptions) => { const initializeQueryClient = () => { const {reactQueryOptions} = options || {} + let suspenseEnabled = reactQueryOptions?.queries?.suspense ?? true + if (!process.env.CLI_COMMAND_CONSOLE && !process.env.CLI_COMMAND_DB) { + globalThis.__BLITZ_SUSPENSE_ENABLED = suspenseEnabled + } + return new QueryClient({ defaultOptions: { ...reactQueryOptions, @@ -42,6 +47,7 @@ export const BlitzRpcPlugin = createClientPlugin< return false }, ...reactQueryOptions?.queries, + suspense: suspenseEnabled, }, }, }) diff --git a/packages/blitz-rpc/src/query/react-query/react-query.ts b/packages/blitz-rpc/src/query/react-query/react-query.ts index 697cfbaa39..d8872ce867 100644 --- a/packages/blitz-rpc/src/query/react-query/react-query.ts +++ b/packages/blitz-rpc/src/query/react-query/react-query.ts @@ -1,21 +1,13 @@ -import { - useQueryErrorResetBoundary, - QueryClientProvider, - HydrationBoundary, - keepPreviousData, -} from "@tanstack/react-query" -import type {DefaultError, InfiniteData} from "@tanstack/query-core" +import {useQueryErrorResetBoundary, QueryClientProvider, Hydrate} from "@tanstack/react-query" import {useInfiniteQuery as useInfiniteReactQuery} from "@tanstack/react-query" -import {useSuspenseInfiniteQuery as useSuspenseInfiniteReactQuery} from "@tanstack/react-query" import {useQuery as useReactQuery} from "@tanstack/react-query" -import {useSuspenseQuery as useSuspenseReactQuery} from "@tanstack/react-query" import {useMutation as useReactQueryMutation} from "@tanstack/react-query" export const reactQueryClientReExports = { useQueryErrorResetBoundary, QueryClientProvider, - HydrationBoundary, + Hydrate, } import type { @@ -26,8 +18,6 @@ import type { UseMutationOptions, UseMutationResult, MutateOptions, - UseSuspenseQueryOptions, - UseSuspenseInfiniteQueryOptions, } from "@tanstack/react-query" import {isServer, FirstParam, PromiseReturnType, AsyncFunc} from "blitz" @@ -62,42 +52,43 @@ export type RestQueryResult = Omit, - TError = DefaultError, + TError = unknown, TSelectedData = TResult, >( queryFn: T, params: FirstParam, - options?: Omit, "queryKey"> & QueryNonLazyOptions, -): [TSelectedData | undefined, RestQueryResult] + options?: UseQueryOptions & QueryNonLazyOptions, +): [TSelectedData, RestQueryResult] export function useQuery< T extends AsyncFunc, TResult = PromiseReturnType, - TError = DefaultError, + TError = unknown, TSelectedData = TResult, >( queryFn: T, params: FirstParam, - options: Omit, "queryKey"> & QueryLazyOptions, -): [TSelectedData | undefined, RestQueryResult] + options: UseQueryOptions & QueryLazyOptions, +): [TSelectedData | undefined, RestQueryResult] export function useQuery< T extends AsyncFunc, TResult = PromiseReturnType, - TError = DefaultError, + TError = unknown, TSelectedData = TResult, >( queryFn: T, params: FirstParam, - options: Omit, "queryKey"> = {}, + options: UseQueryOptions = {}, ) { if (typeof queryFn === "undefined") { throw new Error("useQuery is missing the first argument - it must be a query function") } - let enabled = isServer ? false : options?.enabled ?? options?.enabled !== null + const suspenseEnabled = Boolean(globalThis.__BLITZ_SUSPENSE_ENABLED) + let enabled = isServer && suspenseEnabled ? false : options?.enabled ?? options?.enabled !== null let routerIsReady = false const router = useRouter() if (router) { - routerIsReady = router?.isReady || isServer + routerIsReady = router?.isReady || (isServer && suspenseEnabled) } else { routerIsReady = true } @@ -108,70 +99,19 @@ export function useQuery< queryKey: routerIsReady ? queryKey : ["_routerNotReady_"], queryFn: routerIsReady ? ({signal}) => enhancedResolverRpcClient(params, {fromQueryHook: true}, signal) - : (emptyQueryFn as PromiseReturnType), + : (emptyQueryFn as any), ...options, enabled, }) - const rest = { - ...queryRest, - ...getQueryCacheFunctions, TResult, T>(queryFn, params), - } - - return [data, rest] -} - -// ------------------------- -// useSuspenseQuery -// ------------------------- - -export function useSuspenseQuery< - T extends AsyncFunc, - TResult = PromiseReturnType, - TError = DefaultError, - TSelectedData = TResult, ->( - queryFn: T, - params: FirstParam, - options?: Omit, "queryKey"> & QueryNonLazyOptions, -): [TSelectedData, RestQueryResult] -export function useSuspenseQuery< - T extends AsyncFunc, - TResult = PromiseReturnType, - TError = DefaultError, - TSelectedData = TResult, ->( - queryFn: T, - params: FirstParam, - options: Omit, "queryKey"> & - QueryLazyOptions, -): [TSelectedData | undefined, RestQueryResult] -export function useSuspenseQuery< - T extends AsyncFunc, - TResult = PromiseReturnType, - TError = DefaultError, - TSelectedData = TResult, ->( - queryFn: T, - params: FirstParam, - options: Omit, "queryKey"> = {}, -) { - if (typeof queryFn === "undefined") { - throw new Error("useQuery is missing the first argument - it must be a query function") - } - - const enhancedResolverRpcClient = sanitizeQuery(queryFn) - const queryKey = getQueryKey(queryFn, params) - - let routerIsReady = false - const router = useRouter() - if (router) { - routerIsReady = router?.isReady || isServer - } else { - routerIsReady = true - } - - if (isServer) { + if ( + queryRest.fetchStatus === "idle" && + isServer && + suspenseEnabled !== false && + !data && + (!options || !("suspense" in options) || options.suspense) && + (!options || !("enabled" in options) || options.enabled) + ) { const e = new NextError() e.name = "Rendering Suspense fallback..." e.digest = "DYNAMIC_SERVER_USAGE" @@ -181,19 +121,12 @@ export function useSuspenseQuery< throw e } - const {data, ...queryRest} = useSuspenseReactQuery({ - queryKey: routerIsReady ? queryKey : ["_routerNotReady_"], - queryFn: routerIsReady - ? ({signal}) => enhancedResolverRpcClient(params, {fromQueryHook: true}, signal) - : (emptyQueryFn as PromiseReturnType), - ...options, - }) - const rest = { ...queryRest, ...getQueryCacheFunctions, TResult, T>(queryFn, params), } + // return [data, rest as RestQueryResult] return [data, rest] } @@ -206,42 +139,43 @@ export type RestPaginatedResult = Omit, - TError = DefaultError, + TError = unknown, TSelectedData = TResult, >( queryFn: T, params: FirstParam, - options?: Omit, "queryKey"> & QueryNonLazyOptions, -): [TSelectedData | undefined, RestPaginatedResult] + options?: UseQueryOptions & QueryNonLazyOptions, +): [TSelectedData, RestPaginatedResult] export function usePaginatedQuery< T extends AsyncFunc, TResult = PromiseReturnType, - TError = DefaultError, + TError = unknown, TSelectedData = TResult, >( queryFn: T, params: FirstParam, - options: Omit, "queryKey"> & QueryLazyOptions, + options: UseQueryOptions & QueryLazyOptions, ): [TSelectedData | undefined, RestPaginatedResult] export function usePaginatedQuery< T extends AsyncFunc, TResult = PromiseReturnType, - TError = DefaultError, + TError = unknown, TSelectedData = TResult, >( queryFn: T, params: FirstParam, - options: Omit, "queryKey"> = {}, + options: UseQueryOptions = {}, ) { if (typeof queryFn === "undefined") { throw new Error("usePaginatedQuery is missing the first argument - it must be a query function") } - let enabled = isServer ? false : options?.enabled ?? options?.enabled !== null + const suspenseEnabled = Boolean(globalThis.__BLITZ_SUSPENSE_ENABLED) + let enabled = isServer && suspenseEnabled ? false : options?.enabled ?? options?.enabled !== null let routerIsReady = false const router = useRouter() if (router) { - routerIsReady = router?.isReady || isServer + routerIsReady = router?.isReady || (isServer && suspenseEnabled) } else { routerIsReady = true } @@ -252,13 +186,20 @@ export function usePaginatedQuery< queryKey: routerIsReady ? queryKey : ["_routerNotReady_"], queryFn: routerIsReady ? ({signal}) => enhancedResolverRpcClient(params, {fromQueryHook: true}, signal) - : (emptyQueryFn as PromiseReturnType), + : (emptyQueryFn as any), ...options, - placeholderData: keepPreviousData, + keepPreviousData: true, enabled, }) - if (queryRest.fetchStatus === "idle" && isServer && !data) { + if ( + queryRest.fetchStatus === "idle" && + isServer && + suspenseEnabled !== false && + !data && + (!options || !("suspense" in options) || options.suspense) && + (!options || !("enabled" in options) || options.enabled) + ) { const e = new NextError() e.name = "Rendering Suspense fallback..." e.digest = "DYNAMIC_SERVER_USAGE" @@ -295,43 +236,43 @@ interface InfiniteQueryConfig export function useInfiniteQuery< T extends AsyncFunc, TResult = PromiseReturnType, - TError = DefaultError, + TError = unknown, TSelectedData = TResult, >( queryFn: T, getQueryParams: (pageParam: any) => FirstParam, - options: Omit, "queryKey"> & - QueryNonLazyOptions, -): [TSelectedData[] | undefined, RestInfiniteResult] + options: InfiniteQueryConfig & QueryNonLazyOptions, +): [TSelectedData[], RestInfiniteResult] export function useInfiniteQuery< T extends AsyncFunc, TResult = PromiseReturnType, - TError = DefaultError, + TError = unknown, TSelectedData = TResult, >( queryFn: T, getQueryParams: (pageParam: any) => FirstParam, - options: Omit, "queryKey"> & QueryLazyOptions, + options: InfiniteQueryConfig & QueryLazyOptions, ): [TSelectedData[] | undefined, RestInfiniteResult] export function useInfiniteQuery< T extends AsyncFunc, TResult = PromiseReturnType, - TError = DefaultError, + TError = unknown, TSelectedData = TResult, >( queryFn: T, getQueryParams: (pageParam: any) => FirstParam, - options: Omit, "queryKey">, + options: InfiniteQueryConfig, ) { if (typeof queryFn === "undefined") { throw new Error("useInfiniteQuery is missing the first argument - it must be a query function") } - let enabled = isServer ? false : options?.enabled ?? options?.enabled !== null + const suspenseEnabled = Boolean(globalThis.__BLITZ_SUSPENSE_ENABLED) + let enabled = isServer && suspenseEnabled ? false : options?.enabled ?? options?.enabled !== null let routerIsReady = false const router = useRouter() if (router) { - routerIsReady = router?.isReady || isServer + routerIsReady = router?.isReady || (isServer && suspenseEnabled) } else { routerIsReady = true } @@ -351,93 +292,14 @@ export function useInfiniteQuery< enabled, }) - const infiniteQueryData = data as InfiniteData - - const rest = { - ...queryRest, - ...getQueryCacheFunctions, TResult, T>(queryFn, getQueryParams), - pageParams: infiniteQueryData?.pageParams, - } - - return [infiniteQueryData?.pages as any, rest] -} - -// ------------------------- -// useInfiniteQuery -// ------------------------- -export interface RestInfiniteResult - extends Omit, "data">, - QueryCacheFunctions { - pageParams: any -} - -interface InfiniteQueryConfig - extends UseInfiniteQueryOptions { - // getPreviousPageParam?: (lastPage: TResult, allPages: TResult[]) => TGetPageParamResult - // getNextPageParam?: (lastPage: TResult, allPages: TResult[]) => TGetPageParamResult -} - -export function useSuspenseInfiniteQuery< - T extends AsyncFunc, - TResult = PromiseReturnType, - TError = DefaultError, - TSelectedData = TResult, ->( - queryFn: T, - getQueryParams: (pageParam: any) => FirstParam, - options: Omit, "queryKey"> & - QueryNonLazyOptions, -): [TSelectedData[], RestInfiniteResult] -export function useSuspenseInfiniteQuery< - T extends AsyncFunc, - TResult = PromiseReturnType, - TError = DefaultError, - TSelectedData = TResult, ->( - queryFn: T, - getQueryParams: (pageParam: any) => FirstParam, - options: Omit, "queryKey"> & - QueryLazyOptions, -): [TSelectedData[] | undefined, RestInfiniteResult] -export function useSuspenseInfiniteQuery< - T extends AsyncFunc, - TResult = PromiseReturnType, - TError = DefaultError, - TSelectedData = TResult, ->( - queryFn: T, - getQueryParams: (pageParam: any) => FirstParam, - options: Omit, "queryKey">, -) { - if (typeof queryFn === "undefined") { - throw new Error("useInfiniteQuery is missing the first argument - it must be a query function") - } - - let routerIsReady = false - const router = useRouter() - if (router) { - routerIsReady = router?.isReady || isServer - } else { - routerIsReady = true - } - const enhancedResolverRpcClient = sanitizeQuery(queryFn) - const queryKey = getInfiniteQueryKey(queryFn, getQueryParams) - - const {data, ...queryRest} = useSuspenseInfiniteReactQuery({ - // we need an extra cache key for infinite loading so that the cache for - // for this query is stored separately since the hook result is an array of results. - // Without this cache for usePaginatedQuery and this will conflict and break. - queryKey: routerIsReady ? queryKey : ["_routerNotReady_"], - queryFn: routerIsReady - ? ({pageParam, signal}) => - enhancedResolverRpcClient(getQueryParams(pageParam), {fromQueryHook: true}, signal) - : (emptyQueryFn as any), - ...options, - }) - - const infiniteQueryData = data as InfiniteData - - if (queryRest.fetchStatus === "idle" && isServer && !infiniteQueryData) { + if ( + queryRest.fetchStatus === "idle" && + isServer && + suspenseEnabled !== false && + !data && + (!options || !("suspense" in options) || options.suspense) && + (!options || !("enabled" in options) || options.enabled) + ) { const e = new NextError() e.name = "Rendering Suspense fallback..." e.digest = "DYNAMIC_SERVER_USAGE" @@ -450,10 +312,10 @@ export function useSuspenseInfiniteQuery< const rest = { ...queryRest, ...getQueryCacheFunctions, TResult, T>(queryFn, getQueryParams), - pageParams: infiniteQueryData?.pageParams, + pageParams: data?.pageParams, } - return [infiniteQueryData?.pages as unknown, rest] + return [data?.pages as any, rest] } // ------------------------------------------------------------------- @@ -490,7 +352,7 @@ export declare type MutationFunction = ( export function useMutation< TData = unknown, - TError = DefaultError, + TError = unknown, TVariables = void, TContext = unknown, >( @@ -500,11 +362,11 @@ export function useMutation< const enhancedResolverRpcClient = sanitizeMutation(mutationResolver) const {mutate, mutateAsync, ...rest} = useReactQueryMutation( + (variables) => enhancedResolverRpcClient(variables, {fromQueryHook: true}), { - mutationFn: (variables) => enhancedResolverRpcClient(variables, {fromQueryHook: true}), throwOnError: true, ...config, - }, + } as any, ) return [mutateAsync, rest] as MutationResultPair diff --git a/packages/blitz-rpc/src/query/utils.ts b/packages/blitz-rpc/src/query/utils.ts index fa12cc1394..7ce9b6b341 100644 --- a/packages/blitz-rpc/src/query/utils.ts +++ b/packages/blitz-rpc/src/query/utils.ts @@ -31,10 +31,16 @@ type MutateOptions = { } export const initializeQueryClient = () => { + let suspenseEnabled = true + if (!process.env.CLI_COMMAND_CONSOLE && !process.env.CLI_COMMAND_DB) { + suspenseEnabled = Boolean(globalThis.__BLITZ_SUSPENSE_ENABLED) + } + return new QueryClient({ defaultOptions: { queries: { ...(isServer && {cacheTime: 0}), + suspense: suspenseEnabled, retry: (failureCount, error: any) => { if (process.env.NODE_ENV !== "production") return false @@ -49,7 +55,7 @@ export const initializeQueryClient = () => { } // Query client is initialised in `BlitzRpcPlugin`, and can only be used with BlitzRpcPlugin right now -export const getQueryClient = () => globalThis.queryClient as QueryClient +export const getQueryClient = () => globalThis.queryClient function isRpcClient(f: any): f is RpcClient { return !!f._isRpcClient @@ -165,9 +171,7 @@ interface InvalidateQuery { export const invalidateQuery: InvalidateQuery = (resolver = undefined, ...params: []) => { const fullQueryKey = typeof resolver === "undefined" ? undefined : getQueryKey(resolver, ...params) - return getQueryClient().invalidateQueries({ - queryKey: fullQueryKey, - }) + return getQueryClient().invalidateQueries(fullQueryKey) } export function setQueryData( diff --git a/packages/blitz-rpc/test/unit/react-query-utils.unit.test.ts b/packages/blitz-rpc/test/unit/react-query-utils.unit.test.ts index f7d28864f2..d09fb217b7 100644 --- a/packages/blitz-rpc/test/unit/react-query-utils.unit.test.ts +++ b/packages/blitz-rpc/test/unit/react-query-utils.unit.test.ts @@ -59,7 +59,7 @@ describe("invalidateQuery", () => { expect(spyRefetchQueries).toBeCalledTimes(1) const calledWith = spyRefetchQueries.mock.calls[0]![0] as any // json of the queryKey is "a" - expect(calledWith.queryKey[1].json).toEqual("a") + expect(calledWith[1].json).toEqual("a") }) }) @@ -90,7 +90,7 @@ describe("setQueryData", () => { expect(spySetQueryData).toBeCalledTimes(1) const invalidateCalledWith = spyRefetchQueries.mock.calls[0]![0] as any - expect(invalidateCalledWith.queryKey[1].json).toEqual("params") + expect(invalidateCalledWith[1].json).toEqual("params") const calledWith = spySetQueryData.mock.calls[0] as Array expect(calledWith[0][1].json).toEqual("params") diff --git a/patches/next-auth@4.24.7.patch b/patches/next-auth@4.24.7.patch new file mode 100644 index 0000000000..092a042cd6 --- /dev/null +++ b/patches/next-auth@4.24.7.patch @@ -0,0 +1,23 @@ +diff --git a/package.json b/package.json +index c89e03c41a03de738cfb0ad090a63c2e99dadc7b..a5f38083c24732651c427c2b2d17cbcb23495473 100644 +--- a/package.json ++++ b/package.json +@@ -57,6 +57,18 @@ + "./providers/*": { + "types": "./providers/*.d.ts", + "default": "./providers/*.js" ++ }, ++ "./core/init": { ++ "types": "./core/init.d.ts", ++ "default": "./core/init.js" ++ }, ++ "./core/lib/oauth/authorization-url": { ++ "types": "./core/lib/oauth/authorization-url.d.ts", ++ "default": "./core/lib/oauth/authorization-url.js" ++ }, ++ "./core/lib/oauth/callback": { ++ "types": "./core/lib/oauth/callback.d.ts", ++ "default": "./core/lib/oauth/callback.js" + } + }, + "files": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4405629bdd..aaeb043724 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,6 +10,11 @@ overrides: "@types/react": npm:types-react@rc "@types/react-dom": npm:types-react-dom@rc +patchedDependencies: + next-auth@4.24.7: + hash: xxwv3g3ul7bnzqsfasefw3kyq4 + path: patches/next-auth@4.24.7.patch + importers: .: dependencies: @@ -80,8 +85,8 @@ importers: specifier: ^4.5.0 version: 4.6.1(prisma@4.6.1) "@tanstack/react-query": - specifier: 5.51.1 - version: 5.51.1(react@19.0.0) + specifier: 4.0.10 + version: 4.0.10(react-dom@19.0.0)(react@19.0.0) blitz: specifier: 2.2.1 version: link:../../packages/blitz @@ -160,7 +165,7 @@ importers: version: 15.0.1(@babel/core@7.20.2)(react-dom@19.0.0)(react@19.0.0) next-auth: specifier: 4.24.7 - version: 4.24.7(next@15.0.1)(react-dom@19.0.0)(react@19.0.0) + version: 4.24.7(patch_hash=xxwv3g3ul7bnzqsfasefw3kyq4)(next@15.0.1)(react-dom@19.0.0)(react@19.0.0) prisma: specifier: 6.1.0 version: 6.1.0 @@ -493,8 +498,8 @@ importers: specifier: 3.2.3 version: 3.2.3 playwright: - specifier: 1.49.1 - version: 1.49.1 + specifier: 1.28.0 + version: 1.28.0 ts-node: specifier: 10.9.1 version: 10.9.1(@types/node@18.7.13)(typescript@4.8.4) @@ -596,8 +601,8 @@ importers: specifier: 13.0.3 version: 13.0.3 playwright: - specifier: 1.49.1 - version: 1.49.1 + specifier: 1.28.0 + version: 1.28.0 prettier: specifier: ^2.7.1 version: 2.7.1 @@ -821,8 +826,8 @@ importers: specifier: 3.2.3 version: 3.2.3 playwright: - specifier: 1.49.1 - version: 1.49.1 + specifier: 1.28.0 + version: 1.28.0 ts-node: specifier: 10.9.1 version: 10.9.1(@types/node@18.7.13)(typescript@4.9.5) @@ -918,8 +923,8 @@ importers: specifier: 6.1.0 version: 6.1.0(prisma@6.1.0) "@tanstack/react-query": - specifier: 5.51.1 - version: 5.51.1(react@19.0.0) + specifier: 4.0.10 + version: 4.0.10(react-dom@19.0.0)(react@19.0.0) blitz: specifier: 2.2.1 version: link:../../packages/blitz @@ -1259,8 +1264,8 @@ importers: specifier: 5.0.0 version: 5.0.0 playwright-chromium: - specifier: 1.49.1 - version: 1.49.1 + specifier: 1.28.0 + version: 1.28.0 react: specifier: 19.0.0 version: 19.0.0 @@ -1607,7 +1612,7 @@ importers: version: 15.0.1(@babel/core@7.20.2)(react-dom@19.0.0)(react@19.0.0) next-auth: specifier: 4.24.7 - version: 4.24.7(next@15.0.1)(react-dom@19.0.0)(react@19.0.0) + version: 4.24.7(patch_hash=xxwv3g3ul7bnzqsfasefw3kyq4)(next@15.0.1)(react-dom@19.0.0)(react@19.0.0) react: specifier: 19.0.0 version: 19.0.0 @@ -1730,8 +1735,8 @@ importers: specifier: 1.3.7 version: 1.3.7 "@tanstack/react-query": - specifier: 5.51.1 - version: 5.51.1(react@19.0.0) + specifier: 4.24.4 + version: 4.24.4(react-dom@19.0.0)(react@19.0.0) b64-lite: specifier: 1.4.0 version: 1.4.0 @@ -1758,8 +1763,8 @@ importers: specifier: 2.2.1 version: link:../config "@tanstack/query-core": - specifier: 5.51.1 - version: 5.51.1 + specifier: 4.24.4 + version: 4.24.4 "@types/debug": specifier: 4.1.7 version: 4.1.7 @@ -6738,12 +6743,34 @@ packages: } dev: true - /@tanstack/query-core@5.51.1: + /@tanstack/query-core@4.24.4: resolution: { - integrity: sha512-fJBMQMpo8/KSsWW5ratJR5+IFr7YNJ3K2kfP9l5XObYHsgfVy1w3FJUWU4FT2fj7+JMaEg33zOcNDBo0LMwHnw==, + integrity: sha512-9dqjv9eeB6VHN7lD3cLo16ZAjfjCsdXetSAD5+VyKqLUvcKTL0CklGQRJu+bWzdrS69R6Ea4UZo8obHYZnG6aA==, } + /@tanstack/react-query@4.0.10(react-dom@19.0.0)(react@19.0.0): + resolution: + { + integrity: sha512-Wn5QhZUE5wvr6rGClV7KeQIUsdTmYR9mgmMZen7DSRWauHW2UTynFg3Kkf6pw+XlxxOLsyLWwz/Q6q1lSpM3TQ==, + } + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-native: "*" + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + dependencies: + "@tanstack/query-core": 4.24.4 + "@types/use-sync-external-store": 0.0.3 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + use-sync-external-store: 1.2.0(react@19.0.0) + dev: false + /@tanstack/react-query@4.13.0(react-dom@19.0.0)(react@19.0.0): resolution: { @@ -6765,16 +6792,25 @@ packages: use-sync-external-store: 1.2.0(react@19.0.0) dev: true - /@tanstack/react-query@5.51.1(react@19.0.0): + /@tanstack/react-query@4.24.4(react-dom@19.0.0)(react@19.0.0): resolution: { - integrity: sha512-s47HKFnQ4HOJAHoIiXcpna/roMMPZJPy6fJ6p4ZNVn8+/onlLBEDd1+xc8OnDuwgvecqkZD7Z2mnSRbcWefrKw==, + integrity: sha512-RpaS/3T/a3pHuZJbIAzAYRu+1nkp+/enr9hfRXDS/mojwx567UiMksoqW4wUFWlwIvWTXyhot2nbIipTKEg55Q==, } peerDependencies: - react: ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-native: "*" + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true dependencies: - "@tanstack/query-core": 5.51.1 + "@tanstack/query-core": 4.24.4 react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + use-sync-external-store: 1.2.0(react@19.0.0) dev: false /@testim/chrome-version@1.1.2: @@ -7732,6 +7768,13 @@ packages: integrity: sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==, } + /@types/use-sync-external-store@0.0.3: + resolution: + { + integrity: sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==, + } + dev: false + /@types/vinyl@2.0.6: resolution: { @@ -13696,17 +13739,6 @@ packages: integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==, } - /fsevents@2.3.2: - resolution: - { - integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==, - } - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - /fsevents@2.3.3: resolution: { @@ -17999,7 +18031,7 @@ packages: } dev: false - /next-auth@4.24.7(next@15.0.1)(react-dom@19.0.0)(react@19.0.0): + /next-auth@4.24.7(patch_hash=xxwv3g3ul7bnzqsfasefw3kyq4)(next@15.0.1)(react-dom@19.0.0)(react@19.0.0): resolution: { integrity: sha512-iChjE8ov/1K/z98gdKbn2Jw+2vLgJtVV39X+rCP5SGnVQuco7QOr19FRNGMIrD8d3LYhHWV9j9sKLzq1aDWWQQ==, @@ -18025,6 +18057,7 @@ packages: react: 19.0.0 react-dom: 19.0.0(react@19.0.0) uuid: 8.3.2 + patched: true /next-router-mock@0.9.1(next@15.0.1)(react@19.0.0): resolution: @@ -19276,38 +19309,37 @@ packages: pathe: 0.3.2 dev: true - /playwright-chromium@1.49.1: + /playwright-chromium@1.28.0: resolution: { - integrity: sha512-XAQDkZ1Eem1OONhfS8B2LM2mgHG/i5jIxooxjvqjbF/9GnLnRTJHdQamNjo1e4FZvt7J0BFD/15+qAcT0eKlfA==, + integrity: sha512-5IUBJShMJMaK6NmRj/7KWdvVqd7J8DqLH0wVdXBs/4MfZUAvByBB35y5v6B33NjlJg3SZGX5alR8TANrcKaJNA==, } - engines: {node: ">=18"} + engines: {node: ">=14"} hasBin: true requiresBuild: true dependencies: - playwright-core: 1.49.1 + playwright-core: 1.28.0 dev: true - /playwright-core@1.49.1: + /playwright-core@1.28.0: resolution: { - integrity: sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==, + integrity: sha512-nJLknd28kPBiCNTbqpu6Wmkrh63OEqJSFw9xOfL9qxfNwody7h6/L3O2dZoWQ6Oxcm0VOHjWmGiCUGkc0X3VZA==, } - engines: {node: ">=18"} + engines: {node: ">=14"} hasBin: true dev: true - /playwright@1.49.1: + /playwright@1.28.0: resolution: { - integrity: sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==, + integrity: sha512-kyOXGc5y1mgi+hgEcCIyE1P1+JumLrxS09nFHo5sdJNzrucxPRAGwM4A2X3u3SDOfdgJqx61yIoR6Av+5plJPg==, } - engines: {node: ">=18"} + engines: {node: ">=14"} hasBin: true + requiresBuild: true dependencies: - playwright-core: 1.49.1 - optionalDependencies: - fsevents: 2.3.2 + playwright-core: 1.28.0 dev: true /pluralize@8.0.0: @@ -22947,7 +22979,6 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: react: 19.0.0 - dev: true /use@3.1.1: resolution: