diff --git a/e2e/react-start/basic-react-query/package.json b/e2e/react-start/basic-react-query/package.json index 35a1a56c513..18cccdaece9 100644 --- a/e2e/react-start/basic-react-query/package.json +++ b/e2e/react-start/basic-react-query/package.json @@ -34,7 +34,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite-tsconfig-paths": "^5.1.4" diff --git a/e2e/react-start/basic-tsr-config/package.json b/e2e/react-start/basic-tsr-config/package.json index 05feaa329b6..f6b15fd80f7 100644 --- a/e2e/react-start/basic-tsr-config/package.json +++ b/e2e/react-start/basic-tsr-config/package.json @@ -22,7 +22,7 @@ "@types/node": "^22.10.2", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "typescript": "^5.7.2" } } diff --git a/e2e/react-start/basic/package.json b/e2e/react-start/basic/package.json index e7d202cc16e..645683c342c 100644 --- a/e2e/react-start/basic/package.json +++ b/e2e/react-start/basic/package.json @@ -43,7 +43,7 @@ "@vitejs/plugin-react": "^4.3.4", "combinate": "^1.1.11", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite": "^7.1.7", diff --git a/e2e/react-start/custom-basepath/package.json b/e2e/react-start/custom-basepath/package.json index 24ee0f7abb5..5420b654a46 100644 --- a/e2e/react-start/custom-basepath/package.json +++ b/e2e/react-start/custom-basepath/package.json @@ -30,7 +30,7 @@ "@vitejs/plugin-react": "^4.3.4", "cross-env": "^10.0.0", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "tsx": "^4.20.3", "typescript": "^5.7.2", diff --git a/e2e/react-start/scroll-restoration/package.json b/e2e/react-start/scroll-restoration/package.json index e363e7ec1bd..9fe23757a7c 100644 --- a/e2e/react-start/scroll-restoration/package.json +++ b/e2e/react-start/scroll-restoration/package.json @@ -33,7 +33,7 @@ "@vitejs/plugin-react": "^4.3.4", "combinate": "^1.1.11", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite-tsconfig-paths": "^5.1.4" diff --git a/e2e/react-start/selective-ssr/package.json b/e2e/react-start/selective-ssr/package.json index 0fae143cf6b..03d2a9b9d54 100644 --- a/e2e/react-start/selective-ssr/package.json +++ b/e2e/react-start/selective-ssr/package.json @@ -29,7 +29,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2" } diff --git a/e2e/react-start/serialization-adapters/package.json b/e2e/react-start/serialization-adapters/package.json index cd50c663b5c..71b57e68bfb 100644 --- a/e2e/react-start/serialization-adapters/package.json +++ b/e2e/react-start/serialization-adapters/package.json @@ -29,7 +29,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2" } diff --git a/e2e/react-start/server-functions/package.json b/e2e/react-start/server-functions/package.json index e00d47bd0f3..5da5526e4d8 100644 --- a/e2e/react-start/server-functions/package.json +++ b/e2e/react-start/server-functions/package.json @@ -36,7 +36,7 @@ "@vitejs/plugin-react": "^4.3.4", "combinate": "^1.1.11", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite-tsconfig-paths": "^5.1.4" diff --git a/e2e/react-start/server-functions/src/routeTree.gen.ts b/e2e/react-start/server-functions/src/routeTree.gen.ts index 51327cb8164..d30a27f37c0 100644 --- a/e2e/react-start/server-functions/src/routeTree.gen.ts +++ b/e2e/react-start/server-functions/src/routeTree.gen.ts @@ -21,7 +21,6 @@ import { Route as FormdataContextRouteImport } from './routes/formdata-context' import { Route as EnvOnlyRouteImport } from './routes/env-only' import { Route as DeadCodePreserveRouteImport } from './routes/dead-code-preserve' import { Route as ConsistentRouteImport } from './routes/consistent' -import { Route as AbortSignalRouteImport } from './routes/abort-signal' import { Route as IndexRouteImport } from './routes/index' import { Route as RedirectTestIndexRouteImport } from './routes/redirect-test/index' import { Route as RedirectTestSsrIndexRouteImport } from './routes/redirect-test-ssr/index' @@ -30,12 +29,14 @@ import { Route as MiddlewareIndexRouteImport } from './routes/middleware/index' import { Route as FormdataRedirectIndexRouteImport } from './routes/formdata-redirect/index' import { Route as FactoryIndexRouteImport } from './routes/factory/index' import { Route as CookiesIndexRouteImport } from './routes/cookies/index' +import { Route as AbortSignalIndexRouteImport } from './routes/abort-signal/index' import { Route as RedirectTestTargetRouteImport } from './routes/redirect-test/target' import { Route as RedirectTestSsrTargetRouteImport } from './routes/redirect-test-ssr/target' import { Route as MiddlewareSendServerFnRouteImport } from './routes/middleware/send-serverFn' import { Route as MiddlewareRequestMiddlewareRouteImport } from './routes/middleware/request-middleware' import { Route as MiddlewareClientMiddlewareRouterRouteImport } from './routes/middleware/client-middleware-router' import { Route as CookiesSetRouteImport } from './routes/cookies/set' +import { Route as AbortSignalMethodRouteImport } from './routes/abort-signal/$method' import { Route as FormdataRedirectTargetNameRouteImport } from './routes/formdata-redirect/target.$name' const SubmitPostFormdataRoute = SubmitPostFormdataRouteImport.update({ @@ -98,11 +99,6 @@ const ConsistentRoute = ConsistentRouteImport.update({ path: '/consistent', getParentRoute: () => rootRouteImport, } as any) -const AbortSignalRoute = AbortSignalRouteImport.update({ - id: '/abort-signal', - path: '/abort-signal', - getParentRoute: () => rootRouteImport, -} as any) const IndexRoute = IndexRouteImport.update({ id: '/', path: '/', @@ -143,6 +139,11 @@ const CookiesIndexRoute = CookiesIndexRouteImport.update({ path: '/cookies/', getParentRoute: () => rootRouteImport, } as any) +const AbortSignalIndexRoute = AbortSignalIndexRouteImport.update({ + id: '/abort-signal/', + path: '/abort-signal/', + getParentRoute: () => rootRouteImport, +} as any) const RedirectTestTargetRoute = RedirectTestTargetRouteImport.update({ id: '/redirect-test/target', path: '/redirect-test/target', @@ -175,6 +176,11 @@ const CookiesSetRoute = CookiesSetRouteImport.update({ path: '/cookies/set', getParentRoute: () => rootRouteImport, } as any) +const AbortSignalMethodRoute = AbortSignalMethodRouteImport.update({ + id: '/abort-signal/$method', + path: '/abort-signal/$method', + getParentRoute: () => rootRouteImport, +} as any) const FormdataRedirectTargetNameRoute = FormdataRedirectTargetNameRouteImport.update({ id: '/formdata-redirect/target/$name', @@ -184,7 +190,6 @@ const FormdataRedirectTargetNameRoute = export interface FileRoutesByFullPath { '/': typeof IndexRoute - '/abort-signal': typeof AbortSignalRoute '/consistent': typeof ConsistentRoute '/dead-code-preserve': typeof DeadCodePreserveRoute '/env-only': typeof EnvOnlyRoute @@ -197,12 +202,14 @@ export interface FileRoutesByFullPath { '/serialize-form-data': typeof SerializeFormDataRoute '/status': typeof StatusRoute '/submit-post-formdata': typeof SubmitPostFormdataRoute + '/abort-signal/$method': typeof AbortSignalMethodRoute '/cookies/set': typeof CookiesSetRoute '/middleware/client-middleware-router': typeof MiddlewareClientMiddlewareRouterRoute '/middleware/request-middleware': typeof MiddlewareRequestMiddlewareRoute '/middleware/send-serverFn': typeof MiddlewareSendServerFnRoute '/redirect-test-ssr/target': typeof RedirectTestSsrTargetRoute '/redirect-test/target': typeof RedirectTestTargetRoute + '/abort-signal': typeof AbortSignalIndexRoute '/cookies': typeof CookiesIndexRoute '/factory': typeof FactoryIndexRoute '/formdata-redirect': typeof FormdataRedirectIndexRoute @@ -214,7 +221,6 @@ export interface FileRoutesByFullPath { } export interface FileRoutesByTo { '/': typeof IndexRoute - '/abort-signal': typeof AbortSignalRoute '/consistent': typeof ConsistentRoute '/dead-code-preserve': typeof DeadCodePreserveRoute '/env-only': typeof EnvOnlyRoute @@ -227,12 +233,14 @@ export interface FileRoutesByTo { '/serialize-form-data': typeof SerializeFormDataRoute '/status': typeof StatusRoute '/submit-post-formdata': typeof SubmitPostFormdataRoute + '/abort-signal/$method': typeof AbortSignalMethodRoute '/cookies/set': typeof CookiesSetRoute '/middleware/client-middleware-router': typeof MiddlewareClientMiddlewareRouterRoute '/middleware/request-middleware': typeof MiddlewareRequestMiddlewareRoute '/middleware/send-serverFn': typeof MiddlewareSendServerFnRoute '/redirect-test-ssr/target': typeof RedirectTestSsrTargetRoute '/redirect-test/target': typeof RedirectTestTargetRoute + '/abort-signal': typeof AbortSignalIndexRoute '/cookies': typeof CookiesIndexRoute '/factory': typeof FactoryIndexRoute '/formdata-redirect': typeof FormdataRedirectIndexRoute @@ -245,7 +253,6 @@ export interface FileRoutesByTo { export interface FileRoutesById { __root__: typeof rootRouteImport '/': typeof IndexRoute - '/abort-signal': typeof AbortSignalRoute '/consistent': typeof ConsistentRoute '/dead-code-preserve': typeof DeadCodePreserveRoute '/env-only': typeof EnvOnlyRoute @@ -258,12 +265,14 @@ export interface FileRoutesById { '/serialize-form-data': typeof SerializeFormDataRoute '/status': typeof StatusRoute '/submit-post-formdata': typeof SubmitPostFormdataRoute + '/abort-signal/$method': typeof AbortSignalMethodRoute '/cookies/set': typeof CookiesSetRoute '/middleware/client-middleware-router': typeof MiddlewareClientMiddlewareRouterRoute '/middleware/request-middleware': typeof MiddlewareRequestMiddlewareRoute '/middleware/send-serverFn': typeof MiddlewareSendServerFnRoute '/redirect-test-ssr/target': typeof RedirectTestSsrTargetRoute '/redirect-test/target': typeof RedirectTestTargetRoute + '/abort-signal/': typeof AbortSignalIndexRoute '/cookies/': typeof CookiesIndexRoute '/factory/': typeof FactoryIndexRoute '/formdata-redirect/': typeof FormdataRedirectIndexRoute @@ -277,7 +286,6 @@ export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath fullPaths: | '/' - | '/abort-signal' | '/consistent' | '/dead-code-preserve' | '/env-only' @@ -290,12 +298,14 @@ export interface FileRouteTypes { | '/serialize-form-data' | '/status' | '/submit-post-formdata' + | '/abort-signal/$method' | '/cookies/set' | '/middleware/client-middleware-router' | '/middleware/request-middleware' | '/middleware/send-serverFn' | '/redirect-test-ssr/target' | '/redirect-test/target' + | '/abort-signal' | '/cookies' | '/factory' | '/formdata-redirect' @@ -307,7 +317,6 @@ export interface FileRouteTypes { fileRoutesByTo: FileRoutesByTo to: | '/' - | '/abort-signal' | '/consistent' | '/dead-code-preserve' | '/env-only' @@ -320,12 +329,14 @@ export interface FileRouteTypes { | '/serialize-form-data' | '/status' | '/submit-post-formdata' + | '/abort-signal/$method' | '/cookies/set' | '/middleware/client-middleware-router' | '/middleware/request-middleware' | '/middleware/send-serverFn' | '/redirect-test-ssr/target' | '/redirect-test/target' + | '/abort-signal' | '/cookies' | '/factory' | '/formdata-redirect' @@ -337,7 +348,6 @@ export interface FileRouteTypes { id: | '__root__' | '/' - | '/abort-signal' | '/consistent' | '/dead-code-preserve' | '/env-only' @@ -350,12 +360,14 @@ export interface FileRouteTypes { | '/serialize-form-data' | '/status' | '/submit-post-formdata' + | '/abort-signal/$method' | '/cookies/set' | '/middleware/client-middleware-router' | '/middleware/request-middleware' | '/middleware/send-serverFn' | '/redirect-test-ssr/target' | '/redirect-test/target' + | '/abort-signal/' | '/cookies/' | '/factory/' | '/formdata-redirect/' @@ -368,7 +380,6 @@ export interface FileRouteTypes { } export interface RootRouteChildren { IndexRoute: typeof IndexRoute - AbortSignalRoute: typeof AbortSignalRoute ConsistentRoute: typeof ConsistentRoute DeadCodePreserveRoute: typeof DeadCodePreserveRoute EnvOnlyRoute: typeof EnvOnlyRoute @@ -381,12 +392,14 @@ export interface RootRouteChildren { SerializeFormDataRoute: typeof SerializeFormDataRoute StatusRoute: typeof StatusRoute SubmitPostFormdataRoute: typeof SubmitPostFormdataRoute + AbortSignalMethodRoute: typeof AbortSignalMethodRoute CookiesSetRoute: typeof CookiesSetRoute MiddlewareClientMiddlewareRouterRoute: typeof MiddlewareClientMiddlewareRouterRoute MiddlewareRequestMiddlewareRoute: typeof MiddlewareRequestMiddlewareRoute MiddlewareSendServerFnRoute: typeof MiddlewareSendServerFnRoute RedirectTestSsrTargetRoute: typeof RedirectTestSsrTargetRoute RedirectTestTargetRoute: typeof RedirectTestTargetRoute + AbortSignalIndexRoute: typeof AbortSignalIndexRoute CookiesIndexRoute: typeof CookiesIndexRoute FactoryIndexRoute: typeof FactoryIndexRoute FormdataRedirectIndexRoute: typeof FormdataRedirectIndexRoute @@ -483,13 +496,6 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof ConsistentRouteImport parentRoute: typeof rootRouteImport } - '/abort-signal': { - id: '/abort-signal' - path: '/abort-signal' - fullPath: '/abort-signal' - preLoaderRoute: typeof AbortSignalRouteImport - parentRoute: typeof rootRouteImport - } '/': { id: '/' path: '/' @@ -546,6 +552,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof CookiesIndexRouteImport parentRoute: typeof rootRouteImport } + '/abort-signal/': { + id: '/abort-signal/' + path: '/abort-signal' + fullPath: '/abort-signal' + preLoaderRoute: typeof AbortSignalIndexRouteImport + parentRoute: typeof rootRouteImport + } '/redirect-test/target': { id: '/redirect-test/target' path: '/redirect-test/target' @@ -588,6 +601,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof CookiesSetRouteImport parentRoute: typeof rootRouteImport } + '/abort-signal/$method': { + id: '/abort-signal/$method' + path: '/abort-signal/$method' + fullPath: '/abort-signal/$method' + preLoaderRoute: typeof AbortSignalMethodRouteImport + parentRoute: typeof rootRouteImport + } '/formdata-redirect/target/$name': { id: '/formdata-redirect/target/$name' path: '/formdata-redirect/target/$name' @@ -600,7 +620,6 @@ declare module '@tanstack/react-router' { const rootRouteChildren: RootRouteChildren = { IndexRoute: IndexRoute, - AbortSignalRoute: AbortSignalRoute, ConsistentRoute: ConsistentRoute, DeadCodePreserveRoute: DeadCodePreserveRoute, EnvOnlyRoute: EnvOnlyRoute, @@ -613,12 +632,14 @@ const rootRouteChildren: RootRouteChildren = { SerializeFormDataRoute: SerializeFormDataRoute, StatusRoute: StatusRoute, SubmitPostFormdataRoute: SubmitPostFormdataRoute, + AbortSignalMethodRoute: AbortSignalMethodRoute, CookiesSetRoute: CookiesSetRoute, MiddlewareClientMiddlewareRouterRoute: MiddlewareClientMiddlewareRouterRoute, MiddlewareRequestMiddlewareRoute: MiddlewareRequestMiddlewareRoute, MiddlewareSendServerFnRoute: MiddlewareSendServerFnRoute, RedirectTestSsrTargetRoute: RedirectTestSsrTargetRoute, RedirectTestTargetRoute: RedirectTestTargetRoute, + AbortSignalIndexRoute: AbortSignalIndexRoute, CookiesIndexRoute: CookiesIndexRoute, FactoryIndexRoute: FactoryIndexRoute, FormdataRedirectIndexRoute: FormdataRedirectIndexRoute, diff --git a/e2e/react-start/server-functions/src/routes/abort-signal.tsx b/e2e/react-start/server-functions/src/routes/abort-signal/$method.tsx similarity index 60% rename from e2e/react-start/server-functions/src/routes/abort-signal.tsx rename to e2e/react-start/server-functions/src/routes/abort-signal/$method.tsx index 7de90f3143a..7f7397a5ced 100644 --- a/e2e/react-start/server-functions/src/routes/abort-signal.tsx +++ b/e2e/react-start/server-functions/src/routes/abort-signal/$method.tsx @@ -1,33 +1,45 @@ import { createFileRoute } from '@tanstack/react-router' import { createServerFn } from '@tanstack/react-start' import React from 'react' +import z from 'zod' -export const Route = createFileRoute('/abort-signal')({ +export const Route = createFileRoute('/abort-signal/$method')({ + params: z.object({ + method: z.union([z.literal('GET'), z.literal('POST')]), + }), component: RouteComponent, }) -const abortableServerFn = createServerFn().handler( - async ({ context, signal }) => { - console.log('server function started', { context, signal }) - return new Promise((resolve, reject) => { - if (signal.aborted) { - return reject(new Error('Aborted before start')) - } - const timerId = setTimeout(() => { - console.log('server function finished') - resolve('server function result') - }, 1000) - const onAbort = () => { - clearTimeout(timerId) - console.log('server function aborted') - reject(new Error('Aborted')) - } - signal.addEventListener('abort', onAbort, { once: true }) - }) - }, +function serverFnImpl(signal: AbortSignal) { + console.log('server function started', { signal }) + return new Promise((resolve, reject) => { + if (signal.aborted) { + return reject(new Error('Aborted before start')) + } + const timerId = setTimeout(() => { + console.log('server function finished') + resolve('server function result') + }, 1000) + const onAbort = () => { + clearTimeout(timerId) + console.log('server function aborted') + reject(new Error('Aborted')) + } + signal.addEventListener('abort', onAbort, { once: true }) + }) +} +const abortableServerFnGET = createServerFn().handler(async ({ signal }) => + serverFnImpl(signal), +) + +const abortableServerFnPOST = createServerFn({ method: 'POST' }).handler( + async ({ signal }) => serverFnImpl(signal), ) function RouteComponent() { + const method = Route.useParams().method + const abortableServerFn = + method === 'GET' ? abortableServerFnGET : abortableServerFnPOST const [errorMessage, setErrorMessage] = React.useState( undefined, ) diff --git a/e2e/react-start/server-functions/src/routes/abort-signal/index.tsx b/e2e/react-start/server-functions/src/routes/abort-signal/index.tsx new file mode 100644 index 00000000000..00835dbc203 --- /dev/null +++ b/e2e/react-start/server-functions/src/routes/abort-signal/index.tsx @@ -0,0 +1,27 @@ +import { Link, createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/abort-signal/')({ + component: Home, +}) + +function Home() { + return ( +
+

+ Server functions E2E Abort Signal Tests +

+
    +
  • + + Abortable server function call with GET + +
  • +
  • + + Abortable server function call with POST + +
  • +
+
+ ) +} diff --git a/e2e/react-start/server-functions/tests/server-functions.spec.ts b/e2e/react-start/server-functions/tests/server-functions.spec.ts index b384be2ea6f..208ef2519bc 100644 --- a/e2e/react-start/server-functions/tests/server-functions.spec.ts +++ b/e2e/react-start/server-functions/tests/server-functions.spec.ts @@ -320,48 +320,50 @@ test.describe('server function sets cookies', () => { await runCookieTest(page, expectedCookieValue) }) }) +;['GET', 'POST'].forEach((method) => { + test.describe(`aborting a server function call: method ${method}`, () => { + test('without aborting', async ({ page }) => { + await page.goto('/abort-signal/' + method) -test.describe('aborting a server function call', () => { - test('without aborting', async ({ page }) => { - await page.goto('/abort-signal') - - await page.waitForLoadState('networkidle') - - await page.getByTestId('run-without-abort-btn').click() - await page.waitForLoadState('networkidle') - await page.waitForSelector( - '[data-testid="result"]:has-text("server function result")', - ) - await page.waitForSelector( - '[data-testid="errorMessage"]:has-text("$undefined")', - ) + await page.waitForLoadState('networkidle') - const result = (await page.getByTestId('result').textContent()) || '' - expect(result).toBe('server function result') + await page.getByTestId('run-without-abort-btn').click() + await page.waitForLoadState('networkidle') + await page.waitForSelector( + '[data-testid="result"]:has-text("server function result")', + ) + await page.waitForSelector( + '[data-testid="errorMessage"]:has-text("$undefined")', + ) - const errorMessage = - (await page.getByTestId('errorMessage').textContent()) || '' - expect(errorMessage).toBe('$undefined') - }) + const result = (await page.getByTestId('result').textContent()) || '' + expect(result).toBe('server function result') - test('aborting', async ({ page }) => { - await page.goto('/abort-signal') + const errorMessage = + (await page.getByTestId('errorMessage').textContent()) || '' + expect(errorMessage).toBe('$undefined') + }) - await page.waitForLoadState('networkidle') + test('aborting', async ({ page }) => { + await page.goto('/abort-signal/' + method) + await page.waitForLoadState('networkidle') - await page.getByTestId('run-with-abort-btn').click() - await page.waitForLoadState('networkidle') - await page.waitForSelector('[data-testid="result"]:has-text("$undefined")') - await page.waitForSelector( - '[data-testid="errorMessage"]:has-text("aborted")', - ) + await page.getByTestId('run-with-abort-btn').click() + await page.waitForLoadState('networkidle') + await page.waitForSelector( + '[data-testid="result"]:has-text("$undefined")', + ) + await page.waitForSelector( + '[data-testid="errorMessage"]:has-text("aborted")', + ) - const result = (await page.getByTestId('result').textContent()) || '' - expect(result).toBe('$undefined') + const result = (await page.getByTestId('result').textContent()) || '' + expect(result).toBe('$undefined') - const errorMessage = - (await page.getByTestId('errorMessage').textContent()) || '' - expect(errorMessage).toContain('abort') + const errorMessage = + (await page.getByTestId('errorMessage').textContent()) || '' + expect(errorMessage).toContain('abort') + }) }) }) diff --git a/e2e/react-start/server-routes/package.json b/e2e/react-start/server-routes/package.json index 48f64bc156e..6758af3d5fe 100644 --- a/e2e/react-start/server-routes/package.json +++ b/e2e/react-start/server-routes/package.json @@ -36,7 +36,7 @@ "@vitejs/plugin-react": "^4.3.4", "combinate": "^1.1.11", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite-tsconfig-paths": "^5.1.4" diff --git a/e2e/react-start/virtual-routes/package.json b/e2e/react-start/virtual-routes/package.json index f4e89995022..51fac4f99e7 100644 --- a/e2e/react-start/virtual-routes/package.json +++ b/e2e/react-start/virtual-routes/package.json @@ -33,7 +33,7 @@ "@vitejs/plugin-react": "^4.3.4", "combinate": "^1.1.11", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite-tsconfig-paths": "^5.1.4" diff --git a/e2e/react-start/website/package.json b/e2e/react-start/website/package.json index 89d19b705f3..ba24f0b6060 100644 --- a/e2e/react-start/website/package.json +++ b/e2e/react-start/website/package.json @@ -30,7 +30,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite": "^7.1.7", diff --git a/e2e/solid-start/basic-solid-query/package.json b/e2e/solid-start/basic-solid-query/package.json index faa08273ba6..bb280ca8282 100644 --- a/e2e/solid-start/basic-solid-query/package.json +++ b/e2e/solid-start/basic-solid-query/package.json @@ -30,7 +30,7 @@ "@tanstack/router-e2e-utils": "workspace:^", "@types/node": "^22.10.2", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite-plugin-solid": "^2.11.10", diff --git a/e2e/solid-start/basic-solid-query/test-results/.last-run.json b/e2e/solid-start/basic-solid-query/test-results/.last-run.json new file mode 100644 index 00000000000..cbcc1fbac11 --- /dev/null +++ b/e2e/solid-start/basic-solid-query/test-results/.last-run.json @@ -0,0 +1,4 @@ +{ + "status": "passed", + "failedTests": [] +} \ No newline at end of file diff --git a/e2e/solid-start/basic-tsr-config/package.json b/e2e/solid-start/basic-tsr-config/package.json index 5203eaf94f2..ab818975c51 100644 --- a/e2e/solid-start/basic-tsr-config/package.json +++ b/e2e/solid-start/basic-tsr-config/package.json @@ -20,7 +20,7 @@ "devDependencies": { "@tanstack/router-e2e-utils": "workspace:^", "@types/node": "^22.10.2", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "typescript": "^5.7.2", "vite-plugin-solid": "^2.11.10", "vite-tsconfig-paths": "^5.1.4" diff --git a/e2e/solid-start/basic/package.json b/e2e/solid-start/basic/package.json index 43c97517b48..e72831c6a2d 100644 --- a/e2e/solid-start/basic/package.json +++ b/e2e/solid-start/basic/package.json @@ -41,7 +41,7 @@ "@types/node": "^22.10.2", "combinate": "^1.1.11", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite-plugin-solid": "^2.11.10", diff --git a/e2e/solid-start/custom-basepath/package.json b/e2e/solid-start/custom-basepath/package.json index 5086871b014..91a13eb970f 100644 --- a/e2e/solid-start/custom-basepath/package.json +++ b/e2e/solid-start/custom-basepath/package.json @@ -26,7 +26,7 @@ "@types/node": "^22.10.2", "cross-env": "^10.0.0", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "tsx": "^4.20.3", "typescript": "^5.7.2", diff --git a/e2e/solid-start/query-integration/test-results/.last-run.json b/e2e/solid-start/query-integration/test-results/.last-run.json new file mode 100644 index 00000000000..cbcc1fbac11 --- /dev/null +++ b/e2e/solid-start/query-integration/test-results/.last-run.json @@ -0,0 +1,4 @@ +{ + "status": "passed", + "failedTests": [] +} \ No newline at end of file diff --git a/e2e/solid-start/scroll-restoration/package.json b/e2e/solid-start/scroll-restoration/package.json index a7059586535..e2f56b2ca48 100644 --- a/e2e/solid-start/scroll-restoration/package.json +++ b/e2e/solid-start/scroll-restoration/package.json @@ -29,7 +29,7 @@ "@types/node": "^22.10.2", "combinate": "^1.1.11", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite-plugin-solid": "^2.11.10", diff --git a/e2e/solid-start/selective-ssr/package.json b/e2e/solid-start/selective-ssr/package.json index 7351471c4f0..1df54698281 100644 --- a/e2e/solid-start/selective-ssr/package.json +++ b/e2e/solid-start/selective-ssr/package.json @@ -21,7 +21,7 @@ "@tailwindcss/postcss": "^4.1.15", "@tanstack/router-e2e-utils": "workspace:^", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite": "^7.1.7", diff --git a/e2e/solid-start/serialization-adapters/package.json b/e2e/solid-start/serialization-adapters/package.json index 92dd4b266a6..449fe04493d 100644 --- a/e2e/solid-start/serialization-adapters/package.json +++ b/e2e/solid-start/serialization-adapters/package.json @@ -25,7 +25,7 @@ "@tanstack/router-e2e-utils": "workspace:^", "@types/node": "^22.10.2", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite-plugin-solid": "^2.11.9" diff --git a/e2e/solid-start/server-functions/package.json b/e2e/solid-start/server-functions/package.json index ad522371aa5..ee5de6fbba0 100644 --- a/e2e/solid-start/server-functions/package.json +++ b/e2e/solid-start/server-functions/package.json @@ -32,7 +32,7 @@ "@types/node": "^22.10.2", "combinate": "^1.1.11", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite-plugin-solid": "^2.11.10", diff --git a/e2e/solid-start/server-functions/src/routeTree.gen.ts b/e2e/solid-start/server-functions/src/routeTree.gen.ts index 5dfcad06648..10057c52b04 100644 --- a/e2e/solid-start/server-functions/src/routeTree.gen.ts +++ b/e2e/solid-start/server-functions/src/routeTree.gen.ts @@ -20,7 +20,6 @@ import { Route as HeadersRouteImport } from './routes/headers' import { Route as EnvOnlyRouteImport } from './routes/env-only' import { Route as DeadCodePreserveRouteImport } from './routes/dead-code-preserve' import { Route as ConsistentRouteImport } from './routes/consistent' -import { Route as AbortSignalRouteImport } from './routes/abort-signal' import { Route as IndexRouteImport } from './routes/index' import { Route as RedirectTestIndexRouteImport } from './routes/redirect-test/index' import { Route as RedirectTestSsrIndexRouteImport } from './routes/redirect-test-ssr/index' @@ -29,12 +28,14 @@ import { Route as MiddlewareIndexRouteImport } from './routes/middleware/index' import { Route as FormdataRedirectIndexRouteImport } from './routes/formdata-redirect/index' import { Route as FactoryIndexRouteImport } from './routes/factory/index' import { Route as CookiesIndexRouteImport } from './routes/cookies/index' +import { Route as AbortSignalIndexRouteImport } from './routes/abort-signal/index' import { Route as RedirectTestTargetRouteImport } from './routes/redirect-test/target' import { Route as RedirectTestSsrTargetRouteImport } from './routes/redirect-test-ssr/target' import { Route as MiddlewareSendServerFnRouteImport } from './routes/middleware/send-serverFn' import { Route as MiddlewareRequestMiddlewareRouteImport } from './routes/middleware/request-middleware' import { Route as MiddlewareClientMiddlewareRouterRouteImport } from './routes/middleware/client-middleware-router' import { Route as CookiesSetRouteImport } from './routes/cookies/set' +import { Route as AbortSignalMethodRouteImport } from './routes/abort-signal/$method' import { Route as FormdataRedirectTargetNameRouteImport } from './routes/formdata-redirect/target.$name' const SubmitPostFormdataRoute = SubmitPostFormdataRouteImport.update({ @@ -92,11 +93,6 @@ const ConsistentRoute = ConsistentRouteImport.update({ path: '/consistent', getParentRoute: () => rootRouteImport, } as any) -const AbortSignalRoute = AbortSignalRouteImport.update({ - id: '/abort-signal', - path: '/abort-signal', - getParentRoute: () => rootRouteImport, -} as any) const IndexRoute = IndexRouteImport.update({ id: '/', path: '/', @@ -137,6 +133,11 @@ const CookiesIndexRoute = CookiesIndexRouteImport.update({ path: '/cookies/', getParentRoute: () => rootRouteImport, } as any) +const AbortSignalIndexRoute = AbortSignalIndexRouteImport.update({ + id: '/abort-signal/', + path: '/abort-signal/', + getParentRoute: () => rootRouteImport, +} as any) const RedirectTestTargetRoute = RedirectTestTargetRouteImport.update({ id: '/redirect-test/target', path: '/redirect-test/target', @@ -169,6 +170,11 @@ const CookiesSetRoute = CookiesSetRouteImport.update({ path: '/cookies/set', getParentRoute: () => rootRouteImport, } as any) +const AbortSignalMethodRoute = AbortSignalMethodRouteImport.update({ + id: '/abort-signal/$method', + path: '/abort-signal/$method', + getParentRoute: () => rootRouteImport, +} as any) const FormdataRedirectTargetNameRoute = FormdataRedirectTargetNameRouteImport.update({ id: '/formdata-redirect/target/$name', @@ -178,7 +184,6 @@ const FormdataRedirectTargetNameRoute = export interface FileRoutesByFullPath { '/': typeof IndexRoute - '/abort-signal': typeof AbortSignalRoute '/consistent': typeof ConsistentRoute '/dead-code-preserve': typeof DeadCodePreserveRoute '/env-only': typeof EnvOnlyRoute @@ -190,12 +195,14 @@ export interface FileRoutesByFullPath { '/serialize-form-data': typeof SerializeFormDataRoute '/status': typeof StatusRoute '/submit-post-formdata': typeof SubmitPostFormdataRoute + '/abort-signal/$method': typeof AbortSignalMethodRoute '/cookies/set': typeof CookiesSetRoute '/middleware/client-middleware-router': typeof MiddlewareClientMiddlewareRouterRoute '/middleware/request-middleware': typeof MiddlewareRequestMiddlewareRoute '/middleware/send-serverFn': typeof MiddlewareSendServerFnRoute '/redirect-test-ssr/target': typeof RedirectTestSsrTargetRoute '/redirect-test/target': typeof RedirectTestTargetRoute + '/abort-signal': typeof AbortSignalIndexRoute '/cookies': typeof CookiesIndexRoute '/factory': typeof FactoryIndexRoute '/formdata-redirect': typeof FormdataRedirectIndexRoute @@ -207,7 +214,6 @@ export interface FileRoutesByFullPath { } export interface FileRoutesByTo { '/': typeof IndexRoute - '/abort-signal': typeof AbortSignalRoute '/consistent': typeof ConsistentRoute '/dead-code-preserve': typeof DeadCodePreserveRoute '/env-only': typeof EnvOnlyRoute @@ -219,12 +225,14 @@ export interface FileRoutesByTo { '/serialize-form-data': typeof SerializeFormDataRoute '/status': typeof StatusRoute '/submit-post-formdata': typeof SubmitPostFormdataRoute + '/abort-signal/$method': typeof AbortSignalMethodRoute '/cookies/set': typeof CookiesSetRoute '/middleware/client-middleware-router': typeof MiddlewareClientMiddlewareRouterRoute '/middleware/request-middleware': typeof MiddlewareRequestMiddlewareRoute '/middleware/send-serverFn': typeof MiddlewareSendServerFnRoute '/redirect-test-ssr/target': typeof RedirectTestSsrTargetRoute '/redirect-test/target': typeof RedirectTestTargetRoute + '/abort-signal': typeof AbortSignalIndexRoute '/cookies': typeof CookiesIndexRoute '/factory': typeof FactoryIndexRoute '/formdata-redirect': typeof FormdataRedirectIndexRoute @@ -237,7 +245,6 @@ export interface FileRoutesByTo { export interface FileRoutesById { __root__: typeof rootRouteImport '/': typeof IndexRoute - '/abort-signal': typeof AbortSignalRoute '/consistent': typeof ConsistentRoute '/dead-code-preserve': typeof DeadCodePreserveRoute '/env-only': typeof EnvOnlyRoute @@ -249,12 +256,14 @@ export interface FileRoutesById { '/serialize-form-data': typeof SerializeFormDataRoute '/status': typeof StatusRoute '/submit-post-formdata': typeof SubmitPostFormdataRoute + '/abort-signal/$method': typeof AbortSignalMethodRoute '/cookies/set': typeof CookiesSetRoute '/middleware/client-middleware-router': typeof MiddlewareClientMiddlewareRouterRoute '/middleware/request-middleware': typeof MiddlewareRequestMiddlewareRoute '/middleware/send-serverFn': typeof MiddlewareSendServerFnRoute '/redirect-test-ssr/target': typeof RedirectTestSsrTargetRoute '/redirect-test/target': typeof RedirectTestTargetRoute + '/abort-signal/': typeof AbortSignalIndexRoute '/cookies/': typeof CookiesIndexRoute '/factory/': typeof FactoryIndexRoute '/formdata-redirect/': typeof FormdataRedirectIndexRoute @@ -268,7 +277,6 @@ export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath fullPaths: | '/' - | '/abort-signal' | '/consistent' | '/dead-code-preserve' | '/env-only' @@ -280,12 +288,14 @@ export interface FileRouteTypes { | '/serialize-form-data' | '/status' | '/submit-post-formdata' + | '/abort-signal/$method' | '/cookies/set' | '/middleware/client-middleware-router' | '/middleware/request-middleware' | '/middleware/send-serverFn' | '/redirect-test-ssr/target' | '/redirect-test/target' + | '/abort-signal' | '/cookies' | '/factory' | '/formdata-redirect' @@ -297,7 +307,6 @@ export interface FileRouteTypes { fileRoutesByTo: FileRoutesByTo to: | '/' - | '/abort-signal' | '/consistent' | '/dead-code-preserve' | '/env-only' @@ -309,12 +318,14 @@ export interface FileRouteTypes { | '/serialize-form-data' | '/status' | '/submit-post-formdata' + | '/abort-signal/$method' | '/cookies/set' | '/middleware/client-middleware-router' | '/middleware/request-middleware' | '/middleware/send-serverFn' | '/redirect-test-ssr/target' | '/redirect-test/target' + | '/abort-signal' | '/cookies' | '/factory' | '/formdata-redirect' @@ -326,7 +337,6 @@ export interface FileRouteTypes { id: | '__root__' | '/' - | '/abort-signal' | '/consistent' | '/dead-code-preserve' | '/env-only' @@ -338,12 +348,14 @@ export interface FileRouteTypes { | '/serialize-form-data' | '/status' | '/submit-post-formdata' + | '/abort-signal/$method' | '/cookies/set' | '/middleware/client-middleware-router' | '/middleware/request-middleware' | '/middleware/send-serverFn' | '/redirect-test-ssr/target' | '/redirect-test/target' + | '/abort-signal/' | '/cookies/' | '/factory/' | '/formdata-redirect/' @@ -356,7 +368,6 @@ export interface FileRouteTypes { } export interface RootRouteChildren { IndexRoute: typeof IndexRoute - AbortSignalRoute: typeof AbortSignalRoute ConsistentRoute: typeof ConsistentRoute DeadCodePreserveRoute: typeof DeadCodePreserveRoute EnvOnlyRoute: typeof EnvOnlyRoute @@ -368,12 +379,14 @@ export interface RootRouteChildren { SerializeFormDataRoute: typeof SerializeFormDataRoute StatusRoute: typeof StatusRoute SubmitPostFormdataRoute: typeof SubmitPostFormdataRoute + AbortSignalMethodRoute: typeof AbortSignalMethodRoute CookiesSetRoute: typeof CookiesSetRoute MiddlewareClientMiddlewareRouterRoute: typeof MiddlewareClientMiddlewareRouterRoute MiddlewareRequestMiddlewareRoute: typeof MiddlewareRequestMiddlewareRoute MiddlewareSendServerFnRoute: typeof MiddlewareSendServerFnRoute RedirectTestSsrTargetRoute: typeof RedirectTestSsrTargetRoute RedirectTestTargetRoute: typeof RedirectTestTargetRoute + AbortSignalIndexRoute: typeof AbortSignalIndexRoute CookiesIndexRoute: typeof CookiesIndexRoute FactoryIndexRoute: typeof FactoryIndexRoute FormdataRedirectIndexRoute: typeof FormdataRedirectIndexRoute @@ -463,13 +476,6 @@ declare module '@tanstack/solid-router' { preLoaderRoute: typeof ConsistentRouteImport parentRoute: typeof rootRouteImport } - '/abort-signal': { - id: '/abort-signal' - path: '/abort-signal' - fullPath: '/abort-signal' - preLoaderRoute: typeof AbortSignalRouteImport - parentRoute: typeof rootRouteImport - } '/': { id: '/' path: '/' @@ -526,6 +532,13 @@ declare module '@tanstack/solid-router' { preLoaderRoute: typeof CookiesIndexRouteImport parentRoute: typeof rootRouteImport } + '/abort-signal/': { + id: '/abort-signal/' + path: '/abort-signal' + fullPath: '/abort-signal' + preLoaderRoute: typeof AbortSignalIndexRouteImport + parentRoute: typeof rootRouteImport + } '/redirect-test/target': { id: '/redirect-test/target' path: '/redirect-test/target' @@ -568,6 +581,13 @@ declare module '@tanstack/solid-router' { preLoaderRoute: typeof CookiesSetRouteImport parentRoute: typeof rootRouteImport } + '/abort-signal/$method': { + id: '/abort-signal/$method' + path: '/abort-signal/$method' + fullPath: '/abort-signal/$method' + preLoaderRoute: typeof AbortSignalMethodRouteImport + parentRoute: typeof rootRouteImport + } '/formdata-redirect/target/$name': { id: '/formdata-redirect/target/$name' path: '/formdata-redirect/target/$name' @@ -580,7 +600,6 @@ declare module '@tanstack/solid-router' { const rootRouteChildren: RootRouteChildren = { IndexRoute: IndexRoute, - AbortSignalRoute: AbortSignalRoute, ConsistentRoute: ConsistentRoute, DeadCodePreserveRoute: DeadCodePreserveRoute, EnvOnlyRoute: EnvOnlyRoute, @@ -592,12 +611,14 @@ const rootRouteChildren: RootRouteChildren = { SerializeFormDataRoute: SerializeFormDataRoute, StatusRoute: StatusRoute, SubmitPostFormdataRoute: SubmitPostFormdataRoute, + AbortSignalMethodRoute: AbortSignalMethodRoute, CookiesSetRoute: CookiesSetRoute, MiddlewareClientMiddlewareRouterRoute: MiddlewareClientMiddlewareRouterRoute, MiddlewareRequestMiddlewareRoute: MiddlewareRequestMiddlewareRoute, MiddlewareSendServerFnRoute: MiddlewareSendServerFnRoute, RedirectTestSsrTargetRoute: RedirectTestSsrTargetRoute, RedirectTestTargetRoute: RedirectTestTargetRoute, + AbortSignalIndexRoute: AbortSignalIndexRoute, CookiesIndexRoute: CookiesIndexRoute, FactoryIndexRoute: FactoryIndexRoute, FormdataRedirectIndexRoute: FormdataRedirectIndexRoute, diff --git a/e2e/solid-start/server-functions/src/routes/abort-signal.tsx b/e2e/solid-start/server-functions/src/routes/abort-signal/$method.tsx similarity index 56% rename from e2e/solid-start/server-functions/src/routes/abort-signal.tsx rename to e2e/solid-start/server-functions/src/routes/abort-signal/$method.tsx index 752346264e8..2c4edf359d8 100644 --- a/e2e/solid-start/server-functions/src/routes/abort-signal.tsx +++ b/e2e/solid-start/server-functions/src/routes/abort-signal/$method.tsx @@ -1,33 +1,45 @@ import { createFileRoute } from '@tanstack/solid-router' import { createServerFn } from '@tanstack/solid-start' import * as Solid from 'solid-js' +import z from 'zod' -export const Route = createFileRoute('/abort-signal')({ +export const Route = createFileRoute('/abort-signal/$method')({ + params: z.object({ + method: z.union([z.literal('GET'), z.literal('POST')]), + }), component: RouteComponent, }) -const abortableServerFn = createServerFn().handler( - async ({ context, signal }) => { - console.log('server function started', { context, signal }) - return new Promise((resolve, reject) => { - if (signal.aborted) { - return reject(new Error('Aborted before start')) - } - const timerId = setTimeout(() => { - console.log('server function finished') - resolve('server function result') - }, 1000) - const onAbort = () => { - clearTimeout(timerId) - console.log('server function aborted') - reject(new Error('Aborted')) - } - signal.addEventListener('abort', onAbort, { once: true }) - }) - }, +function serverFnImpl(signal: AbortSignal) { + console.log('server function started', { signal }) + return new Promise((resolve, reject) => { + if (signal.aborted) { + return reject(new Error('Aborted before start')) + } + const timerId = setTimeout(() => { + console.log('server function finished') + resolve('server function result') + }, 1000) + const onAbort = () => { + clearTimeout(timerId) + console.log('server function aborted') + reject(new Error('Aborted')) + } + signal.addEventListener('abort', onAbort, { once: true }) + }) +} +const abortableServerFnGET = createServerFn().handler(async ({ signal }) => + serverFnImpl(signal), +) + +const abortableServerFnPOST = createServerFn({ method: 'POST' }).handler( + async ({ signal }) => serverFnImpl(signal), ) function RouteComponent() { + const params = Route.useParams() + const abortableServerFn = () => + params().method === 'GET' ? abortableServerFnGET : abortableServerFnPOST const [errorMessage, setErrorMessage] = Solid.createSignal< string | undefined >(undefined) @@ -44,7 +56,7 @@ function RouteComponent() { onClick={async () => { reset() const controller = new AbortController() - const serverFnPromise = abortableServerFn({ + const serverFnPromise = abortableServerFn()({ signal: controller.signal, }) const timeoutPromise = new Promise((resolve) => @@ -67,7 +79,7 @@ function RouteComponent() { data-testid="run-without-abort-btn" onClick={async () => { reset() - const serverFnResult = await abortableServerFn() + const serverFnResult = await abortableServerFn()() setResult(serverFnResult) }} > diff --git a/e2e/solid-start/server-functions/src/routes/abort-signal/index.tsx b/e2e/solid-start/server-functions/src/routes/abort-signal/index.tsx new file mode 100644 index 00000000000..a5c69aef8af --- /dev/null +++ b/e2e/solid-start/server-functions/src/routes/abort-signal/index.tsx @@ -0,0 +1,25 @@ +import { Link, createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/abort-signal/')({ + component: Home, +}) + +function Home() { + return ( +
+

Server functions E2E Abort Signal Tests

+
    +
  • + + Abortable server function call with GET + +
  • +
  • + + Abortable server function call with POST + +
  • +
+
+ ) +} diff --git a/e2e/solid-start/server-functions/tests/server-functions.spec.ts b/e2e/solid-start/server-functions/tests/server-functions.spec.ts index 3b32deb5bdd..b35c055a518 100644 --- a/e2e/solid-start/server-functions/tests/server-functions.spec.ts +++ b/e2e/solid-start/server-functions/tests/server-functions.spec.ts @@ -266,48 +266,50 @@ test.describe('server function sets cookies', () => { await runCookieTest(page, expectedCookieValue) }) }) +;['GET', 'POST'].forEach((method) => { + test.describe(`aborting a server function call: method ${method}`, () => { + test('without aborting', async ({ page }) => { + await page.goto('/abort-signal/' + method) -test.describe('aborting a server function call', () => { - test('without aborting', async ({ page }) => { - await page.goto('/abort-signal') - - await page.waitForLoadState('networkidle') - - await page.getByTestId('run-without-abort-btn').click() - await page.waitForLoadState('networkidle') - await page.waitForSelector( - '[data-testid="result"]:has-text("server function result")', - ) - await page.waitForSelector( - '[data-testid="errorMessage"]:has-text("$undefined")', - ) + await page.waitForLoadState('networkidle') - const result = (await page.getByTestId('result').textContent()) || '' - expect(result).toBe('server function result') + await page.getByTestId('run-without-abort-btn').click() + await page.waitForLoadState('networkidle') + await page.waitForSelector( + '[data-testid="result"]:has-text("server function result")', + ) + await page.waitForSelector( + '[data-testid="errorMessage"]:has-text("$undefined")', + ) - const errorMessage = - (await page.getByTestId('errorMessage').textContent()) || '' - expect(errorMessage).toBe('$undefined') - }) + const result = (await page.getByTestId('result').textContent()) || '' + expect(result).toBe('server function result') - test('aborting', async ({ page }) => { - await page.goto('/abort-signal') + const errorMessage = + (await page.getByTestId('errorMessage').textContent()) || '' + expect(errorMessage).toBe('$undefined') + }) - await page.waitForLoadState('networkidle') + test('aborting', async ({ page }) => { + await page.goto('/abort-signal/' + method) + await page.waitForLoadState('networkidle') - await page.getByTestId('run-with-abort-btn').click() - await page.waitForLoadState('networkidle') - await page.waitForSelector('[data-testid="result"]:has-text("$undefined")') - await page.waitForSelector( - '[data-testid="errorMessage"]:has-text("aborted")', - ) + await page.getByTestId('run-with-abort-btn').click() + await page.waitForLoadState('networkidle') + await page.waitForSelector( + '[data-testid="result"]:has-text("$undefined")', + ) + await page.waitForSelector( + '[data-testid="errorMessage"]:has-text("aborted")', + ) - const result = (await page.getByTestId('result').textContent()) || '' - expect(result).toBe('$undefined') + const result = (await page.getByTestId('result').textContent()) || '' + expect(result).toBe('$undefined') - const errorMessage = - (await page.getByTestId('errorMessage').textContent()) || '' - expect(errorMessage).toContain('abort') + const errorMessage = + (await page.getByTestId('errorMessage').textContent()) || '' + expect(errorMessage).toContain('abort') + }) }) }) diff --git a/e2e/solid-start/server-routes/package.json b/e2e/solid-start/server-routes/package.json index d41eab03bb0..42476d78627 100644 --- a/e2e/solid-start/server-routes/package.json +++ b/e2e/solid-start/server-routes/package.json @@ -32,7 +32,7 @@ "@types/node": "^22.10.2", "combinate": "^1.1.11", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite-plugin-solid": "^2.11.10", diff --git a/e2e/solid-start/virtual-routes/package.json b/e2e/solid-start/virtual-routes/package.json index 0bc7f7a97b1..c1ae2ac6e7c 100644 --- a/e2e/solid-start/virtual-routes/package.json +++ b/e2e/solid-start/virtual-routes/package.json @@ -29,7 +29,7 @@ "@types/node": "^22.10.2", "combinate": "^1.1.11", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite-plugin-solid": "^2.11.10", diff --git a/e2e/solid-start/website/package.json b/e2e/solid-start/website/package.json index 0c118e49221..d6e7e0052b9 100644 --- a/e2e/solid-start/website/package.json +++ b/e2e/solid-start/website/package.json @@ -27,7 +27,7 @@ "@tanstack/router-e2e-utils": "workspace:^", "@types/node": "^22.10.2", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite-plugin-solid": "^2.11.10", diff --git a/e2e/vue-start/basic/package.json b/e2e/vue-start/basic/package.json index fd00214cabd..35b437ca124 100644 --- a/e2e/vue-start/basic/package.json +++ b/e2e/vue-start/basic/package.json @@ -43,7 +43,7 @@ "@vitejs/plugin-vue-jsx": "^4.1.2", "combinate": "^1.1.11", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.15", "typescript": "^5.7.2", "vite-tsconfig-paths": "^5.1.4" diff --git a/e2e/vue-start/selective-ssr/package.json b/e2e/vue-start/selective-ssr/package.json index 0fa084d6d55..42fb72ac1ab 100644 --- a/e2e/vue-start/selective-ssr/package.json +++ b/e2e/vue-start/selective-ssr/package.json @@ -21,7 +21,7 @@ "@tailwindcss/postcss": "^4.1.15", "@tanstack/router-e2e-utils": "workspace:^", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite": "^7.1.7", diff --git a/e2e/vue-start/serialization-adapters/package.json b/e2e/vue-start/serialization-adapters/package.json index cfad5379eba..e00b102d9cf 100644 --- a/e2e/vue-start/serialization-adapters/package.json +++ b/e2e/vue-start/serialization-adapters/package.json @@ -22,7 +22,7 @@ "@tailwindcss/postcss": "^4.1.15", "@tanstack/router-e2e-utils": "workspace:^", "postcss": "^8.5.1", - "srvx": "^0.8.6", + "srvx": "^0.9.8", "tailwindcss": "^4.1.17", "typescript": "^5.7.2", "vite": "^7.1.7", diff --git a/examples/react/start-clerk-basic/package.json b/examples/react/start-clerk-basic/package.json index f5445b536bd..c6fd44f7afa 100644 --- a/examples/react/start-clerk-basic/package.json +++ b/examples/react/start-clerk-basic/package.json @@ -18,7 +18,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", - "srvx": "0.8.15", + "srvx": "^0.9.8", "tailwind-merge": "^2.6.0" }, "devDependencies": { diff --git a/packages/start-plugin-core/package.json b/packages/start-plugin-core/package.json index 6971b8a5c8c..e75ae6c380f 100644 --- a/packages/start-plugin-core/package.json +++ b/packages/start-plugin-core/package.json @@ -76,7 +76,7 @@ "cheerio": "^1.0.0", "exsolve": "^1.0.7", "pathe": "^2.0.3", - "srvx": "^0.8.2", + "srvx": "^0.9.8", "tinyglobby": "^0.2.15", "ufo": "^1.5.4", "vitefu": "^1.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9b41ca8d2f5..a73d528a694 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1104,8 +1104,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -1323,8 +1323,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -1424,8 +1424,8 @@ importers: specifier: ^19.2.2 version: 19.2.2(@types/react@19.2.2) srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 typescript: specifier: ^5.7.2 version: 5.8.2 @@ -1549,8 +1549,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -1698,8 +1698,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -1759,8 +1759,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -1817,8 +1817,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -1896,8 +1896,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -1978,8 +1978,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -2100,8 +2100,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -2164,8 +2164,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -2965,8 +2965,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -3151,8 +3151,8 @@ importers: specifier: ^8.5.1 version: 8.5.6 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -3191,8 +3191,8 @@ importers: specifier: 22.10.2 version: 22.10.2 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 typescript: specifier: ^5.7.2 version: 5.8.2 @@ -3246,8 +3246,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -3377,8 +3377,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -3417,8 +3417,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -3472,8 +3472,8 @@ importers: specifier: ^8.5.1 version: 8.5.6 srvx: - specifier: ^0.8.6 - version: 0.8.15 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -3542,8 +3542,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -3615,8 +3615,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -3722,8 +3722,8 @@ importers: specifier: ^8.5.1 version: 8.5.6 srvx: - specifier: ^0.8.6 - version: 0.8.15 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -3780,8 +3780,8 @@ importers: specifier: ^8.5.1 version: 8.5.3 srvx: - specifier: ^0.8.6 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -4788,8 +4788,8 @@ importers: specifier: ^8.5.1 version: 8.5.6 srvx: - specifier: ^0.8.6 - version: 0.8.15 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.15 version: 4.1.17 @@ -4895,8 +4895,8 @@ importers: specifier: ^8.5.1 version: 8.5.6 srvx: - specifier: ^0.8.6 - version: 0.8.15 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -4947,8 +4947,8 @@ importers: specifier: ^8.5.1 version: 8.5.6 srvx: - specifier: ^0.8.6 - version: 0.8.15 + specifier: ^0.9.8 + version: 0.9.8 tailwindcss: specifier: ^4.1.17 version: 4.1.17 @@ -7479,8 +7479,8 @@ importers: specifier: ^0.5.1 version: 0.5.1 srvx: - specifier: 0.8.15 - version: 0.8.15 + specifier: ^0.9.8 + version: 0.9.8 tailwind-merge: specifier: ^2.6.0 version: 2.6.0 @@ -11564,8 +11564,8 @@ importers: specifier: ^2.0.3 version: 2.0.3 srvx: - specifier: ^0.8.2 - version: 0.8.7 + specifier: ^0.9.8 + version: 0.9.8 tinyglobby: specifier: ^0.2.15 version: 0.2.15 @@ -11608,7 +11608,7 @@ importers: version: link:../start-storage-context h3-v2: specifier: npm:h3@2.0.0-beta.5 - version: h3@2.0.0-beta.5(crossws@0.4.1(srvx@0.8.15)) + version: h3@2.0.0-beta.5(crossws@0.4.1(srvx@0.9.8)) seroval: specifier: ^1.4.0 version: 1.4.0 @@ -22218,8 +22218,8 @@ packages: engines: {node: '>=20.16.0'} hasBin: true - srvx@0.8.7: - resolution: {integrity: sha512-g3+15LlwVOGL2QpoTPZlvRjg+9a5Tx/69CatXjFP6txvhIaW2FmGyzJfb8yft5wyfGddvJmP/Yx+e/uNDMRSLQ==} + srvx@0.9.8: + resolution: {integrity: sha512-RZaxTKJEE/14HYn8COLuUOJAt0U55N9l1Xf6jj+T0GoA01EUH1Xz5JtSUOI+EHn+AEgPCVn7gk6jHJffrr06fQ==} engines: {node: '>=20.16.0'} hasBin: true @@ -31033,6 +31033,11 @@ snapshots: optionalDependencies: srvx: 0.8.15 + crossws@0.4.1(srvx@0.9.8): + optionalDependencies: + srvx: 0.9.8 + optional: true + css-loader@7.1.2(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1): dependencies: icss-utils: 5.1.0(postcss@8.5.6) @@ -32507,14 +32512,14 @@ snapshots: ufo: 1.6.1 uncrypto: 0.1.3 - h3@2.0.0-beta.5(crossws@0.4.1(srvx@0.8.15)): + h3@2.0.0-beta.5(crossws@0.4.1(srvx@0.9.8)): dependencies: cookie-es: 2.0.0 fetchdts: 0.1.7 rou3: 0.7.8 srvx: 0.8.15 optionalDependencies: - crossws: 0.4.1(srvx@0.8.15) + crossws: 0.4.1(srvx@0.9.8) h3@2.0.1-rc.2(crossws@0.4.1(srvx@0.8.15)): dependencies: @@ -35518,9 +35523,7 @@ snapshots: dependencies: cookie-es: 2.0.0 - srvx@0.8.7: - dependencies: - cookie-es: 2.0.0 + srvx@0.9.8: {} stable-hash-x@0.2.0: {}