Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions e2e/react-start/server-functions/src/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { Route as IndexRouteImport } from './routes/index'
import { Route as MiddlewareIndexRouteImport } from './routes/middleware/index'
import { Route as FormdataRedirectIndexRouteImport } from './routes/formdata-redirect/index'
import { Route as CookiesIndexRouteImport } from './routes/cookies/index'
import { Route as MiddlewareRetryNextRouteImport } from './routes/middleware/retry-next'
import { Route as MiddlewareClientMiddlewareRouterRouteImport } from './routes/middleware/client-middleware-router'
import { Route as CookiesSetRouteImport } from './routes/cookies/set'
import { Route as FormdataRedirectTargetNameRouteImport } from './routes/formdata-redirect/target.$name'
Expand Down Expand Up @@ -109,6 +110,11 @@ const CookiesIndexRoute = CookiesIndexRouteImport.update({
path: '/cookies/',
getParentRoute: () => rootRouteImport,
} as any)
const MiddlewareRetryNextRoute = MiddlewareRetryNextRouteImport.update({
id: '/middleware/retry-next',
path: '/middleware/retry-next',
getParentRoute: () => rootRouteImport,
} as any)
const MiddlewareClientMiddlewareRouterRoute =
MiddlewareClientMiddlewareRouterRouteImport.update({
id: '/middleware/client-middleware-router',
Expand Down Expand Up @@ -143,6 +149,7 @@ export interface FileRoutesByFullPath {
'/submit-post-formdata': typeof SubmitPostFormdataRoute
'/cookies/set': typeof CookiesSetRoute
'/middleware/client-middleware-router': typeof MiddlewareClientMiddlewareRouterRoute
'/middleware/retry-next': typeof MiddlewareRetryNextRoute
'/cookies': typeof CookiesIndexRoute
'/formdata-redirect': typeof FormdataRedirectIndexRoute
'/middleware': typeof MiddlewareIndexRoute
Expand All @@ -164,6 +171,7 @@ export interface FileRoutesByTo {
'/submit-post-formdata': typeof SubmitPostFormdataRoute
'/cookies/set': typeof CookiesSetRoute
'/middleware/client-middleware-router': typeof MiddlewareClientMiddlewareRouterRoute
'/middleware/retry-next': typeof MiddlewareRetryNextRoute
'/cookies': typeof CookiesIndexRoute
'/formdata-redirect': typeof FormdataRedirectIndexRoute
'/middleware': typeof MiddlewareIndexRoute
Expand All @@ -186,6 +194,7 @@ export interface FileRoutesById {
'/submit-post-formdata': typeof SubmitPostFormdataRoute
'/cookies/set': typeof CookiesSetRoute
'/middleware/client-middleware-router': typeof MiddlewareClientMiddlewareRouterRoute
'/middleware/retry-next': typeof MiddlewareRetryNextRoute
'/cookies/': typeof CookiesIndexRoute
'/formdata-redirect/': typeof FormdataRedirectIndexRoute
'/middleware/': typeof MiddlewareIndexRoute
Expand All @@ -209,6 +218,7 @@ export interface FileRouteTypes {
| '/submit-post-formdata'
| '/cookies/set'
| '/middleware/client-middleware-router'
| '/middleware/retry-next'
| '/cookies'
| '/formdata-redirect'
| '/middleware'
Expand All @@ -230,6 +240,7 @@ export interface FileRouteTypes {
| '/submit-post-formdata'
| '/cookies/set'
| '/middleware/client-middleware-router'
| '/middleware/retry-next'
| '/cookies'
| '/formdata-redirect'
| '/middleware'
Expand All @@ -251,6 +262,7 @@ export interface FileRouteTypes {
| '/submit-post-formdata'
| '/cookies/set'
| '/middleware/client-middleware-router'
| '/middleware/retry-next'
| '/cookies/'
| '/formdata-redirect/'
| '/middleware/'
Expand All @@ -273,6 +285,7 @@ export interface RootRouteChildren {
SubmitPostFormdataRoute: typeof SubmitPostFormdataRoute
CookiesSetRoute: typeof CookiesSetRoute
MiddlewareClientMiddlewareRouterRoute: typeof MiddlewareClientMiddlewareRouterRoute
MiddlewareRetryNextRoute: typeof MiddlewareRetryNextRoute
CookiesIndexRoute: typeof CookiesIndexRoute
FormdataRedirectIndexRoute: typeof FormdataRedirectIndexRoute
MiddlewareIndexRoute: typeof MiddlewareIndexRoute
Expand Down Expand Up @@ -393,6 +406,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof CookiesIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/middleware/retry-next': {
id: '/middleware/retry-next'
path: '/middleware/retry-next'
fullPath: '/middleware/retry-next'
preLoaderRoute: typeof MiddlewareRetryNextRouteImport
parentRoute: typeof rootRouteImport
}
'/middleware/client-middleware-router': {
id: '/middleware/client-middleware-router'
path: '/middleware/client-middleware-router'
Expand Down Expand Up @@ -433,6 +453,7 @@ const rootRouteChildren: RootRouteChildren = {
SubmitPostFormdataRoute: SubmitPostFormdataRoute,
CookiesSetRoute: CookiesSetRoute,
MiddlewareClientMiddlewareRouterRoute: MiddlewareClientMiddlewareRouterRoute,
MiddlewareRetryNextRoute: MiddlewareRetryNextRoute,
CookiesIndexRoute: CookiesIndexRoute,
FormdataRedirectIndexRoute: FormdataRedirectIndexRoute,
MiddlewareIndexRoute: MiddlewareIndexRoute,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ function RouteComponent() {
Client Middleware has access to router instance
</Route.Link>
</li>
<li>
<Route.Link to="./retry-next" data-testid="retry-next-link">
Middleware can call next() multiple times
</Route.Link>
</li>
</ul>
</div>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { createFileRoute } from '@tanstack/react-router'
import { createMiddleware, createServerFn } from '@tanstack/react-start'

const retryMiddleware = createMiddleware({ type: 'function' })
.client(async ({ next }) => {
const res = await next({ sendContext: { count: 0 } })
// @ts-expect-error: private property
const count = res.result
return await next({ sendContext: { count } })
})
.server(async ({ next, context: { count } }) => {
const res = await next({ context: { count } })
// @ts-expect-error: private property
const nextCount = res.result
return await next({ context: { count: nextCount } })
})

const serverFn = createServerFn()
.middleware([retryMiddleware])
.handler(({ context: { count } }) => {
return count + 1
})

export const Route = createFileRoute('/middleware/retry-next')({
component: RouteComponent,
loader: async () => ({ serverFnLoaderResult: await serverFn() }),
})

function RouteComponent() {
const { serverFnLoaderResult } = Route.useLoaderData()
return (
<div className="p-2 m-2 grid gap-2" data-testid="retry-next-component">
<h3>Server Function Middleware Retry Test</h3>
<p>
This component tests that server function middleware can call next()
multiple times for retry logic.
</p>
<div data-testid="retry-success-result">
<pre>called {serverFnLoaderResult} times</pre>
</div>
</div>
)
}
20 changes: 20 additions & 0 deletions e2e/react-start/server-functions/tests/server-functions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,4 +371,24 @@ test.describe('middleware', () => {
await runTest(page)
})
})

test.describe('middleware can call next() multiple times', () => {
async function runRetryTest(page: Page) {
await page.waitForLoadState('networkidle')
await expect(page.getByTestId('retry-success-result')).toContainText(
'called 4 times',
)
}

test('direct visit', async ({ page }) => {
await page.goto('/middleware/retry-next')
await runRetryTest(page)
})

test('client navigation', async ({ page }) => {
await page.goto('/middleware')
await page.getByTestId('retry-next-link').click()
await runRetryTest(page)
})
})
})