Compare commits
23 Commits
@blitzjs/g
...
@blitzjs/a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
107254ece9 | ||
|
|
816330b9d0 | ||
|
|
18decd1558 | ||
|
|
1610c73f99 | ||
|
|
0a257e9150 | ||
|
|
2661bcd98d | ||
|
|
11c9f00eb9 | ||
|
|
ce1a603b26 | ||
|
|
125370a1d0 | ||
|
|
39c8c0ab80 | ||
|
|
fbf5e51a78 | ||
|
|
9cda1be11b | ||
|
|
5b20ce6282 | ||
|
|
0fc2d71a18 | ||
|
|
3fa3a4ef30 | ||
|
|
565db3c5a8 | ||
|
|
ae04524b4c | ||
|
|
38d320fd28 | ||
|
|
8723d0053c | ||
|
|
ce23d4ed09 | ||
|
|
b6c9c4ae6d | ||
|
|
0b3286468b | ||
|
|
50f17d21ce |
@@ -4104,6 +4104,46 @@
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "fungilation",
|
||||
"name": "Gary Fung",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3803466?v=4",
|
||||
"profile": "https://garyfung.medium.com",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "rene-demonsters",
|
||||
"name": "René Vlugt",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/20322259?v=4",
|
||||
"profile": "https://github.com/rene-demonsters",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "kksandr7",
|
||||
"name": "Ksandr",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/132560756?v=4",
|
||||
"profile": "https://www.drupal.org/u/kksandr",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Daidalos117",
|
||||
"name": "Roman Rajchert",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/15905269?v=4",
|
||||
"profile": "https://github.com/Daidalos117",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
"access": "restricted",
|
||||
"baseBranch": "main",
|
||||
"updateInternalDependencies": "patch",
|
||||
"ignore": ["web", "test-*", "toolkit-*", "@blitzjs/recipe-*"]
|
||||
"ignore": ["web", "test-*", "toolkit-*", "next-blitz-auth"]
|
||||
}
|
||||
|
||||
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@@ -148,7 +148,7 @@ jobs:
|
||||
- name: Install playwright
|
||||
if: matrix.folder != 'next-13-app-dir' || matrix.os != 'windows-latest'
|
||||
run: |
|
||||
pnpx playwright@1.28.0 install --with-deps
|
||||
pnpx playwright@1.49.1 install --with-deps
|
||||
shell: bash
|
||||
|
||||
- name: Build
|
||||
|
||||
4
.github/workflows/pr-release.yml
vendored
4
.github/workflows/pr-release.yml
vendored
@@ -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.9.0
|
||||
version: 8.6.6
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
- name: Pre-publish
|
||||
uses: pnpm/action-setup@646cdf48217256a3d0b80361c5a50727664284f2
|
||||
with:
|
||||
version: 8.9.0
|
||||
version: 8.6.6
|
||||
- run: pnpm install
|
||||
env:
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<img alt="" src="https://img.shields.io/badge/Join%20our%20community-6700EB.svg?style=for-the-badge&labelColor=000000&logoWidth=20&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAQ9SURBVHgB7d3dVdtAEIbhcSpICUoH0IEogQqSVBBSAU4FSSpIOoAORAfQgSghHXzZ1U/YcMD4R9rZmf2ec3y448LyiNf27iLiGIAmPLrweC9Un3DhrzG6EarLNP09nlwJ1SOZ/lQr5N80/S/p2QMVCBf5N17XCfm1Y/rBHqjAG9PPHvBsz+mf9WAP+HLA9M/YA14cOP2payH7jpj+VCtk1wnTP+vj7xCy6cTpn7EHLMLp059iD1iD8eveJbVCNsSLheX1YA/YgOWnf8YeKB3Wmf7Ud6Fy4f/FHmtpxbl3YlC4MJ/Cj0bWdwPnPbARg+L0S54XQHS32WwuxClzd4CM0z9rPfeAuTtA5ulPXYQ7wZ04Y+oOoDD9KZc9YOoOoDj9s4dwFzgXR6w1wIPoOvPWA9buAHEJ173o3gWiy3AnuBUHLEbgmYwvAk1/wuM8vAgexThzbwPDkx7/DHwVXfFOxP2GmsKd4Ab6zPeAyU8CI7AHFmH2BRCBPXAyk18GzUrqAXCTiR4ssyj0VFw/oCU8+e+RZ33AWz6KMaYbIIWxB+JSLs1bsbkeMN0AqakHvoku9oA2sAfqBvbAQdw0QArsgb25aYBUQT3QgT2gB+yBuqGcHij2UCqXDZACe2Anlw2QYg/QAOyBuoE98CL3DZDCuK4/rh/Q7oGL6U+TOvcNkJoijN8X1C48+T+g75eQDrAH/qmqAVJgDwyqaoAUe4AGYA/UDZX3QLUNkEIZPRCd5+6BahsgVUgPROwBTSijB7jpVAvGHriHvmw9wAZ4BpX1ABvgmakHtPcbRuwBTWAPULgAV9D/jKDY9YRvwvgEaurD44uQHvAol7qBW7WKluVtIHiUS7GyvA0s6CiXDnxrpQfsgbqBS7GKk/2jYHCrVlGyfxTMrVo0ALdq1Q3sgSKofh0M9oA61a+D2QM0AHugbmAPqClmSRjK2apVVQ8UsySsoK1aHdgDesCtWnUDeyCrIpeFg1u3sylyWTi3btMA7IG6gT2wuuK3hoE9sKrit4YVslWLPaAN7IG6ocKt2zmY2h4O9sDiTG0PZw/QANy6XTewBxZj9ogYVHy025LMHhEz9cBn0We6B0yfERReBLfhx0/R1YQHPx/QBPbA0VwcEwf2wNFcHBPHHjiem3MC2QPHcXdSaJjA+KfgTPQ8hhfjBzHC40mhlzJ+Xq9lK4a4PCs43AVaGTed5mZq+iOXZwWHi3AnOj2wFWNcnxYe7gTxLtBKHuamP/J+Wnh8a5irB7ZC5Yk9gPX1QuXC+usHWqGyhYvUYR0a7zboUOFCNVhnk0krZAOW7wFOvzXhom2xnEbIHizTA1wEYhWW6YFGyC6c1gOcfg9wfA80Qj7g8B7g9HuCww+haIR8wf49wOn3Cvv9k8tGyC/s7gFOv3fY3QONkH+v9MBWqB7PeqDn9FcIT//kcitUn6kHOu/T/xfWzlQy3dEHhwAAAABJRU5ErkJggg==">
|
||||
</a>
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
<a aria-label="All Contributors" href="#contributors-"><img alt="" src="https://img.shields.io/badge/all_contributors-432-17BB8A.svg?style=for-the-badge&labelColor=000000"></a>
|
||||
<a aria-label="All Contributors" href="#contributors-"><img alt="" src="https://img.shields.io/badge/all_contributors-436-17BB8A.svg?style=for-the-badge&labelColor=000000"></a>
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
<a aria-label="License" href="https://github.com/blitz-js/blitz/blob/main/LICENSE">
|
||||
<img alt="" src="https://img.shields.io/npm/l/blitz.svg?style=for-the-badge&labelColor=000000&color=blue">
|
||||
@@ -761,6 +761,12 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
<td align="center"><a href="https://github.com/bezalel6"><img src="https://avatars.githubusercontent.com/u/51681171?v=4?s=100" width="100px;" alt=""/><br /><sub><b>bezalel6</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=bezalel6" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=bezalel6" title="Code">💻</a></td>
|
||||
<td align="center"><a href="cherniavskii.com"><img src="https://avatars.githubusercontent.com/u/13808724?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andrew Cherniavskii</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cherniavskii" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://danielidoko-r3zt.vercel.app/"><img src="https://avatars.githubusercontent.com/u/95912955?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Idoko</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=doe-base" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=doe-base" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=doe-base" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://garyfung.medium.com"><img src="https://avatars.githubusercontent.com/u/3803466?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gary Fung</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=fungilation" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=fungilation" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/rene-demonsters"><img src="https://avatars.githubusercontent.com/u/20322259?v=4?s=100" width="100px;" alt=""/><br /><sub><b>René Vlugt</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rene-demonsters" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=rene-demonsters" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.drupal.org/u/kksandr"><img src="https://avatars.githubusercontent.com/u/132560756?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ksandr</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kksandr7" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=kksandr7" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Daidalos117"><img src="https://avatars.githubusercontent.com/u/15905269?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Roman Rajchert</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Daidalos117" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=Daidalos117" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
@@ -1,5 +1,50 @@
|
||||
# next-blitz-auth
|
||||
|
||||
## 0.1.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.2.1
|
||||
- @blitzjs/auth@2.2.1
|
||||
- @blitzjs/next@2.2.1
|
||||
- @blitzjs/rpc@2.2.1
|
||||
- @blitzjs/config@2.2.1
|
||||
|
||||
## 0.1.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [565db3c5a]
|
||||
- Updated dependencies [3fa3a4ef3]
|
||||
- blitz@2.2.0
|
||||
- @blitzjs/auth@2.2.0
|
||||
- @blitzjs/next@2.2.0
|
||||
- @blitzjs/rpc@2.2.0
|
||||
- @blitzjs/config@2.2.0
|
||||
|
||||
## 0.1.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ce23d4ed0]
|
||||
- @blitzjs/next@2.1.4
|
||||
- blitz@2.1.4
|
||||
- @blitzjs/auth@2.1.4
|
||||
- @blitzjs/rpc@2.1.4
|
||||
- @blitzjs/config@2.1.4
|
||||
|
||||
## 0.1.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [0b3286468]
|
||||
- Updated dependencies [50f17d21c]
|
||||
- @blitzjs/auth@2.1.3
|
||||
- @blitzjs/next@2.1.3
|
||||
- @blitzjs/rpc@2.1.3
|
||||
- blitz@2.1.3
|
||||
- @blitzjs/config@2.1.3
|
||||
|
||||
## 0.1.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "next-blitz-auth",
|
||||
"version": "0.1.14",
|
||||
"version": "0.1.18",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"blitz:dev": "next dev",
|
||||
@@ -12,28 +12,28 @@
|
||||
"schema": "prisma/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.1.2",
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@blitzjs/next": "2.1.2",
|
||||
"@blitzjs/rpc": "2.1.2",
|
||||
"@blitzjs/auth": "3.0.1",
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@blitzjs/next": "3.0.1",
|
||||
"@blitzjs/rpc": "3.0.1",
|
||||
"@hookform/error-message": "2.0.0",
|
||||
"@hookform/resolvers": "2.9.10",
|
||||
"@prisma/client": "^4.5.0",
|
||||
"@tanstack/react-query": "4.0.10",
|
||||
"blitz": "2.1.2",
|
||||
"@tanstack/react-query": "5.51.1",
|
||||
"blitz": "3.0.1",
|
||||
"flatted": "3.2.7",
|
||||
"next": "14.3.0-canary.28",
|
||||
"next": "15.0.1",
|
||||
"prisma": "^4.5.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"react-hook-form": "7.39.1",
|
||||
"superjson": "1.11.0",
|
||||
"zod": "3.20.2"
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "18.11.7",
|
||||
"@types/react": "18.0.23",
|
||||
"@types/react-dom": "18.0.7",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0",
|
||||
"eslint": "8.26.0",
|
||||
"eslint-config-next": "13.0.0",
|
||||
"typescript": "4.8.4"
|
||||
|
||||
4
apps/next13/src/app/loading.tsx
Normal file
4
apps/next13/src/app/loading.tsx
Normal file
@@ -0,0 +1,4 @@
|
||||
export default function Loading() {
|
||||
// You can add any UI inside Loading, including a Skeleton.
|
||||
return "Loading..."
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import {useQuery, useMutation} from "@blitzjs/rpc"
|
||||
import {useQuery, useMutation, useSuspenseQuery} 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] = useQuery(getCurrentUser, null)
|
||||
const [user] = useSuspenseQuery(getCurrentUser, null)
|
||||
const [isPending, startTransition] = useTransition()
|
||||
const [logoutMutation] = useMutation(logout)
|
||||
console.log(user)
|
||||
|
||||
@@ -4,7 +4,7 @@ import {zodResolver} from "@hookform/resolvers/zod"
|
||||
import {z} from "zod"
|
||||
|
||||
export interface FormProps<S extends z.ZodType<any, any>>
|
||||
extends Omit<PropsWithoutRef<JSX.IntrinsicElements["form"]>, "onSubmit"> {
|
||||
extends Omit<PropsWithoutRef<React.JSX.IntrinsicElements["form"]>, "onSubmit"> {
|
||||
/** All your form fields */
|
||||
children?: ReactNode
|
||||
/** Text to display in the submit button */
|
||||
|
||||
@@ -2,14 +2,15 @@ import {forwardRef, PropsWithoutRef, ComponentPropsWithoutRef} from "react"
|
||||
import {useFormContext} from "react-hook-form"
|
||||
import {ErrorMessage} from "@hookform/error-message"
|
||||
|
||||
export interface LabeledTextFieldProps extends PropsWithoutRef<JSX.IntrinsicElements["input"]> {
|
||||
export interface LabeledTextFieldProps
|
||||
extends PropsWithoutRef<React.JSX.IntrinsicElements["input"]> {
|
||||
/** Field name. */
|
||||
name: string
|
||||
/** Field label. */
|
||||
label: string
|
||||
/** Field type. Doesn't include radio buttons and checkboxes */
|
||||
type?: "text" | "password" | "email" | "number"
|
||||
outerProps?: PropsWithoutRef<JSX.IntrinsicElements["div"]>
|
||||
outerProps?: PropsWithoutRef<React.JSX.IntrinsicElements["div"]>
|
||||
labelProps?: ComponentPropsWithoutRef<"label">
|
||||
}
|
||||
|
||||
|
||||
2
apps/toolkit-app-passportjs/next-env.d.ts
vendored
2
apps/toolkit-app-passportjs/next-env.d.ts
vendored
@@ -2,4 +2,4 @@
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
|
||||
|
||||
@@ -23,31 +23,30 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.1.2",
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@blitzjs/next": "2.1.2",
|
||||
"@blitzjs/rpc": "2.1.2",
|
||||
"@blitzjs/auth": "3.0.1",
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@blitzjs/next": "3.0.1",
|
||||
"@blitzjs/rpc": "3.0.1",
|
||||
"@hookform/error-message": "2.0.0",
|
||||
"@hookform/resolvers": "2.9.10",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.1.2",
|
||||
"next": "14.3.0-canary.28",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "3.0.1",
|
||||
"next": "15.0.1",
|
||||
"openid-client": "5.2.1",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"react-hook-form": "7.39.1",
|
||||
"ts-node": "10.9.1",
|
||||
"zod": "3.20.2"
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@testing-library/react-hooks": "8.0.1",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@types/jest": "29.2.2",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/preview-email": "2.0.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.42.1",
|
||||
"eslint": "8.27.0",
|
||||
"eslint-config-next": "12.3.1",
|
||||
|
||||
@@ -4,7 +4,7 @@ import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { z } from "zod"
|
||||
|
||||
export interface FormProps<S extends z.ZodType<any, any>>
|
||||
extends Omit<PropsWithoutRef<JSX.IntrinsicElements["form"]>, "onSubmit"> {
|
||||
extends Omit<PropsWithoutRef<React.JSX.IntrinsicElements["form"]>, "onSubmit"> {
|
||||
/** All your form fields */
|
||||
children?: ReactNode
|
||||
/** Text to display in the submit button */
|
||||
|
||||
@@ -2,14 +2,15 @@ import { forwardRef, PropsWithoutRef, ComponentPropsWithoutRef } from "react"
|
||||
import { useFormContext } from "react-hook-form"
|
||||
import { ErrorMessage } from "@hookform/error-message"
|
||||
|
||||
export interface LabeledTextFieldProps extends PropsWithoutRef<JSX.IntrinsicElements["input"]> {
|
||||
export interface LabeledTextFieldProps
|
||||
extends PropsWithoutRef<React.JSX.IntrinsicElements["input"]> {
|
||||
/** Field name. */
|
||||
name: string
|
||||
/** Field label. */
|
||||
label: string
|
||||
/** Field type. Doesn't include radio buttons and checkboxes */
|
||||
type?: "text" | "password" | "email" | "number"
|
||||
outerProps?: PropsWithoutRef<JSX.IntrinsicElements["div"]>
|
||||
outerProps?: PropsWithoutRef<React.JSX.IntrinsicElements["div"]>
|
||||
labelProps?: ComponentPropsWithoutRef<"label">
|
||||
}
|
||||
|
||||
|
||||
2
apps/toolkit-app/next-env.d.ts
vendored
2
apps/toolkit-app/next-env.d.ts
vendored
@@ -2,4 +2,4 @@
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
const { withNextAuthAdapter } = require("@blitzjs/auth/next-auth")
|
||||
const { withBlitz } = require("@blitzjs/next")
|
||||
|
||||
/**
|
||||
@@ -11,4 +10,4 @@ const config = {
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = withBlitz(withNextAuthAdapter(config))
|
||||
module.exports = withBlitz(config)
|
||||
|
||||
@@ -24,31 +24,30 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.1.2",
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@blitzjs/next": "2.1.2",
|
||||
"@blitzjs/rpc": "2.1.2",
|
||||
"@blitzjs/auth": "3.0.1",
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@blitzjs/next": "3.0.1",
|
||||
"@blitzjs/rpc": "3.0.1",
|
||||
"@hookform/error-message": "2.0.0",
|
||||
"@hookform/resolvers": "2.9.10",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.1.2",
|
||||
"next": "14.3.0-canary.28",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "3.0.1",
|
||||
"next": "15.0.1",
|
||||
"next-auth": "4.24.7",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"react-hook-form": "7.39.1",
|
||||
"ts-node": "10.9.1",
|
||||
"zod": "3.20.2"
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@testing-library/jest-dom": "5.16.5",
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@testing-library/react-hooks": "8.0.1",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/preview-email": "2.0.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.42.1",
|
||||
"@vitejs/plugin-react": "2.2.0",
|
||||
"eslint": "8.27.0",
|
||||
|
||||
@@ -4,7 +4,7 @@ import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { z } from "zod"
|
||||
|
||||
export interface FormProps<S extends z.ZodType<any, any>>
|
||||
extends Omit<PropsWithoutRef<JSX.IntrinsicElements["form"]>, "onSubmit"> {
|
||||
extends Omit<PropsWithoutRef<React.JSX.IntrinsicElements["form"]>, "onSubmit"> {
|
||||
/** All your form fields */
|
||||
children?: ReactNode
|
||||
/** Text to display in the submit button */
|
||||
|
||||
@@ -2,14 +2,15 @@ import { ComponentPropsWithoutRef, forwardRef, PropsWithoutRef } from "react"
|
||||
import { useFormContext } from "react-hook-form"
|
||||
import { ErrorMessage } from "@hookform/error-message"
|
||||
|
||||
export interface LabeledSelectFieldProps extends PropsWithoutRef<JSX.IntrinsicElements["select"]> {
|
||||
export interface LabeledSelectFieldProps
|
||||
extends PropsWithoutRef<React.JSX.IntrinsicElements["select"]> {
|
||||
/** Field name. */
|
||||
name: string
|
||||
/** Field label. */
|
||||
label: string
|
||||
/** Field type. Doesn't include radio buttons and checkboxes */
|
||||
options: any[]
|
||||
outerProps?: PropsWithoutRef<JSX.IntrinsicElements["div"]>
|
||||
outerProps?: PropsWithoutRef<React.JSX.IntrinsicElements["div"]>
|
||||
labelProps?: ComponentPropsWithoutRef<"label">
|
||||
}
|
||||
|
||||
|
||||
@@ -2,14 +2,15 @@ import { forwardRef, PropsWithoutRef, ComponentPropsWithoutRef } from "react"
|
||||
import { useFormContext } from "react-hook-form"
|
||||
import { ErrorMessage } from "@hookform/error-message"
|
||||
|
||||
export interface LabeledTextFieldProps extends PropsWithoutRef<JSX.IntrinsicElements["input"]> {
|
||||
export interface LabeledTextFieldProps
|
||||
extends PropsWithoutRef<React.JSX.IntrinsicElements["input"]> {
|
||||
/** Field name. */
|
||||
name: string
|
||||
/** Field label. */
|
||||
label: string
|
||||
/** Field type. Doesn't include radio buttons and checkboxes */
|
||||
type?: "text" | "password" | "email" | "number"
|
||||
outerProps?: PropsWithoutRef<JSX.IntrinsicElements["div"]>
|
||||
outerProps?: PropsWithoutRef<React.JSX.IntrinsicElements["div"]>
|
||||
labelProps?: ComponentPropsWithoutRef<"label">
|
||||
}
|
||||
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
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: "/" }
|
||||
},
|
||||
})
|
||||
)
|
||||
@@ -44,11 +44,6 @@ const UserInfo = () => {
|
||||
<Link href={"/auth/login"} className={styles.loginButton}>
|
||||
<strong>Login</strong>
|
||||
</Link>
|
||||
<Link href="/api/auth/github/login" passHref legacyBehavior>
|
||||
<a className="button small">
|
||||
<strong>Sign in with GitHub</strong>
|
||||
</a>
|
||||
</Link>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
2
apps/web/next-env.d.ts
vendored
2
apps/web/next-env.d.ts
vendored
@@ -2,4 +2,4 @@
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
|
||||
|
||||
@@ -16,27 +16,27 @@
|
||||
"schema": "./db/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.1.2",
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@blitzjs/next": "2.1.2",
|
||||
"@blitzjs/rpc": "2.1.2",
|
||||
"@prisma/client": "4.6.1",
|
||||
"@blitzjs/auth": "3.0.1",
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@blitzjs/next": "3.0.1",
|
||||
"@blitzjs/rpc": "3.0.1",
|
||||
"@prisma/client": "6.1.0",
|
||||
"@types/jest": "29.2.2",
|
||||
"@types/passport-twitter": "1.0.37",
|
||||
"blitz": "2.1.2",
|
||||
"blitz": "3.0.1",
|
||||
"jest": "29.3.0",
|
||||
"jest-environment-jsdom": "29.3.0",
|
||||
"next": "14.3.0-canary.28",
|
||||
"next": "15.0.1",
|
||||
"passport-mock-strategy": "2.0.0",
|
||||
"passport-twitter": "1.0.4",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"ts-node": "10.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"eslint": "8.27.0",
|
||||
"typescript": "^4.8.4"
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
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})
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
}),
|
||||
)
|
||||
90
apps/web/src/pages/page-with-inf-mutate.tsx
Normal file
90
apps/web/src/pages/page-with-inf-mutate.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import {useSuspenseInfiniteQuery} from "@blitzjs/rpc"
|
||||
import getInfiniteUsers from "src/queries/getInfiniteUsers"
|
||||
import {useActionState} from "react"
|
||||
|
||||
function PageWithInfiniteQueryMutate(props) {
|
||||
const [usersPages, extraInfo] = useSuspenseInfiniteQuery(
|
||||
getInfiniteUsers,
|
||||
(page = {take: 3, skip: 0}) => page,
|
||||
{
|
||||
getNextPageParam: (lastPage) => lastPage.nextPage,
|
||||
initialPageParam: {take: 3, skip: 0},
|
||||
},
|
||||
)
|
||||
const {isFetchingNextPage, fetchNextPage, hasNextPage, setQueryData} = extraInfo
|
||||
|
||||
const onOnContactSave = async (previousState, formData: FormData) => {
|
||||
const name = formData.get("name") as string | null
|
||||
|
||||
await setQueryData(
|
||||
(oldData) => {
|
||||
if (!oldData) {
|
||||
return {
|
||||
pages: [],
|
||||
pageParams: [],
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...oldData,
|
||||
pages: oldData.pages.map((page, index) => {
|
||||
if (index === 0) {
|
||||
return {
|
||||
...page,
|
||||
users: [
|
||||
{
|
||||
id: Math.random(),
|
||||
name,
|
||||
role: "user",
|
||||
email: `${name}@yopmail.com`,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
hashedPassword: "alsdklaskdoaskdokdo",
|
||||
},
|
||||
...page.users,
|
||||
],
|
||||
}
|
||||
}
|
||||
return page
|
||||
}),
|
||||
}
|
||||
},
|
||||
{refetch: false},
|
||||
)
|
||||
}
|
||||
|
||||
const [, formAction] = useActionState(onOnContactSave, {name: ""})
|
||||
|
||||
return (
|
||||
<div>
|
||||
<form action={formAction}>
|
||||
<input type="text" name="name" placeholder="User name" />
|
||||
<button type="submit">Add user</button>
|
||||
</form>
|
||||
{usersPages.map((usersPage) => (
|
||||
<>
|
||||
{usersPage?.users.map((u) => (
|
||||
<div key={u.name}>
|
||||
<p>name: {u.name}</p>
|
||||
<p>role: {u.role}</p>
|
||||
<p>email: {u.email}</p>
|
||||
<hr />
|
||||
</div>
|
||||
))}
|
||||
|
||||
{usersPage.hasMore && (
|
||||
<button onClick={() => fetchNextPage()} disabled={!hasNextPage || !!isFetchingNextPage}>
|
||||
{isFetchingNextPage
|
||||
? "Loading more..."
|
||||
: hasNextPage
|
||||
? "Load More"
|
||||
: "Nothing more to load"}
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PageWithInfiniteQueryMutate
|
||||
@@ -1,4 +1,4 @@
|
||||
import {useInfiniteQuery} from "@blitzjs/rpc"
|
||||
import {useSuspenseInfiniteQuery} from "@blitzjs/rpc"
|
||||
import {gSSP} from "src/blitz-server"
|
||||
import getInfiniteUsers from "src/queries/getInfiniteUsers"
|
||||
|
||||
@@ -10,9 +10,14 @@ export const getServerSideProps = gSSP(async ({ctx}) => {
|
||||
})
|
||||
|
||||
function PageWithPrefetchInfiniteQuery(props) {
|
||||
const [usersPages] = useInfiniteQuery(getInfiniteUsers, (page = {take: 3, skip: 0}) => page, {
|
||||
getNextPageParam: (lastPage) => lastPage.nextPage,
|
||||
})
|
||||
const [usersPages] = useSuspenseInfiniteQuery(
|
||||
getInfiniteUsers,
|
||||
(page = {take: 3, skip: 0}) => page,
|
||||
{
|
||||
getNextPageParam: (lastPage) => lastPage.nextPage,
|
||||
initialPageParam: {take: 3, skip: 0},
|
||||
},
|
||||
)
|
||||
return (
|
||||
<div>
|
||||
{usersPages.map((usersPage) =>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {useQuery} from "@blitzjs/rpc"
|
||||
import {useSuspenseQuery} 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] = useQuery(getUsers, {})
|
||||
const [users] = useSuspenseQuery(getUsers, {})
|
||||
return (
|
||||
<div>
|
||||
{users.map((u) => (
|
||||
|
||||
@@ -7,7 +7,7 @@ function UsersPage() {
|
||||
<div>
|
||||
Users:
|
||||
<ul>
|
||||
{users.map((user) => (
|
||||
{users?.map((user) => (
|
||||
<li key={user.id}>
|
||||
{user.name} - {user.email}
|
||||
</li>
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
|
||||
|
||||
@@ -17,31 +17,30 @@
|
||||
"prisma:studio": "prisma studio"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.1.2",
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@blitzjs/next": "2.1.2",
|
||||
"@blitzjs/rpc": "2.1.2",
|
||||
"@blitzjs/auth": "3.0.1",
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@blitzjs/next": "3.0.1",
|
||||
"@blitzjs/rpc": "3.0.1",
|
||||
"@hookform/error-message": "2.0.0",
|
||||
"@hookform/resolvers": "2.9.10",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.1.2",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "3.0.1",
|
||||
"delay": "5.0.0",
|
||||
"next": "14.3.0-canary.28",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"react-hook-form": "7.39.1",
|
||||
"ts-node": "10.9.1",
|
||||
"zod": "3.20.2"
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@testing-library/jest-dom": "5.16.5",
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@testing-library/react-hooks": "8.0.1",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/preview-email": "2.0.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.42.1",
|
||||
"@vitejs/plugin-react": "2.2.0",
|
||||
"eslint": "8.27.0",
|
||||
@@ -50,7 +49,7 @@
|
||||
"husky": "8.0.2",
|
||||
"jsdom": "20.0.3",
|
||||
"lint-staged": "13.0.3",
|
||||
"playwright": "1.28.0",
|
||||
"playwright": "1.49.1",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier-plugin-prisma": "4.4.0",
|
||||
"pretty-quick": "3.1.3",
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import {useMutation, useQuery} from "@blitzjs/rpc"
|
||||
import {QueryClient, useMutation, useQuery} from "@blitzjs/rpc"
|
||||
import logout from "../mutations/logout"
|
||||
import getAuthenticatedBasic from "../queries/getAuthenticatedBasic"
|
||||
import {Suspense} from "react"
|
||||
|
||||
function Content() {
|
||||
const [result] = useQuery(getAuthenticatedBasic, undefined)
|
||||
const [result, {isLoading, isError, error}] = useQuery(getAuthenticatedBasic, undefined)
|
||||
const [logoutMutation] = useMutation(logout)
|
||||
if (isError) throw error
|
||||
if (isLoading || !result) return <div>Loading...</div>
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<div id="content">{result}</div>
|
||||
<button
|
||||
id="logout"
|
||||
@@ -17,16 +18,14 @@ function Content() {
|
||||
>
|
||||
logout
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function AuthenticatedQuery() {
|
||||
return (
|
||||
<div id="page">
|
||||
<Suspense fallback={"Loading..."}>
|
||||
<Content />
|
||||
</Suspense>
|
||||
<Content />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {useMutation, useQuery} from "@blitzjs/rpc"
|
||||
import {useMutation, useSuspenseQuery} 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] = useQuery(getAuthenticatedBasic, undefined)
|
||||
const [result] = useSuspenseQuery(getAuthenticatedBasic, undefined)
|
||||
const [logoutMutation] = useMutation(logout)
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {useRouter} from "next/router"
|
||||
import {useMutation, useQuery} from "@blitzjs/rpc"
|
||||
import {useMutation, useSuspenseQuery} 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] = useQuery(getCurrentUser, null)
|
||||
const [userId] = useSuspenseQuery(getCurrentUser, null)
|
||||
const [loginMutation] = useMutation(login)
|
||||
const [logoutMutation] = useMutation(logout)
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {useQuery} from "@blitzjs/rpc"
|
||||
import {useSuspenseQuery} from "@blitzjs/rpc"
|
||||
import getNoauthBasic from "../queries/getNoauthBasic"
|
||||
import {Suspense} from "react"
|
||||
|
||||
function Content() {
|
||||
const [result] = useQuery(getNoauthBasic, undefined)
|
||||
const [result] = useSuspenseQuery(getNoauthBasic, undefined)
|
||||
return <div id="content">{result}</div>
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {useMutation, useQuery} from "@blitzjs/rpc"
|
||||
import {useMutation, useSuspenseQuery} 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] = useQuery(getAuthenticatedBasic, undefined)
|
||||
const [result] = useSuspenseQuery(getAuthenticatedBasic, undefined)
|
||||
const [logoutMutation] = useMutation(logout)
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {useMutation, useQuery} from "@blitzjs/rpc"
|
||||
import {useMutation, useSuspenseQuery} 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] = useQuery(getAuthenticatedBasic, undefined)
|
||||
const [result] = useSuspenseQuery(getAuthenticatedBasic, undefined)
|
||||
const [logoutMutation] = useMutation(logout)
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {useMutation, useQuery} from "@blitzjs/rpc"
|
||||
import {useMutation, useSuspenseQuery} 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] = useQuery(getAuthenticatedBasic, undefined)
|
||||
const [result] = useSuspenseQuery(getAuthenticatedBasic, undefined)
|
||||
const [logoutMutation] = useMutation(logout)
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {useMutation, useQuery} from "@blitzjs/rpc"
|
||||
import {useMutation, useSuspenseQuery} 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] = useQuery(getAuthenticatedBasic, undefined)
|
||||
const [result] = useSuspenseQuery(getAuthenticatedBasic, undefined)
|
||||
const [logoutMutation] = useMutation(logout)
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {useMutation, useQuery} from "@blitzjs/rpc"
|
||||
import {useMutation, useSuspenseQuery} 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] = useQuery(getAuthenticatedBasic, undefined)
|
||||
const [result] = useSuspenseQuery(getAuthenticatedBasic, undefined)
|
||||
const [logoutMutation] = useMutation(logout)
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -32,9 +32,9 @@ type Props = {
|
||||
}
|
||||
|
||||
export const getServerSideProps = gSSP<Props>(async ({ctx}) => {
|
||||
await getQueryClient().prefetchQuery(getQueryKey(getNoauthBasic, null), () =>
|
||||
getNoauthBasic(null, ctx),
|
||||
)
|
||||
await getQueryClient().prefetchQuery({
|
||||
queryKey: getQueryKey(getNoauthBasic),
|
||||
})
|
||||
return {
|
||||
props: {
|
||||
dehydratedState: dehydrate(queryClient),
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import {invalidateQuery, useMutation, useQuery} from "@blitzjs/rpc"
|
||||
import {invalidateQuery, useMutation, useSuspenseQuery} from "@blitzjs/rpc"
|
||||
import changeRole from "../mutations/changeRole"
|
||||
import getPublicDataForUser from "../queries/getPublicDataForUser"
|
||||
import {Suspense} from "react"
|
||||
|
||||
function Content() {
|
||||
const [publicData] = useQuery(getPublicDataForUser, {userId: 1})
|
||||
const [publicData] = useSuspenseQuery(getPublicDataForUser, {userId: 1})
|
||||
return (
|
||||
<div id="session">
|
||||
<>
|
||||
|
||||
2
integration-tests/auth/next-env.d.ts
vendored
2
integration-tests/auth/next-env.d.ts
vendored
@@ -2,4 +2,4 @@
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
|
||||
|
||||
@@ -17,16 +17,16 @@
|
||||
"prisma:studio": "prisma studio"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.1.2",
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@blitzjs/next": "2.1.2",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.1.2",
|
||||
"@blitzjs/auth": "3.0.1",
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@blitzjs/next": "3.0.1",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "3.0.1",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "14.3.0-canary.28",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"secure-password": "4.0.0",
|
||||
"wait-port": "1.0.4"
|
||||
},
|
||||
@@ -36,13 +36,13 @@
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node": "18.7.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"b64-lite": "1.4.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
"get-port": "6.1.2",
|
||||
"node-fetch": "3.2.3",
|
||||
"playwright": "1.28.0",
|
||||
"playwright": "1.49.1",
|
||||
"ts-node": "10.9.1",
|
||||
"typescript": "^4.8.4"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference types="next/navigation-types/compat/navigation" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
|
||||
|
||||
@@ -16,24 +16,24 @@
|
||||
"schema": "db/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.1.2",
|
||||
"@blitzjs/next": "2.1.2",
|
||||
"@blitzjs/rpc": "2.1.2",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.1.2",
|
||||
"@blitzjs/auth": "3.0.1",
|
||||
"@blitzjs/next": "3.0.1",
|
||||
"@blitzjs/rpc": "3.0.1",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "3.0.1",
|
||||
"lowdb": "2.1.0",
|
||||
"next": "14.3.0-canary.28",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"b64-lite": "1.4.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
{
|
||||
"extends": "@blitzjs/config/tsconfig.nextjs.json",
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "types"],
|
||||
"include": ["**/*.ts", "**/*.tsx", "next-env.d.ts", "types", ".next/types/**/*.ts"],
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"react": ["./node_modules/@types/react"]
|
||||
}
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"strictNullChecks": true
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"baseUrl": "."
|
||||
|
||||
2
integration-tests/middleware/next-env.d.ts
vendored
2
integration-tests/middleware/next-env.d.ts
vendored
@@ -3,4 +3,4 @@
|
||||
/// <reference types="next/navigation-types/compat/navigation" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
|
||||
|
||||
@@ -11,20 +11,20 @@
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@blitzjs/next": "2.1.2",
|
||||
"@blitzjs/rpc": "2.1.2",
|
||||
"blitz": "2.1.2",
|
||||
"next": "14.3.0-canary.28",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@blitzjs/next": "3.0.1",
|
||||
"@blitzjs/rpc": "3.0.1",
|
||||
"blitz": "3.0.1",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
"get-port": "6.1.2",
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"use client"
|
||||
import {getQueryData, useQuery} from "@blitzjs/rpc"
|
||||
import {getQueryData, useSuspenseQuery} from "@blitzjs/rpc"
|
||||
import {Suspense, useState} from "react"
|
||||
import getBasic from "../../src/queries/getBasic"
|
||||
|
||||
function Content() {
|
||||
const [data] = useQuery(getBasic, undefined)
|
||||
const [data] = useSuspenseQuery(getBasic, undefined)
|
||||
const [newData, setNewData] = useState<string>()
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
|
||||
|
||||
@@ -17,17 +17,17 @@
|
||||
"prisma:studio": "prisma studio"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.1.2",
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@blitzjs/next": "2.1.2",
|
||||
"@blitzjs/rpc": "2.1.2",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.1.2",
|
||||
"@blitzjs/auth": "3.0.1",
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@blitzjs/next": "3.0.1",
|
||||
"@blitzjs/rpc": "3.0.1",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "3.0.1",
|
||||
"lowdb": "2.1.0",
|
||||
"next": "14.3.0-canary.28",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"secure-password": "4.0.0",
|
||||
"wait-port": "1.0.4"
|
||||
},
|
||||
@@ -37,13 +37,13 @@
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node": "18.7.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"b64-lite": "1.4.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
"get-port": "6.1.2",
|
||||
"node-fetch": "3.2.3",
|
||||
"playwright": "1.28.0",
|
||||
"playwright": "1.49.1",
|
||||
"ts-node": "10.9.1",
|
||||
"typescript": "^4.9.5"
|
||||
}
|
||||
|
||||
3
integration-tests/no-suspense/next-env.d.ts
vendored
3
integration-tests/no-suspense/next-env.d.ts
vendored
@@ -1,5 +1,6 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference types="next/navigation-types/compat/navigation" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
|
||||
|
||||
@@ -16,24 +16,24 @@
|
||||
"prisma:studio": "prisma studio"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.1.2",
|
||||
"@blitzjs/next": "2.1.2",
|
||||
"@blitzjs/rpc": "2.1.2",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.1.2",
|
||||
"@blitzjs/auth": "3.0.1",
|
||||
"@blitzjs/next": "3.0.1",
|
||||
"@blitzjs/rpc": "3.0.1",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "3.0.1",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "14.3.0-canary.28",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"b64-lite": "1.4.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
{
|
||||
"extends": "@blitzjs/config/tsconfig.nextjs.json",
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "types"],
|
||||
"include": ["**/*.ts", "**/*.tsx", "next-env.d.ts", "types", ".next/types/**/*.ts"],
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"react": ["./node_modules/@types/react"]
|
||||
}
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"strictNullChecks": true
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"baseUrl": "."
|
||||
|
||||
@@ -8,21 +8,21 @@
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.1.2",
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@blitzjs/next": "2.1.2",
|
||||
"@blitzjs/rpc": "2.1.2",
|
||||
"@prisma/client": "4.6.1",
|
||||
"@tanstack/react-query": "4.0.10",
|
||||
"blitz": "2.1.2",
|
||||
"next": "14.3.0-canary.28",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"@blitzjs/auth": "3.0.1",
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@blitzjs/next": "3.0.1",
|
||||
"@blitzjs/rpc": "3.0.1",
|
||||
"@prisma/client": "6.1.0",
|
||||
"@tanstack/react-query": "5.51.1",
|
||||
"blitz": "3.0.1",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@types/react": "18.0.25",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@vitejs/plugin-react": "1.3.0",
|
||||
"delay": "5.0.0",
|
||||
"eslint": "8.27.0",
|
||||
|
||||
@@ -3,3 +3,7 @@
|
||||
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\\")."`;
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import {describe, it, expect, beforeAll, vi} from "vitest"
|
||||
import {act, screen, waitForElementToBeRemoved} from "@testing-library/react"
|
||||
import {useQuery, useInfiniteQuery, BlitzRpcPlugin, BlitzProvider} from "@blitzjs/rpc"
|
||||
import {
|
||||
useSuspenseQuery,
|
||||
useQuery,
|
||||
useSuspenseInfiniteQuery,
|
||||
BlitzRpcPlugin,
|
||||
BlitzProvider,
|
||||
} from "@blitzjs/rpc"
|
||||
import React from "react"
|
||||
import delay from "delay"
|
||||
import {buildMutationRpc, buildQueryRpc, mockRouter, render} from "../../utils/blitz-test-utils"
|
||||
@@ -11,19 +17,18 @@ beforeAll(() => {
|
||||
globalThis.IS_REACT_ACT_ENVIRONMENT = true
|
||||
})
|
||||
|
||||
describe("useQuery", () => {
|
||||
describe("useSuspenseQuery", () => {
|
||||
const setupHook = (
|
||||
ID: string,
|
||||
params: any,
|
||||
queryFn: (...args: any) => any,
|
||||
options: Parameters<typeof useQuery>[2] = {} as any,
|
||||
options: Parameters<typeof useSuspenseQuery>[2] = {} as any,
|
||||
): [{data?: any; setQueryData?: any}, Function] => {
|
||||
let res = {}
|
||||
const qc = BlitzRpcPlugin({})
|
||||
|
||||
function TestHarness() {
|
||||
const [data, {setQueryData}] = useQuery(queryFn, params, {
|
||||
suspense: true,
|
||||
function TestSuspenseHarness() {
|
||||
const [data, {setQueryData}] = useSuspenseQuery(queryFn, params, {
|
||||
...(options as any),
|
||||
} as any)
|
||||
|
||||
@@ -38,7 +43,7 @@ describe("useQuery", () => {
|
||||
|
||||
const ui = () => (
|
||||
<React.Suspense fallback="Loading...">
|
||||
<TestHarness />
|
||||
<TestSuspenseHarness />
|
||||
</React.Suspense>
|
||||
)
|
||||
|
||||
@@ -90,27 +95,9 @@ describe("useQuery", () => {
|
||||
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")
|
||||
})
|
||||
|
||||
it("suspense disabled if enabled is undefined", async () => {
|
||||
setupHook("7", "test", buildQueryRpc(upcase), {enabled: undefined})
|
||||
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 = () => {
|
||||
useQuery(buildQueryRpc(upcase), undefined, {refetchInterval: 10000})
|
||||
useSuspenseQuery(buildQueryRpc(upcase), undefined, {refetchInterval: 10000})
|
||||
return <div></div>
|
||||
}
|
||||
const ui = () => <Demo />
|
||||
@@ -126,7 +113,112 @@ describe("useQuery", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("useInfiniteQuery", () => {
|
||||
describe("useQuery", () => {
|
||||
const setupHook = (
|
||||
ID: string,
|
||||
params: any,
|
||||
queryFn: (...args: any) => any,
|
||||
options: Parameters<typeof useQuery>[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 <div>Loading...</div>
|
||||
}
|
||||
return (
|
||||
<div id={`harness-${ID}`}>
|
||||
<span>{data ? `Ready${ID}` : "No data"}</span>
|
||||
<span>{data}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const ui = () => <TestHarness />
|
||||
|
||||
const {rerender} = render(ui(), {
|
||||
wrapper: ({children}) => (
|
||||
<BlitzProvider>
|
||||
<RouterContext.Provider value={mockRouter}>{children}</RouterContext.Provider>
|
||||
</BlitzProvider>
|
||||
),
|
||||
})
|
||||
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")
|
||||
})
|
||||
|
||||
it("suspense disabled if enabled is undefined", async () => {
|
||||
setupHook("7", "test", buildQueryRpc(upcase), {enabled: undefined})
|
||||
await screen.findByText("No data")
|
||||
})
|
||||
|
||||
it("works with options other than enabled & suspense without type error", () => {
|
||||
const Demo = () => {
|
||||
useSuspenseQuery(buildQueryRpc(upcase), undefined, {refetchInterval: 10000})
|
||||
return <div></div>
|
||||
}
|
||||
const ui = () => <Demo />
|
||||
|
||||
const {rerender} = render(ui(), {
|
||||
wrapper: ({children}) => (
|
||||
<BlitzProvider>
|
||||
<RouterContext.Provider value={mockRouter}>{children}</RouterContext.Provider>
|
||||
</BlitzProvider>
|
||||
),
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("useSuspenseInfiniteQuery", () => {
|
||||
const setupHook = (
|
||||
ID: string,
|
||||
params: (arg?: any) => any,
|
||||
@@ -138,7 +230,7 @@ describe("useInfiniteQuery", () => {
|
||||
function TestHarness() {
|
||||
// TODO - fix typing
|
||||
//@ts-ignore
|
||||
const [groupedData] = useInfiniteQuery(queryFn, params, {
|
||||
const [groupedData] = useSuspenseInfiniteQuery(queryFn, params, {
|
||||
suspense: true,
|
||||
getNextPageParam: () => {},
|
||||
})
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
/// <reference types="next/navigation-types/compat/navigation" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
|
||||
|
||||
@@ -16,23 +16,23 @@
|
||||
"schema": "db/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/next": "2.1.2",
|
||||
"@blitzjs/rpc": "2.1.2",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.1.2",
|
||||
"@blitzjs/next": "3.0.1",
|
||||
"@blitzjs/rpc": "3.0.1",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "3.0.1",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "14.3.0-canary.28",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"b64-lite": "1.4.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {getQueryData, useQuery} from "@blitzjs/rpc"
|
||||
import {getQueryData, useSuspenseQuery} from "@blitzjs/rpc"
|
||||
import {Suspense, useState} from "react"
|
||||
import getBasic from "../app/queries/getBasic"
|
||||
|
||||
function Content() {
|
||||
const [data] = useQuery(getBasic, undefined)
|
||||
const [data] = useSuspenseQuery(getBasic, undefined)
|
||||
const [newData, setNewData] = useState<string>()
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React, {Suspense} from "react"
|
||||
import {BlitzPage} from "@blitzjs/next"
|
||||
import {invalidateQuery, useQuery} from "@blitzjs/rpc"
|
||||
import {invalidateQuery, useSuspenseQuery} from "@blitzjs/rpc"
|
||||
import getSequence from "../app/queries/getSequence"
|
||||
|
||||
const useQueryOptions = {
|
||||
const useSuspenseQueryOptions = {
|
||||
refetchInterval: 0,
|
||||
refetchOnMount: false,
|
||||
refetchOnReconnect: false,
|
||||
@@ -11,8 +11,16 @@ const useQueryOptions = {
|
||||
}
|
||||
|
||||
const PageWithInvalidateQuery: React.FC = () => {
|
||||
const [query1, {isFetching: isQ1Fetching}] = useQuery(getSequence, "query1", useQueryOptions)
|
||||
const [query2, {isFetching: isQ2Fetching}] = useQuery(getSequence, "query2", useQueryOptions)
|
||||
const [query1, {isFetching: isQ1Fetching}] = useSuspenseQuery(
|
||||
getSequence,
|
||||
"query1",
|
||||
useSuspenseQueryOptions,
|
||||
)
|
||||
const [query2, {isFetching: isQ2Fetching}] = useSuspenseQuery(
|
||||
getSequence,
|
||||
"query2",
|
||||
useSuspenseQueryOptions,
|
||||
)
|
||||
|
||||
const isFetching = isQ1Fetching || isQ2Fetching
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {getQueryData, useQuery} from "@blitzjs/rpc"
|
||||
import {getQueryData, useSuspenseQuery} from "@blitzjs/rpc"
|
||||
import {Suspense, useState} from "react"
|
||||
import getNoSuspenseBasic from "../../no-suspense/app/queries/getNoSuspenseBasic"
|
||||
|
||||
function Content() {
|
||||
const [data] = useQuery(getNoSuspenseBasic, undefined)
|
||||
const [data] = useSuspenseQuery(getNoSuspenseBasic, undefined)
|
||||
const [newData, setNewData] = useState<string>()
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {useInfiniteQuery} from "@blitzjs/rpc"
|
||||
import {useSuspenseInfiniteQuery} 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] = useInfiniteQuery(
|
||||
const [data] = useSuspenseInfiniteQuery(
|
||||
testQuery,
|
||||
(pageParams) => ({...pageParams, name: "hello world"}),
|
||||
{
|
||||
suspense: false,
|
||||
getNextPageParam: (lastPage) => lastPage,
|
||||
initialPageParam: {name: "hello world"},
|
||||
},
|
||||
)
|
||||
return <div id="data">{data ? data : "no-data"}</div>
|
||||
|
||||
@@ -51,22 +51,22 @@ const runTests = () => {
|
||||
)
|
||||
})
|
||||
|
||||
describe("prefetch infinite query", () => {
|
||||
it(
|
||||
"should work",
|
||||
async () => {
|
||||
const browser = await webdriver(appPort, "/page-with-prefetch-inf-query")
|
||||
// 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")
|
||||
// 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,
|
||||
)
|
||||
})
|
||||
// if (browser) await browser.close()
|
||||
// },
|
||||
// 5000 * 60 * 2,
|
||||
// )
|
||||
// })
|
||||
|
||||
describe("invalidate query", () => {
|
||||
it(
|
||||
|
||||
@@ -7,19 +7,19 @@
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@blitzjs/next": "2.1.2",
|
||||
"@blitzjs/rpc": "2.1.2",
|
||||
"blitz": "2.1.2",
|
||||
"next": "14.3.0-canary.28",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@blitzjs/next": "3.0.1",
|
||||
"@blitzjs/rpc": "3.0.1",
|
||||
"blitz": "3.0.1",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"b64-lite": "1.4.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
|
||||
@@ -7,19 +7,19 @@
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@blitzjs/next": "2.1.2",
|
||||
"@blitzjs/rpc": "2.1.2",
|
||||
"blitz": "2.1.2",
|
||||
"next": "14.3.0-canary.28",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@blitzjs/next": "3.0.1",
|
||||
"@blitzjs/rpc": "3.0.1",
|
||||
"blitz": "3.0.1",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"b64-lite": "1.4.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference types="next/navigation-types/compat/navigation" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
|
||||
|
||||
@@ -16,24 +16,24 @@
|
||||
"schema": "db/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.1.2",
|
||||
"@blitzjs/next": "2.1.2",
|
||||
"@blitzjs/rpc": "2.1.2",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.1.2",
|
||||
"@blitzjs/auth": "3.0.1",
|
||||
"@blitzjs/next": "3.0.1",
|
||||
"@blitzjs/rpc": "3.0.1",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "3.0.1",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "14.3.0-canary.28",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"b64-lite": "1.4.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import getBasic from "../app/queries/getBasic"
|
||||
import {useQuery} from "@blitzjs/rpc"
|
||||
import {useSuspenseQuery} from "@blitzjs/rpc"
|
||||
import {Suspense} from "react"
|
||||
|
||||
function Content() {
|
||||
const [result] = useQuery(getBasic, undefined)
|
||||
const [result] = useSuspenseQuery(getBasic, undefined)
|
||||
return <div id="content">{result}</div>
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
{
|
||||
"extends": "@blitzjs/config/tsconfig.nextjs.json",
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "types"],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "types", ".next/types/**/*.ts"],
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"react": ["./node_modules/@types/react"]
|
||||
}
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"strictNullChecks": true
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"baseUrl": "."
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "workspace:2.1.2",
|
||||
"@blitzjs/next": "workspace:2.1.2",
|
||||
"@blitzjs/rpc": "workspace:2.1.2",
|
||||
"@blitzjs/config": "workspace:3.0.1",
|
||||
"@blitzjs/next": "workspace:3.0.1",
|
||||
"@blitzjs/rpc": "workspace:3.0.1",
|
||||
"@tanstack/react-query": "4.13.0",
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@types/rimraf": "3.0.2",
|
||||
"@types/selenium-webdriver": "4.0.18",
|
||||
"chromedriver": "100.0.0",
|
||||
@@ -22,9 +22,9 @@
|
||||
"get-port": "6.1.2",
|
||||
"node-fetch": "3.2.3",
|
||||
"pkg-dir": "5.0.0",
|
||||
"playwright-chromium": "1.28.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"playwright-chromium": "1.49.1",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"resolve-cwd": "3.0.0",
|
||||
"resolve-from": "5.0.0",
|
||||
"rimraf": "3.0.2",
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"husky": "8.0.2",
|
||||
"jsdom": "^19.0.0",
|
||||
"lint-staged": "13.0.3",
|
||||
"next": "14.3.0-canary.28",
|
||||
"next": "15.0.1",
|
||||
"only-allow": "1.1.0",
|
||||
"prettier": "^2.8.8",
|
||||
"prettier-plugin-prisma": "4.4.0",
|
||||
@@ -46,12 +46,11 @@
|
||||
]
|
||||
},
|
||||
"pnpm": {
|
||||
"patchedDependencies": {
|
||||
"next-auth@4.24.7": "patches/next-auth@4.24.7.patch"
|
||||
},
|
||||
"overrides": {
|
||||
"@types/mime": "3.0.4",
|
||||
"next": "14.3.0-canary.28"
|
||||
"next": "15.0.1",
|
||||
"@types/react": "npm:types-react@rc",
|
||||
"@types/react-dom": "npm:types-react-dom@rc"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,57 @@
|
||||
# @blitzjs/auth
|
||||
|
||||
## 3.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 816330b9d: fix: Overriden custom cookies used inside `withBlitzAuth`
|
||||
- blitz@3.0.1
|
||||
|
||||
## 3.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
- ce1a603b2: TODO: Upgrade @tanstack/react-query to v5.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ce1a603b2]
|
||||
- Updated dependencies [1610c73f9]
|
||||
- blitz@3.0.0
|
||||
|
||||
## 2.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.2.1
|
||||
|
||||
## 2.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 3fa3a4ef3: chore: support next.js 15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [565db3c5a]
|
||||
- Updated dependencies [3fa3a4ef3]
|
||||
- blitz@2.2.0
|
||||
|
||||
## 2.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.1.4
|
||||
|
||||
## 2.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 0b3286468: chore: bump `next.js` and `zod` versions
|
||||
- Updated dependencies [0b3286468]
|
||||
- Updated dependencies [50f17d21c]
|
||||
- blitz@2.1.3
|
||||
|
||||
## 2.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/auth",
|
||||
"version": "2.1.2",
|
||||
"version": "3.0.1",
|
||||
"homepage": "https://blitzjs.com/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -50,7 +50,7 @@
|
||||
"url": "0.11.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"blitz": "2.1.2",
|
||||
"blitz": "3.0.1",
|
||||
"next": "*",
|
||||
"next-auth": "*",
|
||||
"secure-password": "4.0.0"
|
||||
@@ -67,19 +67,18 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@testing-library/react-hooks": "8.0.1",
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@types/cookie": "0.4.1",
|
||||
"@types/debug": "4.1.7",
|
||||
"@types/jsonwebtoken": "8.5.8",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react-dom": "17.0.14",
|
||||
"blitz": "2.1.2",
|
||||
"next": "14.3.0-canary.28",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0",
|
||||
"blitz": "3.0.1",
|
||||
"next": "15.0.1",
|
||||
"next-auth": "4.24.7",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"secure-password": "4.0.0",
|
||||
"typescript": "^4.8.4",
|
||||
"unbuild": "0.7.6",
|
||||
|
||||
@@ -7,7 +7,7 @@ import {parsePublicDataToken, getPublicDataStore, useSession} from "./index"
|
||||
import {COOKIE_PUBLIC_DATA_TOKEN} from "../shared"
|
||||
import {toBase64} from "b64-lite"
|
||||
import {act} from "@testing-library/react"
|
||||
import {renderHook} from "@testing-library/react-hooks"
|
||||
import {renderHook} from "@testing-library/react"
|
||||
|
||||
vi.mock("blitz", async () => {
|
||||
const blitz = await vi.importActual("blitz")
|
||||
|
||||
@@ -152,7 +152,7 @@ export interface UseSessionOptions {
|
||||
}
|
||||
|
||||
export const useSession = (options: UseSessionOptions = {}): ClientSession => {
|
||||
const suspense = options?.suspense ?? Boolean(globalThis.__BLITZ_SUSPENSE_ENABLED)
|
||||
const suspense = options?.suspense ?? true
|
||||
|
||||
let initialState: ClientSession
|
||||
if (options.initialPublicData) {
|
||||
@@ -260,7 +260,7 @@ export type RedirectAuthenticatedToFn = (
|
||||
) => RedirectAuthenticatedTo
|
||||
|
||||
export type BlitzPage<P = {}> = React.ComponentType<P> & {
|
||||
getLayout?: (component: JSX.Element) => JSX.Element
|
||||
getLayout?: (component: React.JSX.Element) => React.JSX.Element
|
||||
authenticate?: boolean | {redirectTo?: string | RouteUrlObject; role?: string | Array<string>}
|
||||
suppressFirstRenderFlicker?: boolean
|
||||
redirectAuthenticatedTo?: RedirectAuthenticatedTo | RedirectAuthenticatedToFn
|
||||
|
||||
@@ -5,6 +5,5 @@ 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<Ctx>
|
||||
}
|
||||
|
||||
@@ -289,8 +289,10 @@ const makeProxyToPublicData = <T extends SessionContextClass>(ctxClass: T): T =>
|
||||
export async function getBlitzContext(): Promise<Ctx> {
|
||||
try {
|
||||
const {headers, cookies} = require("next/headers")
|
||||
const reqHeader = Object.fromEntries(headers())
|
||||
const csrfToken = cookies().get(COOKIE_CSRF_TOKEN())
|
||||
const cookieStore = await cookies()
|
||||
const headersStore = await headers()
|
||||
const reqHeader = Object.fromEntries(headersStore)
|
||||
const csrfToken = cookieStore.get(COOKIE_CSRF_TOKEN())
|
||||
if (csrfToken) {
|
||||
reqHeader[HEADER_CSRF] = csrfToken.value
|
||||
}
|
||||
@@ -464,7 +466,7 @@ export class SessionContextClass implements SessionContext {
|
||||
}
|
||||
const cookieHeaders = this._headers.get("set-cookie")
|
||||
if (response instanceof Response) {
|
||||
response.headers.set("Set-Cookie", cookieHeaders!)
|
||||
response.headers.append("Set-Cookie", cookieHeaders!)
|
||||
} else {
|
||||
response.setHeader("Set-Cookie", splitCookiesString(cookieHeaders!))
|
||||
}
|
||||
|
||||
@@ -1,5 +1,64 @@
|
||||
# @blitzjs/next
|
||||
|
||||
## 3.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @blitzjs/rpc@3.0.1
|
||||
- blitz@3.0.1
|
||||
|
||||
## 3.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
- ce1a603b2: TODO: Upgrade @tanstack/react-query to v5.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [11c9f00eb]
|
||||
- Updated dependencies [ce1a603b2]
|
||||
- Updated dependencies [1610c73f9]
|
||||
- @blitzjs/rpc@3.0.0
|
||||
- blitz@3.0.0
|
||||
|
||||
## 2.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.2.1
|
||||
- @blitzjs/rpc@2.2.1
|
||||
|
||||
## 2.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 3fa3a4ef3: chore: support next.js 15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [565db3c5a]
|
||||
- Updated dependencies [3fa3a4ef3]
|
||||
- blitz@2.2.0
|
||||
- @blitzjs/rpc@2.2.0
|
||||
|
||||
## 2.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ce23d4ed0: fix: Update `turbopack-empty.js` syntax to support latest turbopack and next.js versions
|
||||
- blitz@2.1.4
|
||||
- @blitzjs/rpc@2.1.4
|
||||
|
||||
## 2.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 0b3286468: chore: bump `next.js` and `zod` versions
|
||||
- Updated dependencies [0b3286468]
|
||||
- Updated dependencies [50f17d21c]
|
||||
- @blitzjs/rpc@2.1.3
|
||||
- blitz@2.1.3
|
||||
|
||||
## 2.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/next",
|
||||
"version": "2.1.2",
|
||||
"version": "3.0.1",
|
||||
"homepage": "https://blitzjs.com/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -29,7 +29,7 @@
|
||||
"eslint.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"@blitzjs/rpc": "2.1.2",
|
||||
"@blitzjs/rpc": "3.0.1",
|
||||
"@types/hoist-non-react-statics": "3.3.1",
|
||||
"copy-webpack-plugin": "11.0.0",
|
||||
"debug": "4.3.3",
|
||||
@@ -39,30 +39,29 @@
|
||||
"supports-color": "8.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"blitz": "2.1.2",
|
||||
"blitz": "3.0.1",
|
||||
"next": "*",
|
||||
"react": "*",
|
||||
"tslog": "4.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@testing-library/dom": "8.13.0",
|
||||
"@testing-library/jest-dom": "5.16.3",
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@testing-library/react-hooks": "8.0.1",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@testing-library/user-event": "13.5.0",
|
||||
"@types/debug": "4.1.7",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react-dom": "17.0.14",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0",
|
||||
"@types/testing-library__react-hooks": "4.0.0",
|
||||
"blitz": "2.1.2",
|
||||
"blitz": "3.0.1",
|
||||
"cross-spawn": "7.0.3",
|
||||
"find-up": "4.1.0",
|
||||
"next": "14.3.0-canary.28",
|
||||
"next": "15.0.1",
|
||||
"next-router-mock": "0.9.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"resolve-from": "5.0.0",
|
||||
"ts-jest": "27.1.4",
|
||||
"tslog": "4.9.0",
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
export {}
|
||||
const exports = {
|
||||
"npm-which": {},
|
||||
"cross-spawn": {},
|
||||
fs: {},
|
||||
child_process: {},
|
||||
}
|
||||
|
||||
module.exports = exports
|
||||
|
||||
@@ -70,7 +70,7 @@ test("handleError forwards along async errors", async () => {
|
||||
//
|
||||
// React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary."
|
||||
// `)
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// can recover
|
||||
@@ -116,7 +116,7 @@ test("can pass an error to useErrorHandler", async () => {
|
||||
//
|
||||
// React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary."
|
||||
// `)
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// can recover
|
||||
|
||||
@@ -77,25 +77,10 @@ test("standard use-case", () => {
|
||||
const {unmount} = render(<App />)
|
||||
|
||||
userEvent.type(screen.getByRole("textbox", {name: /username/i}), "fail")
|
||||
|
||||
const [[actualError], [componentStack]] = consoleError.mock.calls
|
||||
expect(firstLine(actualError as string)).toMatchInlineSnapshot(
|
||||
`"Error: Uncaught [Error: 💥 CABOOM 💥]"`,
|
||||
)
|
||||
expect(cleanStack(componentStack)).toMatchInlineSnapshot(`
|
||||
"Error: Uncaught [Error: 💥 CABOOM 💥]
|
||||
at reportException
|
||||
at innerInvokeEventListeners
|
||||
at invokeEventListeners
|
||||
at HTMLUnknownElementImpl._dispatch
|
||||
at HTMLUnknownElementImpl.dispatchEvent
|
||||
at HTMLUnknownElement.dispatchEvent
|
||||
at Object.invokeGuardedCallbackDev
|
||||
at invokeGuardedCallback
|
||||
at beginWork\$1
|
||||
at performUnitOfWork "
|
||||
`)
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
const calls = consoleError.mock.calls[0]
|
||||
//@ts-expect-error - it's a mock
|
||||
expect(calls[1]).toMatchInlineSnapshot("[Error: 💥 CABOOM 💥]")
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
expect(screen.getByRole("alert")).toMatchInlineSnapshot(`
|
||||
@@ -149,7 +134,7 @@ test("fallbackRender prop", () => {
|
||||
}
|
||||
|
||||
const {unmount} = render(<App />)
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// the render prop API allows a single action to reset the app state
|
||||
@@ -168,7 +153,7 @@ test("simple fallback is supported", () => {
|
||||
<span>child</span>
|
||||
</ErrorBoundary>,
|
||||
)
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
expect(screen.getByText(/oh no/i)).to.exist
|
||||
expect(screen.queryByText(/child/i)).to.not.exist
|
||||
@@ -183,27 +168,16 @@ test("withErrorBoundary HOC", () => {
|
||||
() => {
|
||||
throw new Error("💥 CABOOM 💥")
|
||||
},
|
||||
{FallbackComponent: ErrorFallback, onError: onErrorHandler},
|
||||
{
|
||||
FallbackComponent: ErrorFallback,
|
||||
onError: onErrorHandler,
|
||||
},
|
||||
)
|
||||
const {unmount} = render(<Boundary />)
|
||||
|
||||
const [[actualError], [componentStack]] = consoleError.mock.calls
|
||||
const firstLineOfError = firstLine(actualError as string)
|
||||
expect(firstLineOfError).toMatchInlineSnapshot(`"Error: Uncaught [Error: 💥 CABOOM 💥]"`)
|
||||
expect(cleanStack(componentStack)).toMatchInlineSnapshot(`
|
||||
"Error: Uncaught [Error: 💥 CABOOM 💥]
|
||||
at reportException
|
||||
at innerInvokeEventListeners
|
||||
at invokeEventListeners
|
||||
at HTMLUnknownElementImpl._dispatch
|
||||
at HTMLUnknownElementImpl.dispatchEvent
|
||||
at HTMLUnknownElement.dispatchEvent
|
||||
at Object.invokeGuardedCallbackDev
|
||||
at invokeGuardedCallback
|
||||
at beginWork\$1
|
||||
at performUnitOfWork "
|
||||
`)
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
const calls = consoleError.mock.calls[0]
|
||||
//@ts-expect-error - it's a mock
|
||||
expect(calls[1]).toMatchInlineSnapshot("[Error: 💥 CABOOM 💥]")
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
const [error, onErrorComponentStack] = (onErrorHandler.mock.calls as [[Error, string]])[0]
|
||||
@@ -265,7 +239,6 @@ test("requires either a fallback, fallbackRender, or FallbackComponent", () => {
|
||||
let unmount: undefined | (() => void)
|
||||
expect(() => {
|
||||
const result = render(
|
||||
// @ts-expect-error we're testing the runtime check of missing props here
|
||||
<ErrorBoundary>
|
||||
<Bomb />
|
||||
</ErrorBoundary>,
|
||||
@@ -318,7 +291,7 @@ test("supports automatic reset of error boundary when resetKeys change", () => {
|
||||
// blow it up
|
||||
userEvent.click(screen.getByText("toggle explode"))
|
||||
expect(screen.getByRole("alert")).to.exist
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// recover via try again button
|
||||
@@ -333,7 +306,7 @@ test("supports automatic reset of error boundary when resetKeys change", () => {
|
||||
// blow it up again
|
||||
userEvent.click(screen.getByText("toggle explode"))
|
||||
expect(screen.getByRole("alert")).to.exist
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// recover via resetKeys change
|
||||
@@ -348,7 +321,7 @@ test("supports automatic reset of error boundary when resetKeys change", () => {
|
||||
// blow it up again
|
||||
userEvent.click(screen.getByText("toggle explode"))
|
||||
expect(screen.getByRole("alert")).to.exist
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// toggles adding an extra resetKey to the array
|
||||
@@ -358,7 +331,7 @@ test("supports automatic reset of error boundary when resetKeys change", () => {
|
||||
expect(handleResetKeysChange).toHaveBeenCalledWith([true], [true, true])
|
||||
handleResetKeysChange.mockClear()
|
||||
expect(screen.getByRole("alert")).to.exist
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// toggle explode back to false
|
||||
@@ -369,7 +342,7 @@ test("supports automatic reset of error boundary when resetKeys change", () => {
|
||||
expect(handleResetKeysChange).toHaveBeenCalledWith([true, true], [false, true])
|
||||
expect(screen.getByRole("alert")).to.exist
|
||||
handleResetKeysChange.mockClear()
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// toggle extra resetKey
|
||||
@@ -411,7 +384,7 @@ test("supports reset via resetKeys right after error is triggered on component m
|
||||
|
||||
// it blows up on render
|
||||
expect(screen.queryByRole("alert", {})).to.exist
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// recover via "toggle explode" button
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {RedirectError} from "blitz"
|
||||
import {useRouter} from "next/compat/router"
|
||||
import type {NextRouter} from "next/router"
|
||||
import * as React from "react"
|
||||
import React from "react"
|
||||
import {RouterContext} from "./router-context"
|
||||
import _debug from "debug"
|
||||
import type {ExcludeRouterProps, WithRouterProps} from "next/dist/client/with-router"
|
||||
@@ -77,7 +77,7 @@ const initialState: ErrorBoundaryState = {error: null}
|
||||
function withRouter<P extends WithRouterProps>(
|
||||
ComposedComponent: React.ComponentType<P>,
|
||||
): React.ComponentType<ExcludeRouterProps<P>> {
|
||||
function WithRouterWrapper(props: any): JSX.Element {
|
||||
function WithRouterWrapper(props: any): React.JSX.Element {
|
||||
return <ComposedComponent router={useRouter()} {...props} />
|
||||
}
|
||||
|
||||
@@ -114,7 +114,13 @@ export const ErrorBoundary = withRouter(
|
||||
await this.props.router.push(error.url)
|
||||
return
|
||||
}
|
||||
this.props.onError?.(error, info)
|
||||
if (this.props.onError) {
|
||||
let componentStack = info.componentStack
|
||||
if (!componentStack) {
|
||||
componentStack = new Error("Stack trace").stack || ""
|
||||
}
|
||||
this.props.onError(error, {componentStack})
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -190,7 +196,7 @@ export const ErrorBoundary = withRouter(
|
||||
},
|
||||
)
|
||||
|
||||
function withErrorBoundary<P extends JSX.IntrinsicAttributes>(
|
||||
function withErrorBoundary<P extends React.JSX.IntrinsicAttributes>(
|
||||
Component: React.ComponentType<P>,
|
||||
errorBoundaryProps: ErrorBoundaryProps,
|
||||
): React.ComponentType<P> {
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import React from "react"
|
||||
import {NextPageContext} from "next"
|
||||
import dynamic from "next/dynamic"
|
||||
const Head = dynamic(() => import("next/head").then((mod) => mod.default), {
|
||||
ssr: false,
|
||||
loading: () => null,
|
||||
})
|
||||
const Head = dynamic(
|
||||
() =>
|
||||
import("next/head").then((mod) => ({
|
||||
default: mod.default,
|
||||
})),
|
||||
{
|
||||
ssr: false,
|
||||
loading: () => null,
|
||||
},
|
||||
)
|
||||
|
||||
const statusCodes: {[code: number]: string} = {
|
||||
400: "Bad Request",
|
||||
|
||||
@@ -9,10 +9,16 @@ import type {Router} from "next/router"
|
||||
import {BlitzProvider} from "./provider"
|
||||
import dynamic from "next/dynamic"
|
||||
export {Routes} from ".blitz"
|
||||
const Head = dynamic(() => import("next/head").then((mod) => mod.default), {
|
||||
ssr: false,
|
||||
loading: () => null,
|
||||
})
|
||||
const Head = dynamic(
|
||||
() =>
|
||||
import("next/head").then((mod) => ({
|
||||
default: mod.default,
|
||||
})),
|
||||
{
|
||||
ssr: false,
|
||||
loading: () => null,
|
||||
},
|
||||
)
|
||||
|
||||
export {BlitzProvider} from "./provider"
|
||||
|
||||
@@ -55,7 +61,7 @@ type RedirectAuthenticatedToFnCtx = {
|
||||
}
|
||||
type RedirectAuthenticatedToFn = (args: RedirectAuthenticatedToFnCtx) => RedirectAuthenticatedTo
|
||||
export type BlitzPage<P = {}> = React.ComponentType<P> & {
|
||||
getLayout?: (component: JSX.Element) => JSX.Element
|
||||
getLayout?: (component: React.JSX.Element) => React.JSX.Element
|
||||
authenticate?: boolean | {redirectTo?: string | RouteUrlObject; role?: string | Array<string>}
|
||||
suppressFirstRenderFlicker?: boolean
|
||||
redirectAuthenticatedTo?: RedirectAuthenticatedTo | RedirectAuthenticatedToFn
|
||||
|
||||
@@ -123,11 +123,15 @@ const prefetchQueryFactory = (
|
||||
}
|
||||
|
||||
if (infinite) {
|
||||
await queryClient.prefetchInfiniteQuery(getInfiniteQueryKey(fn, input), () =>
|
||||
fn(input, ctx),
|
||||
)
|
||||
await queryClient.prefetchQuery({
|
||||
queryKey: getInfiniteQueryKey(fn, input),
|
||||
queryFn: () => fn(input, ctx),
|
||||
})
|
||||
} else {
|
||||
await queryClient.prefetchQuery(getQueryKey(fn, input), () => fn(input, ctx))
|
||||
await queryClient.prefetchQuery({
|
||||
queryKey: getQueryKey(fn, input),
|
||||
queryFn: () => fn(input, ctx),
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -243,7 +247,6 @@ export interface BlitzConfig extends NextConfig {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function withBlitz(nextConfig: BlitzConfig = {}): NextConfig {
|
||||
if (
|
||||
process.env.NODE_ENV !== "production" &&
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {QueryClientProvider, Hydrate} from "@blitzjs/rpc"
|
||||
import {QueryClientProvider, HydrationBoundary} from "@blitzjs/rpc"
|
||||
import type {QueryClient, HydrateOptions} from "@blitzjs/rpc"
|
||||
import React from "react"
|
||||
|
||||
export type BlitzProviderProps = {
|
||||
children: JSX.Element
|
||||
children: React.JSX.Element
|
||||
client?: QueryClient
|
||||
contextSharing?: boolean
|
||||
dehydratedState?: unknown
|
||||
@@ -12,20 +12,16 @@ export type BlitzProviderProps = {
|
||||
|
||||
export const BlitzProvider = ({
|
||||
client = globalThis.queryClient,
|
||||
contextSharing = false,
|
||||
dehydratedState,
|
||||
hydrateOptions,
|
||||
children,
|
||||
}: BlitzProviderProps) => {
|
||||
if (client) {
|
||||
return (
|
||||
<QueryClientProvider
|
||||
client={client || globalThis.queryClient}
|
||||
contextSharing={contextSharing}
|
||||
>
|
||||
<Hydrate state={dehydratedState} options={hydrateOptions}>
|
||||
<QueryClientProvider client={client || globalThis.queryClient}>
|
||||
<HydrationBoundary state={dehydratedState} options={hydrateOptions}>
|
||||
{children}
|
||||
</Hydrate>
|
||||
</HydrationBoundary>
|
||||
</QueryClientProvider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import React from "react"
|
||||
import {describe, it, expect, vi, afterEach} from "vitest"
|
||||
import {extractRouterParams, useParam, useParams} from "./use-params"
|
||||
import {renderHook as defaultRenderHook} from "@testing-library/react-hooks"
|
||||
import {renderHook as defaultRenderHook} from "@testing-library/react"
|
||||
import {NextRouter} from "next/router"
|
||||
import {RouterContext} from "./router-context"
|
||||
|
||||
|
||||
@@ -1,5 +1,57 @@
|
||||
# @blitzjs/rpc
|
||||
|
||||
## 3.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@3.0.1
|
||||
|
||||
## 3.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
- ce1a603b2: TODO: Upgrade @tanstack/react-query to v5.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 11c9f00eb: fix(4407): setQueryData with useInfiniteQuery
|
||||
- Updated dependencies [ce1a603b2]
|
||||
- Updated dependencies [1610c73f9]
|
||||
- blitz@3.0.0
|
||||
|
||||
## 2.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.2.1
|
||||
|
||||
## 2.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 3fa3a4ef3: chore: support next.js 15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [565db3c5a]
|
||||
- Updated dependencies [3fa3a4ef3]
|
||||
- blitz@2.2.0
|
||||
|
||||
## 2.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.1.4
|
||||
|
||||
## 2.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 0b3286468: chore: bump `next.js` and `zod` versions
|
||||
- Updated dependencies [0b3286468]
|
||||
- Updated dependencies [50f17d21c]
|
||||
- blitz@2.1.3
|
||||
|
||||
## 2.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/rpc",
|
||||
"version": "2.1.2",
|
||||
"version": "3.0.1",
|
||||
"homepage": "https://blitzjs.com/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -27,7 +27,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@swc/core": "1.3.7",
|
||||
"@tanstack/react-query": "4.24.4",
|
||||
"@tanstack/react-query": "5.51.1",
|
||||
"b64-lite": "1.4.0",
|
||||
"bad-behavior": "1.0.1",
|
||||
"chalk": "^4.1.0",
|
||||
@@ -36,26 +36,26 @@
|
||||
"supports-color": "8.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tanstack/query-core": "4.24.4",
|
||||
"blitz": "2.1.2",
|
||||
"@tanstack/query-core": "5.51.1",
|
||||
"blitz": "3.0.1",
|
||||
"next": "*",
|
||||
"react": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/auth": "2.1.2",
|
||||
"@blitzjs/config": "2.1.2",
|
||||
"@tanstack/query-core": "4.24.4",
|
||||
"@blitzjs/auth": "3.0.1",
|
||||
"@blitzjs/config": "3.0.1",
|
||||
"@tanstack/query-core": "5.51.1",
|
||||
"@types/debug": "4.1.7",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react-dom": "17.0.14",
|
||||
"blitz": "2.1.2",
|
||||
"next": "14.3.0-canary.28",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0",
|
||||
"blitz": "3.0.1",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"typescript": "^4.8.4",
|
||||
"unbuild": "0.7.6",
|
||||
"watch": "1.0.2",
|
||||
"zod": "3.20.2"
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -4,7 +4,6 @@ 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<Ctx>
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ export {
|
||||
useMutation,
|
||||
usePaginatedQuery,
|
||||
useQuery,
|
||||
useSuspenseInfiniteQuery,
|
||||
useSuspenseQuery,
|
||||
} from "./query/react-query"
|
||||
export type {
|
||||
DefaultOptions,
|
||||
@@ -28,5 +30,6 @@ export type {
|
||||
export * from "./query/utils"
|
||||
|
||||
import {reactQueryClientReExports} from "./query/react-query"
|
||||
const {QueryClientProvider, Hydrate, useQueryErrorResetBoundary} = reactQueryClientReExports
|
||||
export {QueryClientProvider, Hydrate, useQueryErrorResetBoundary}
|
||||
const {QueryClientProvider, HydrationBoundary, useQueryErrorResetBoundary} =
|
||||
reactQueryClientReExports
|
||||
export {QueryClientProvider, HydrationBoundary, useQueryErrorResetBoundary}
|
||||
|
||||
@@ -221,7 +221,7 @@ async function getResolverMap(): Promise<ResolverFiles | null | undefined> {
|
||||
// Handles:
|
||||
// - Vite
|
||||
// {
|
||||
// const {resolverFilesLoaded, viteProvider} = await loadTelefuncFilesWithVite(runContext)
|
||||
// const {resolverFilesLoaded, viteProvider} = await loadTelefuncFilesWithVite(run
|
||||
// if (resolverFilesLoaded) {
|
||||
// assertUsage(
|
||||
// Object.keys(resolverFilesLoaded).length > 0,
|
||||
@@ -364,17 +364,18 @@ type Params = Record<string, unknown>
|
||||
|
||||
export function rpcAppHandler(config?: RpcConfig) {
|
||||
registerBlitzErrorClasses()
|
||||
async function handleRpcRequest(req: Request, context: {params: Params}, ctx?: Ctx) {
|
||||
async function handleRpcRequest(req: Request, segmentData: {params: Promise<Params>}, ctx?: Ctx) {
|
||||
const params = await segmentData.params
|
||||
const session = ctx?.session
|
||||
const resolverMap = await getResolverMap()
|
||||
assert(resolverMap, "No query or mutation resolvers found")
|
||||
|
||||
assert(
|
||||
Array.isArray(context.params.blitz),
|
||||
Array.isArray(params.blitz),
|
||||
"It seems your Blitz RPC endpoint file is not named [[...blitz]].(jt)s. Please ensure it is",
|
||||
)
|
||||
|
||||
const relativeRoutePath = (context.params.blitz as string[])?.join("/")
|
||||
const relativeRoutePath = (params.blitz as string[])?.join("/")
|
||||
const routePath = "/" + relativeRoutePath
|
||||
const resolverName = routePath.replace(/(\/api\/rpc)?\//, "")
|
||||
const rpcLogger = new RpcLogger(resolverName, config?.logging)
|
||||
@@ -413,14 +414,14 @@ export function rpcAppHandler(config?: RpcConfig) {
|
||||
json:
|
||||
req.method === "POST"
|
||||
? body.params
|
||||
: context.params.params
|
||||
? parse(`${context.params.params}`)
|
||||
: params.params
|
||||
? parse(`${params.params}`)
|
||||
: undefined,
|
||||
meta:
|
||||
req.method === "POST"
|
||||
? body.meta?.params
|
||||
: context.params.meta
|
||||
? parse(`${context.params.meta}`)
|
||||
: params.meta
|
||||
? parse(`${params.meta}`)
|
||||
: undefined,
|
||||
})
|
||||
rpcLogger.timer.initResolver()
|
||||
|
||||
@@ -28,11 +28,6 @@ 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,
|
||||
@@ -47,7 +42,6 @@ export const BlitzRpcPlugin = createClientPlugin<
|
||||
return false
|
||||
},
|
||||
...reactQueryOptions?.queries,
|
||||
suspense: suspenseEnabled,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {QueryClientProvider} from "@tanstack/react-query"
|
||||
import React from "react"
|
||||
|
||||
export type BlitzProviderType = ({children}: {children: React.ReactNode}) => JSX.Element
|
||||
export type BlitzProviderType = ({children}: {children: React.ReactNode}) => React.JSX.Element
|
||||
|
||||
const BlitzProvider: BlitzProviderType = ({children}) => {
|
||||
const [queryClient] = React.useState(globalThis.queryClient)
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
import {useQueryErrorResetBoundary, QueryClientProvider, Hydrate} from "@tanstack/react-query"
|
||||
import {
|
||||
useQueryErrorResetBoundary,
|
||||
QueryClientProvider,
|
||||
HydrationBoundary,
|
||||
keepPreviousData,
|
||||
} from "@tanstack/react-query"
|
||||
import type {DefaultError, InfiniteData} from "@tanstack/query-core"
|
||||
|
||||
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,
|
||||
Hydrate,
|
||||
HydrationBoundary,
|
||||
}
|
||||
|
||||
import type {
|
||||
@@ -18,6 +26,8 @@ import type {
|
||||
UseMutationOptions,
|
||||
UseMutationResult,
|
||||
MutateOptions,
|
||||
UseSuspenseQueryOptions,
|
||||
UseSuspenseInfiniteQueryOptions,
|
||||
} from "@tanstack/react-query"
|
||||
|
||||
import {isServer, FirstParam, PromiseReturnType, AsyncFunc} from "blitz"
|
||||
@@ -29,6 +39,7 @@ import {
|
||||
sanitizeQuery,
|
||||
sanitizeMutation,
|
||||
getInfiniteQueryKey,
|
||||
QueryType,
|
||||
} from "../utils"
|
||||
import {useRouter} from "next/compat/router"
|
||||
|
||||
@@ -52,43 +63,42 @@ export type RestQueryResult<TResult, TError> = Omit<UseQueryResult<TResult, TErr
|
||||
export function useQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = unknown,
|
||||
TError = DefaultError,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
params: FirstParam<T>,
|
||||
options?: UseQueryOptions<TResult, TError, TSelectedData> & QueryNonLazyOptions,
|
||||
): [TSelectedData, RestQueryResult<TSelectedData, TError>]
|
||||
options?: Omit<UseQueryOptions<TResult, TError, TSelectedData>, "queryKey"> & QueryNonLazyOptions,
|
||||
): [TSelectedData | undefined, RestQueryResult<TSelectedData | undefined, TError>]
|
||||
export function useQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = unknown,
|
||||
TError = DefaultError,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
params: FirstParam<T>,
|
||||
options: UseQueryOptions<TResult, TError, TSelectedData> & QueryLazyOptions,
|
||||
): [TSelectedData | undefined, RestQueryResult<TSelectedData, TError>]
|
||||
options: Omit<UseQueryOptions<TResult, TError, TSelectedData>, "queryKey"> & QueryLazyOptions,
|
||||
): [TSelectedData | undefined, RestQueryResult<TSelectedData | undefined, TError>]
|
||||
export function useQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = unknown,
|
||||
TError = DefaultError,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
params: FirstParam<T>,
|
||||
options: UseQueryOptions<TResult, TError, TSelectedData> = {},
|
||||
options: Omit<UseQueryOptions<TResult, TError, TSelectedData>, "queryKey"> = {},
|
||||
) {
|
||||
if (typeof queryFn === "undefined") {
|
||||
throw new Error("useQuery is missing the first argument - it must be a query function")
|
||||
}
|
||||
|
||||
const suspenseEnabled = Boolean(globalThis.__BLITZ_SUSPENSE_ENABLED)
|
||||
let enabled = isServer && suspenseEnabled ? false : options?.enabled ?? options?.enabled !== null
|
||||
let enabled = isServer ? false : options?.enabled ?? options?.enabled !== null
|
||||
let routerIsReady = false
|
||||
const router = useRouter()
|
||||
if (router) {
|
||||
routerIsReady = router?.isReady || (isServer && suspenseEnabled)
|
||||
routerIsReady = router?.isReady || isServer
|
||||
} else {
|
||||
routerIsReady = true
|
||||
}
|
||||
@@ -99,19 +109,70 @@ export function useQuery<
|
||||
queryKey: routerIsReady ? queryKey : ["_routerNotReady_"],
|
||||
queryFn: routerIsReady
|
||||
? ({signal}) => enhancedResolverRpcClient(params, {fromQueryHook: true}, signal)
|
||||
: (emptyQueryFn as any),
|
||||
: (emptyQueryFn as PromiseReturnType<T>),
|
||||
...options,
|
||||
enabled,
|
||||
})
|
||||
|
||||
if (
|
||||
queryRest.fetchStatus === "idle" &&
|
||||
isServer &&
|
||||
suspenseEnabled !== false &&
|
||||
!data &&
|
||||
(!options || !("suspense" in options) || options.suspense) &&
|
||||
(!options || !("enabled" in options) || options.enabled)
|
||||
) {
|
||||
const rest = {
|
||||
...queryRest,
|
||||
...getQueryCacheFunctions<FirstParam<T>, TResult, T>(queryFn, params),
|
||||
}
|
||||
|
||||
return [data, rest]
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// useSuspenseQuery
|
||||
// -------------------------
|
||||
|
||||
export function useSuspenseQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = DefaultError,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
params: FirstParam<T>,
|
||||
options?: Omit<UseQueryOptions<TResult, TError, TSelectedData>, "queryKey"> & QueryNonLazyOptions,
|
||||
): [TSelectedData, RestQueryResult<TSelectedData, TError>]
|
||||
export function useSuspenseQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = DefaultError,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
params: FirstParam<T>,
|
||||
options: Omit<UseSuspenseQueryOptions<TResult, TError, TSelectedData>, "queryKey"> &
|
||||
QueryLazyOptions,
|
||||
): [TSelectedData | undefined, RestQueryResult<TSelectedData, TError>]
|
||||
export function useSuspenseQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = DefaultError,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
params: FirstParam<T>,
|
||||
options: Omit<UseSuspenseQueryOptions<TResult, TError, TSelectedData>, "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) {
|
||||
const e = new NextError()
|
||||
e.name = "Rendering Suspense fallback..."
|
||||
e.digest = "DYNAMIC_SERVER_USAGE"
|
||||
@@ -121,12 +182,19 @@ export function useQuery<
|
||||
throw e
|
||||
}
|
||||
|
||||
const {data, ...queryRest} = useSuspenseReactQuery({
|
||||
queryKey: routerIsReady ? queryKey : ["_routerNotReady_"],
|
||||
queryFn: routerIsReady
|
||||
? ({signal}) => enhancedResolverRpcClient(params, {fromQueryHook: true}, signal)
|
||||
: (emptyQueryFn as PromiseReturnType<T>),
|
||||
...options,
|
||||
})
|
||||
|
||||
const rest = {
|
||||
...queryRest,
|
||||
...getQueryCacheFunctions<FirstParam<T>, TResult, T>(queryFn, params),
|
||||
}
|
||||
|
||||
// return [data, rest as RestQueryResult<TResult>]
|
||||
return [data, rest]
|
||||
}
|
||||
|
||||
@@ -139,43 +207,42 @@ export type RestPaginatedResult<TResult, TError> = Omit<UseQueryResult<TResult,
|
||||
export function usePaginatedQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = unknown,
|
||||
TError = DefaultError,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
params: FirstParam<T>,
|
||||
options?: UseQueryOptions<TResult, TError, TSelectedData> & QueryNonLazyOptions,
|
||||
): [TSelectedData, RestPaginatedResult<TSelectedData, TError>]
|
||||
export function usePaginatedQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = unknown,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
params: FirstParam<T>,
|
||||
options: UseQueryOptions<TResult, TError, TSelectedData> & QueryLazyOptions,
|
||||
options?: Omit<UseQueryOptions<TResult, TError, TSelectedData>, "queryKey"> & QueryNonLazyOptions,
|
||||
): [TSelectedData | undefined, RestPaginatedResult<TSelectedData, TError>]
|
||||
export function usePaginatedQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = unknown,
|
||||
TError = DefaultError,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
params: FirstParam<T>,
|
||||
options: UseQueryOptions<TResult, TError, TSelectedData> = {},
|
||||
options: Omit<UseQueryOptions<TResult, TError, TSelectedData>, "queryKey"> & QueryLazyOptions,
|
||||
): [TSelectedData | undefined, RestPaginatedResult<TSelectedData, TError>]
|
||||
export function usePaginatedQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = DefaultError,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
params: FirstParam<T>,
|
||||
options: Omit<UseQueryOptions<TResult, TError, TSelectedData>, "queryKey"> = {},
|
||||
) {
|
||||
if (typeof queryFn === "undefined") {
|
||||
throw new Error("usePaginatedQuery is missing the first argument - it must be a query function")
|
||||
}
|
||||
|
||||
const suspenseEnabled = Boolean(globalThis.__BLITZ_SUSPENSE_ENABLED)
|
||||
let enabled = isServer && suspenseEnabled ? false : options?.enabled ?? options?.enabled !== null
|
||||
let enabled = isServer ? false : options?.enabled ?? options?.enabled !== null
|
||||
let routerIsReady = false
|
||||
const router = useRouter()
|
||||
if (router) {
|
||||
routerIsReady = router?.isReady || (isServer && suspenseEnabled)
|
||||
routerIsReady = router?.isReady || isServer
|
||||
} else {
|
||||
routerIsReady = true
|
||||
}
|
||||
@@ -186,20 +253,13 @@ export function usePaginatedQuery<
|
||||
queryKey: routerIsReady ? queryKey : ["_routerNotReady_"],
|
||||
queryFn: routerIsReady
|
||||
? ({signal}) => enhancedResolverRpcClient(params, {fromQueryHook: true}, signal)
|
||||
: (emptyQueryFn as any),
|
||||
: (emptyQueryFn as PromiseReturnType<T>),
|
||||
...options,
|
||||
keepPreviousData: true,
|
||||
placeholderData: keepPreviousData,
|
||||
enabled,
|
||||
})
|
||||
|
||||
if (
|
||||
queryRest.fetchStatus === "idle" &&
|
||||
isServer &&
|
||||
suspenseEnabled !== false &&
|
||||
!data &&
|
||||
(!options || !("suspense" in options) || options.suspense) &&
|
||||
(!options || !("enabled" in options) || options.enabled)
|
||||
) {
|
||||
if (queryRest.fetchStatus === "idle" && isServer && !data) {
|
||||
const e = new NextError()
|
||||
e.name = "Rendering Suspense fallback..."
|
||||
e.digest = "DYNAMIC_SERVER_USAGE"
|
||||
@@ -223,7 +283,7 @@ export function usePaginatedQuery<
|
||||
// -------------------------
|
||||
export interface RestInfiniteResult<TResult, TError>
|
||||
extends Omit<UseInfiniteQueryResult<TResult, TError>, "data">,
|
||||
QueryCacheFunctions<TResult> {
|
||||
QueryCacheFunctions<InfiniteData<TResult>> {
|
||||
pageParams: any
|
||||
}
|
||||
|
||||
@@ -236,43 +296,43 @@ interface InfiniteQueryConfig<TResult, TError, TSelectedData>
|
||||
export function useInfiniteQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = unknown,
|
||||
TError = DefaultError,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
getQueryParams: (pageParam: any) => FirstParam<T>,
|
||||
options: InfiniteQueryConfig<TResult, TError, TSelectedData> & QueryNonLazyOptions,
|
||||
): [TSelectedData[], RestInfiniteResult<TSelectedData, TError>]
|
||||
export function useInfiniteQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = unknown,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
getQueryParams: (pageParam: any) => FirstParam<T>,
|
||||
options: InfiniteQueryConfig<TResult, TError, TSelectedData> & QueryLazyOptions,
|
||||
options: Omit<InfiniteQueryConfig<TResult, TError, TSelectedData>, "queryKey"> &
|
||||
QueryNonLazyOptions,
|
||||
): [TSelectedData[] | undefined, RestInfiniteResult<TSelectedData, TError>]
|
||||
export function useInfiniteQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = unknown,
|
||||
TError = DefaultError,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
getQueryParams: (pageParam: any) => FirstParam<T>,
|
||||
options: InfiniteQueryConfig<TResult, TError, TSelectedData>,
|
||||
options: Omit<InfiniteQueryConfig<TResult, TError, TSelectedData>, "queryKey"> & QueryLazyOptions,
|
||||
): [TSelectedData[] | undefined, RestInfiniteResult<TSelectedData, TError>]
|
||||
export function useInfiniteQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = DefaultError,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
getQueryParams: (pageParam: any) => FirstParam<T>,
|
||||
options: Omit<InfiniteQueryConfig<TResult, TError, TSelectedData>, "queryKey">,
|
||||
) {
|
||||
if (typeof queryFn === "undefined") {
|
||||
throw new Error("useInfiniteQuery is missing the first argument - it must be a query function")
|
||||
}
|
||||
|
||||
const suspenseEnabled = Boolean(globalThis.__BLITZ_SUSPENSE_ENABLED)
|
||||
let enabled = isServer && suspenseEnabled ? false : options?.enabled ?? options?.enabled !== null
|
||||
let enabled = isServer ? false : options?.enabled ?? options?.enabled !== null
|
||||
let routerIsReady = false
|
||||
const router = useRouter()
|
||||
if (router) {
|
||||
routerIsReady = router?.isReady || (isServer && suspenseEnabled)
|
||||
routerIsReady = router?.isReady || isServer
|
||||
} else {
|
||||
routerIsReady = true
|
||||
}
|
||||
@@ -292,14 +352,93 @@ export function useInfiniteQuery<
|
||||
enabled,
|
||||
})
|
||||
|
||||
if (
|
||||
queryRest.fetchStatus === "idle" &&
|
||||
isServer &&
|
||||
suspenseEnabled !== false &&
|
||||
!data &&
|
||||
(!options || !("suspense" in options) || options.suspense) &&
|
||||
(!options || !("enabled" in options) || options.enabled)
|
||||
) {
|
||||
const infiniteQueryData = data as InfiniteData<TResult>
|
||||
|
||||
const rest = {
|
||||
...queryRest,
|
||||
...getQueryCacheFunctions<FirstParam<T>, InfiniteData<TResult>, T>(queryFn, getQueryParams),
|
||||
pageParams: infiniteQueryData?.pageParams,
|
||||
}
|
||||
|
||||
return [infiniteQueryData?.pages as any, rest]
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// useInfiniteQuery
|
||||
// -------------------------
|
||||
export interface RestInfiniteResult<TResult, TError>
|
||||
extends Omit<UseInfiniteQueryResult<TResult, TError>, "data">,
|
||||
QueryCacheFunctions<InfiniteData<TResult>> {
|
||||
pageParams: any
|
||||
}
|
||||
|
||||
interface InfiniteQueryConfig<TResult, TError, TSelectedData>
|
||||
extends UseInfiniteQueryOptions<TResult, TError, TSelectedData, TResult> {
|
||||
// getPreviousPageParam?: (lastPage: TResult, allPages: TResult[]) => TGetPageParamResult
|
||||
// getNextPageParam?: (lastPage: TResult, allPages: TResult[]) => TGetPageParamResult
|
||||
}
|
||||
|
||||
export function useSuspenseInfiniteQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = DefaultError,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
getQueryParams: (pageParam: any) => FirstParam<T>,
|
||||
options: Omit<UseSuspenseInfiniteQueryOptions<TResult, TError, TSelectedData>, "queryKey"> &
|
||||
QueryNonLazyOptions,
|
||||
): [TSelectedData[], RestInfiniteResult<TSelectedData, TError>]
|
||||
export function useSuspenseInfiniteQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = DefaultError,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
getQueryParams: (pageParam: any) => FirstParam<T>,
|
||||
options: Omit<UseSuspenseInfiniteQueryOptions<TResult, TError, TSelectedData>, "queryKey"> &
|
||||
QueryLazyOptions,
|
||||
): [TSelectedData[] | undefined, RestInfiniteResult<TSelectedData, TError>]
|
||||
export function useSuspenseInfiniteQuery<
|
||||
T extends AsyncFunc,
|
||||
TResult = PromiseReturnType<T>,
|
||||
TError = DefaultError,
|
||||
TSelectedData = TResult,
|
||||
>(
|
||||
queryFn: T,
|
||||
getQueryParams: (pageParam: any) => FirstParam<T>,
|
||||
options: Omit<UseSuspenseInfiniteQueryOptions<TResult, TError, TSelectedData>, "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<TResult>
|
||||
|
||||
if (queryRest.fetchStatus === "idle" && isServer && !infiniteQueryData) {
|
||||
const e = new NextError()
|
||||
e.name = "Rendering Suspense fallback..."
|
||||
e.digest = "DYNAMIC_SERVER_USAGE"
|
||||
@@ -311,11 +450,15 @@ export function useInfiniteQuery<
|
||||
|
||||
const rest = {
|
||||
...queryRest,
|
||||
...getQueryCacheFunctions<FirstParam<T>, TResult, T>(queryFn, getQueryParams),
|
||||
pageParams: data?.pageParams,
|
||||
...getQueryCacheFunctions<FirstParam<T>, InfiniteData<TResult>, T>(
|
||||
queryFn,
|
||||
getQueryParams,
|
||||
QueryType.INFINITE,
|
||||
),
|
||||
pageParams: infiniteQueryData?.pageParams,
|
||||
}
|
||||
|
||||
return [data?.pages as any, rest]
|
||||
return [infiniteQueryData?.pages as unknown, rest]
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
@@ -352,7 +495,7 @@ export declare type MutationFunction<TData, TVariables = unknown> = (
|
||||
|
||||
export function useMutation<
|
||||
TData = unknown,
|
||||
TError = unknown,
|
||||
TError = DefaultError,
|
||||
TVariables = void,
|
||||
TContext = unknown,
|
||||
>(
|
||||
@@ -362,11 +505,11 @@ export function useMutation<
|
||||
const enhancedResolverRpcClient = sanitizeMutation(mutationResolver)
|
||||
|
||||
const {mutate, mutateAsync, ...rest} = useReactQueryMutation<TData, TError, TVariables, TContext>(
|
||||
(variables) => enhancedResolverRpcClient(variables, {fromQueryHook: true}),
|
||||
{
|
||||
mutationFn: (variables) => enhancedResolverRpcClient(variables, {fromQueryHook: true}),
|
||||
throwOnError: true,
|
||||
...config,
|
||||
} as any,
|
||||
},
|
||||
)
|
||||
|
||||
return [mutateAsync, rest] as MutationResultPair<TData, TError, TVariables, TContext>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user