From f329a3d14c6bb2746455c12acbe4a9329fd9875a Mon Sep 17 00:00:00 2001 From: Sheraff Date: Wed, 13 May 2026 23:54:20 +0200 Subject: [PATCH 1/9] fix: revert plugin changes, allow createMiddleware self compilation, fix HMR tests --- .../src/createCsrfMiddleware.ts | 9 ++- .../start-fn-stubs/src/createMiddleware.ts | 13 +++++ packages/start-fn-stubs/src/index.ts | 1 + .../src/start-compiler/compiler.ts | 2 + .../src/vite/start-compiler-plugin/plugin.ts | 55 ++++--------------- 5 files changed, 31 insertions(+), 49 deletions(-) create mode 100644 packages/start-fn-stubs/src/createMiddleware.ts diff --git a/packages/start-client-core/src/createCsrfMiddleware.ts b/packages/start-client-core/src/createCsrfMiddleware.ts index b7152d44a9..8bc4c90a22 100644 --- a/packages/start-client-core/src/createCsrfMiddleware.ts +++ b/packages/start-client-core/src/createCsrfMiddleware.ts @@ -1,5 +1,4 @@ -import { createIsomorphicFn } from '@tanstack/start-fn-stubs' -import { createMiddleware } from './createMiddleware' +import { createIsomorphicFn, createMiddleware } from '@tanstack/start-fn-stubs' import type { RequestMiddlewareAfterServer, RequestServerOptions, @@ -77,8 +76,8 @@ type CreateCsrfMiddleware = ( opts?: CsrfMiddlewareOptions, ) => RequestMiddlewareAfterServer<{}, undefined, undefined> -const innerCreateCsrfMiddleware: CreateCsrfMiddleware = (opts = {}) => { - const middleware = createMiddleware().server(async (ctx) => { +const innerCreateCsrfMiddleware = ((opts: any = {}) => { + const middleware = createMiddleware().server(async (ctx: any) => { const csrfCtx = ctx as RequestServerOptions & typeof ctx if (opts.filter && !(await opts.filter(csrfCtx))) { @@ -97,7 +96,7 @@ const innerCreateCsrfMiddleware: CreateCsrfMiddleware = (opts = {}) => { } return middleware -} +}) as any as CreateCsrfMiddleware export const createCsrfMiddleware: CreateCsrfMiddleware = createIsomorphicFn().server(innerCreateCsrfMiddleware) as CreateCsrfMiddleware diff --git a/packages/start-fn-stubs/src/createMiddleware.ts b/packages/start-fn-stubs/src/createMiddleware.ts new file mode 100644 index 0000000000..f61012d726 --- /dev/null +++ b/packages/start-fn-stubs/src/createMiddleware.ts @@ -0,0 +1,13 @@ +export function createMiddleware(opts?: any, opts2?: any): any { + const options = { ...(opts2 || opts) } + const proxy = new Proxy({}, { + get(_, prop) { + if (prop === 'options') return options + return (value: any) => { + options[prop] = value + return proxy + } + } + }) + return proxy +} \ No newline at end of file diff --git a/packages/start-fn-stubs/src/index.ts b/packages/start-fn-stubs/src/index.ts index 5ca646d9d1..1cd9d1f96d 100644 --- a/packages/start-fn-stubs/src/index.ts +++ b/packages/start-fn-stubs/src/index.ts @@ -5,5 +5,6 @@ export { type ClientOnlyFn, type IsomorphicFnBase, } from './createIsomorphicFn' +export { createMiddleware } from './createMiddleware' export { createServerOnlyFn, createClientOnlyFn } from './envOnly' diff --git a/packages/start-plugin-core/src/start-compiler/compiler.ts b/packages/start-plugin-core/src/start-compiler/compiler.ts index 9a950c65e2..5b7459f86a 100644 --- a/packages/start-plugin-core/src/start-compiler/compiler.ts +++ b/packages/start-plugin-core/src/start-compiler/compiler.ts @@ -694,6 +694,7 @@ export class StartCompiler { ['createIsomorphicFn', 'IsomorphicFn'], ['createServerOnlyFn', 'ServerOnlyFn'], ['createClientOnlyFn', 'ClientOnlyFn'], + ['createMiddleware', 'Middleware'], ]), ) @@ -705,6 +706,7 @@ export class StartCompiler { ['createIsomorphicFn', 'IsomorphicFn'], ['createServerOnlyFn', 'ServerOnlyFn'], ['createClientOnlyFn', 'ClientOnlyFn'], + ['createMiddleware', 'Middleware'], ]), ) diff --git a/packages/start-plugin-core/src/vite/start-compiler-plugin/plugin.ts b/packages/start-plugin-core/src/vite/start-compiler-plugin/plugin.ts index d423798547..3130ca47c1 100644 --- a/packages/start-plugin-core/src/vite/start-compiler-plugin/plugin.ts +++ b/packages/start-plugin-core/src/vite/start-compiler-plugin/plugin.ts @@ -1,4 +1,3 @@ -import { AsyncLocalStorage } from 'node:async_hooks' import { VIRTUAL_MODULES } from '@tanstack/start-server-core' import { resolve as resolvePath } from 'pathe' import { @@ -47,20 +46,6 @@ type ModuleInvalidationEnvironment = { } } -type StartCompilerPluginContext = { - environment: { - name: string - mode: string - transformRequest: (url: string) => Promise - } - load: (options: { id: string }) => Promise<{ code?: string | null }> - resolve: ( - source: string, - importer?: string, - ) => Promise<{ id: string; external?: boolean | string } | null> - error: (message: string) => never -} - function invalidateMatchingFileModules( environment: ModuleInvalidationEnvironment, ids: Iterable, @@ -196,17 +181,6 @@ export function startCompilerPlugin( opts: StartCompilerPluginOptions, ): PluginOption { const compilers = new Map>() - const compilerContextStorage = - new AsyncLocalStorage() - - const getCompilerContext = () => { - const context = compilerContextStorage.getStore() - if (!context) { - throw new Error('Start compiler Vite context is unavailable.') - } - - return context - } // Shared registry of server functions across all environments const serverFnsById: Record = {} @@ -288,30 +262,27 @@ export function startCompilerPlugin( ? createViteDevServerFnModuleSpecifierEncoder(root) : undefined, loadModule: async (id: string) => { - const compilerContext = getCompilerContext() - if (mode === 'build') { - const loaded = await compilerContext.load({ id }) + const loaded = await this.load({ id }) const code = loaded.code ?? '' compiler!.ingestModule({ code, id }) return } - if (compilerContext.environment.mode !== 'dev') { - compilerContext.error( - `could not load module ${id}: unknown environment mode ${compilerContext.environment.mode}`, + if (this.environment.mode !== 'dev') { + this.error( + `could not load module ${id}: unknown environment mode ${this.environment.mode}`, ) } - await compilerContext.environment.transformRequest( + await this.environment.transformRequest( `${id}?${SERVER_FN_LOOKUP}`, ) }, resolveId: async (source: string, importer?: string) => { - const compilerContext = getCompilerContext() - const r = await compilerContext.resolve(source, importer) + const r = await this.resolve(source, importer) if (r) { if (!r.external) { @@ -331,15 +302,11 @@ export function startCompilerPlugin( compilerTransforms, }) - const result = await compilerContextStorage.run( - this as unknown as StartCompilerPluginContext, - () => - compiler.compile({ - id, - code, - detectedKinds, - }), - ) + const result = await compiler.compile({ + id, + code, + detectedKinds, + }) return result }, }, From 54bfae2af2290e7f8933b779173c394f8a3a735b Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 21:56:02 +0000 Subject: [PATCH 2/9] ci: apply automated fixes --- .../start-fn-stubs/src/createMiddleware.ts | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/start-fn-stubs/src/createMiddleware.ts b/packages/start-fn-stubs/src/createMiddleware.ts index f61012d726..6c21a57d93 100644 --- a/packages/start-fn-stubs/src/createMiddleware.ts +++ b/packages/start-fn-stubs/src/createMiddleware.ts @@ -1,13 +1,16 @@ export function createMiddleware(opts?: any, opts2?: any): any { - const options = { ...(opts2 || opts) } - const proxy = new Proxy({}, { - get(_, prop) { - if (prop === 'options') return options - return (value: any) => { - options[prop] = value - return proxy - } - } - }) - return proxy -} \ No newline at end of file + const options = { ...(opts2 || opts) } + const proxy = new Proxy( + {}, + { + get(_, prop) { + if (prop === 'options') return options + return (value: any) => { + options[prop] = value + return proxy + } + }, + }, + ) + return proxy +} From 2bd877c1e87795425d392b12274f2be2beca865b Mon Sep 17 00:00:00 2001 From: Sheraff Date: Thu, 14 May 2026 00:13:41 +0200 Subject: [PATCH 3/9] how about not using a stub? --- packages/start-client-core/src/createCsrfMiddleware.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/start-client-core/src/createCsrfMiddleware.ts b/packages/start-client-core/src/createCsrfMiddleware.ts index 8bc4c90a22..b7152d44a9 100644 --- a/packages/start-client-core/src/createCsrfMiddleware.ts +++ b/packages/start-client-core/src/createCsrfMiddleware.ts @@ -1,4 +1,5 @@ -import { createIsomorphicFn, createMiddleware } from '@tanstack/start-fn-stubs' +import { createIsomorphicFn } from '@tanstack/start-fn-stubs' +import { createMiddleware } from './createMiddleware' import type { RequestMiddlewareAfterServer, RequestServerOptions, @@ -76,8 +77,8 @@ type CreateCsrfMiddleware = ( opts?: CsrfMiddlewareOptions, ) => RequestMiddlewareAfterServer<{}, undefined, undefined> -const innerCreateCsrfMiddleware = ((opts: any = {}) => { - const middleware = createMiddleware().server(async (ctx: any) => { +const innerCreateCsrfMiddleware: CreateCsrfMiddleware = (opts = {}) => { + const middleware = createMiddleware().server(async (ctx) => { const csrfCtx = ctx as RequestServerOptions & typeof ctx if (opts.filter && !(await opts.filter(csrfCtx))) { @@ -96,7 +97,7 @@ const innerCreateCsrfMiddleware = ((opts: any = {}) => { } return middleware -}) as any as CreateCsrfMiddleware +} export const createCsrfMiddleware: CreateCsrfMiddleware = createIsomorphicFn().server(innerCreateCsrfMiddleware) as CreateCsrfMiddleware From 830eaa8777c3d3067ddca3c3f93d7a79a2c46075 Mon Sep 17 00:00:00 2001 From: Sheraff Date: Thu, 14 May 2026 18:00:14 +0200 Subject: [PATCH 4/9] Revert "how about not using a stub?" This reverts commit 2bd877c1e87795425d392b12274f2be2beca865b. --- packages/start-client-core/src/createCsrfMiddleware.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/start-client-core/src/createCsrfMiddleware.ts b/packages/start-client-core/src/createCsrfMiddleware.ts index b7152d44a9..8bc4c90a22 100644 --- a/packages/start-client-core/src/createCsrfMiddleware.ts +++ b/packages/start-client-core/src/createCsrfMiddleware.ts @@ -1,5 +1,4 @@ -import { createIsomorphicFn } from '@tanstack/start-fn-stubs' -import { createMiddleware } from './createMiddleware' +import { createIsomorphicFn, createMiddleware } from '@tanstack/start-fn-stubs' import type { RequestMiddlewareAfterServer, RequestServerOptions, @@ -77,8 +76,8 @@ type CreateCsrfMiddleware = ( opts?: CsrfMiddlewareOptions, ) => RequestMiddlewareAfterServer<{}, undefined, undefined> -const innerCreateCsrfMiddleware: CreateCsrfMiddleware = (opts = {}) => { - const middleware = createMiddleware().server(async (ctx) => { +const innerCreateCsrfMiddleware = ((opts: any = {}) => { + const middleware = createMiddleware().server(async (ctx: any) => { const csrfCtx = ctx as RequestServerOptions & typeof ctx if (opts.filter && !(await opts.filter(csrfCtx))) { @@ -97,7 +96,7 @@ const innerCreateCsrfMiddleware: CreateCsrfMiddleware = (opts = {}) => { } return middleware -} +}) as any as CreateCsrfMiddleware export const createCsrfMiddleware: CreateCsrfMiddleware = createIsomorphicFn().server(innerCreateCsrfMiddleware) as CreateCsrfMiddleware From 8ce33eee2e9292b3cdcf31e52da56030e27ddd48 Mon Sep 17 00:00:00 2001 From: Sheraff Date: Thu, 14 May 2026 18:23:50 +0200 Subject: [PATCH 5/9] minor type fix --- packages/start-client-core/src/createCsrfMiddleware.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/start-client-core/src/createCsrfMiddleware.ts b/packages/start-client-core/src/createCsrfMiddleware.ts index 8bc4c90a22..6cdd1c0d13 100644 --- a/packages/start-client-core/src/createCsrfMiddleware.ts +++ b/packages/start-client-core/src/createCsrfMiddleware.ts @@ -78,7 +78,7 @@ type CreateCsrfMiddleware = ( const innerCreateCsrfMiddleware = ((opts: any = {}) => { const middleware = createMiddleware().server(async (ctx: any) => { - const csrfCtx = ctx as RequestServerOptions & typeof ctx + const csrfCtx = ctx as RequestServerOptions if (opts.filter && !(await opts.filter(csrfCtx))) { return ctx.next() From e4452d52b1b993f9a3dff6a361e0f91623f9a1c8 Mon Sep 17 00:00:00 2001 From: Sheraff Date: Thu, 14 May 2026 19:02:04 +0200 Subject: [PATCH 6/9] fix: revert plugin changes, createCsrfMiddleware compilation, fix HMR tests --- .changeset/strong-trains-act.md | 1 - packages/react-start/src/index.ts | 11 +++++++++++ packages/solid-start/src/index.ts | 11 +++++++++++ packages/start-client-core/src/index.tsx | 11 ----------- packages/start-fn-stubs/src/createMiddleware.ts | 16 ---------------- packages/start-fn-stubs/src/index.ts | 1 - .../src/start-compiler/compiler.ts | 1 - packages/start-server-core/package.json | 6 ++++++ .../src/createCsrfMiddleware.ts | 13 ++++++++----- .../start-server-core/src/createStartHandler.ts | 3 +-- .../tests/createCsrfMiddleware.test.ts | 4 ++-- packages/start-server-core/vite.config.ts | 1 + packages/vue-start/src/index.ts | 11 +++++++++++ 13 files changed, 51 insertions(+), 39 deletions(-) delete mode 100644 packages/start-fn-stubs/src/createMiddleware.ts rename packages/{start-client-core => start-server-core}/src/createCsrfMiddleware.ts (95%) rename packages/{start-client-core/src => start-server-core}/tests/createCsrfMiddleware.test.ts (98%) diff --git a/.changeset/strong-trains-act.md b/.changeset/strong-trains-act.md index d0394c8efa..9f9b454196 100644 --- a/.changeset/strong-trains-act.md +++ b/.changeset/strong-trains-act.md @@ -1,5 +1,4 @@ --- -'@tanstack/start-client-core': minor '@tanstack/start-plugin-core': patch '@tanstack/start-server-core': patch '@tanstack/start-fn-stubs': patch diff --git a/packages/react-start/src/index.ts b/packages/react-start/src/index.ts index 8b51b6c783..ec2dac01de 100644 --- a/packages/react-start/src/index.ts +++ b/packages/react-start/src/index.ts @@ -1,2 +1,13 @@ export { useServerFn } from './useServerFn' export * from '@tanstack/start-client-core' +export { + createCsrfMiddleware, + csrfSymbol, + getCsrfRequestValidationResult, + isCsrfRequestAllowed, +} from '@tanstack/start-server-core/createCsrfMiddleware' +export type { + CsrfMatcher, + CsrfMiddlewareOptions, + CsrfSecFetchSite, +} from '@tanstack/start-server-core/createCsrfMiddleware' diff --git a/packages/solid-start/src/index.ts b/packages/solid-start/src/index.ts index 8b51b6c783..ec2dac01de 100644 --- a/packages/solid-start/src/index.ts +++ b/packages/solid-start/src/index.ts @@ -1,2 +1,13 @@ export { useServerFn } from './useServerFn' export * from '@tanstack/start-client-core' +export { + createCsrfMiddleware, + csrfSymbol, + getCsrfRequestValidationResult, + isCsrfRequestAllowed, +} from '@tanstack/start-server-core/createCsrfMiddleware' +export type { + CsrfMatcher, + CsrfMiddlewareOptions, + CsrfSecFetchSite, +} from '@tanstack/start-server-core/createCsrfMiddleware' diff --git a/packages/start-client-core/src/index.tsx b/packages/start-client-core/src/index.tsx index 5bf09c4440..f7835c9859 100644 --- a/packages/start-client-core/src/index.tsx +++ b/packages/start-client-core/src/index.tsx @@ -84,17 +84,6 @@ export { flattenMiddlewares, executeMiddleware, } from './createServerFn' -export { - createCsrfMiddleware, - csrfSymbol, - getCsrfRequestValidationResult, - isCsrfRequestAllowed, -} from './createCsrfMiddleware' -export type { - CsrfMatcher, - CsrfMiddlewareOptions, - CsrfSecFetchSite, -} from './createCsrfMiddleware' export { TSS_FORMDATA_CONTEXT, diff --git a/packages/start-fn-stubs/src/createMiddleware.ts b/packages/start-fn-stubs/src/createMiddleware.ts deleted file mode 100644 index 6c21a57d93..0000000000 --- a/packages/start-fn-stubs/src/createMiddleware.ts +++ /dev/null @@ -1,16 +0,0 @@ -export function createMiddleware(opts?: any, opts2?: any): any { - const options = { ...(opts2 || opts) } - const proxy = new Proxy( - {}, - { - get(_, prop) { - if (prop === 'options') return options - return (value: any) => { - options[prop] = value - return proxy - } - }, - }, - ) - return proxy -} diff --git a/packages/start-fn-stubs/src/index.ts b/packages/start-fn-stubs/src/index.ts index 1cd9d1f96d..5ca646d9d1 100644 --- a/packages/start-fn-stubs/src/index.ts +++ b/packages/start-fn-stubs/src/index.ts @@ -5,6 +5,5 @@ export { type ClientOnlyFn, type IsomorphicFnBase, } from './createIsomorphicFn' -export { createMiddleware } from './createMiddleware' export { createServerOnlyFn, createClientOnlyFn } from './envOnly' diff --git a/packages/start-plugin-core/src/start-compiler/compiler.ts b/packages/start-plugin-core/src/start-compiler/compiler.ts index 5b7459f86a..6cd2f026e6 100644 --- a/packages/start-plugin-core/src/start-compiler/compiler.ts +++ b/packages/start-plugin-core/src/start-compiler/compiler.ts @@ -694,7 +694,6 @@ export class StartCompiler { ['createIsomorphicFn', 'IsomorphicFn'], ['createServerOnlyFn', 'ServerOnlyFn'], ['createClientOnlyFn', 'ClientOnlyFn'], - ['createMiddleware', 'Middleware'], ]), ) diff --git a/packages/start-server-core/package.json b/packages/start-server-core/package.json index 18588e650e..b18ed0ee1b 100644 --- a/packages/start-server-core/package.json +++ b/packages/start-server-core/package.json @@ -47,6 +47,12 @@ "default": "./dist/esm/index.js" } }, + "./createCsrfMiddleware": { + "import": { + "types": "./dist/esm/createCsrfMiddleware.d.ts", + "default": "./dist/esm/createCsrfMiddleware.js" + } + }, "./createServerRpc": { "import": { "types": "./dist/esm/createServerRpc.d.ts", diff --git a/packages/start-client-core/src/createCsrfMiddleware.ts b/packages/start-server-core/src/createCsrfMiddleware.ts similarity index 95% rename from packages/start-client-core/src/createCsrfMiddleware.ts rename to packages/start-server-core/src/createCsrfMiddleware.ts index 6cdd1c0d13..54e4201ca8 100644 --- a/packages/start-client-core/src/createCsrfMiddleware.ts +++ b/packages/start-server-core/src/createCsrfMiddleware.ts @@ -1,8 +1,11 @@ -import { createIsomorphicFn, createMiddleware } from '@tanstack/start-fn-stubs' +import { + createIsomorphicFn, + createMiddleware, +} from '@tanstack/start-client-core' import type { RequestMiddlewareAfterServer, RequestServerOptions, -} from './createMiddleware' +} from '@tanstack/start-client-core' import type { Register } from '@tanstack/router-core' export const csrfSymbol = Symbol.for('tanstack-start:csrf-middleware') @@ -76,8 +79,8 @@ type CreateCsrfMiddleware = ( opts?: CsrfMiddlewareOptions, ) => RequestMiddlewareAfterServer<{}, undefined, undefined> -const innerCreateCsrfMiddleware = ((opts: any = {}) => { - const middleware = createMiddleware().server(async (ctx: any) => { +const innerCreateCsrfMiddleware: CreateCsrfMiddleware = (opts = {}) => { + const middleware = createMiddleware().server(async (ctx) => { const csrfCtx = ctx as RequestServerOptions if (opts.filter && !(await opts.filter(csrfCtx))) { @@ -96,7 +99,7 @@ const innerCreateCsrfMiddleware = ((opts: any = {}) => { } return middleware -}) as any as CreateCsrfMiddleware +} export const createCsrfMiddleware: CreateCsrfMiddleware = createIsomorphicFn().server(innerCreateCsrfMiddleware) as CreateCsrfMiddleware diff --git a/packages/start-server-core/src/createStartHandler.ts b/packages/start-server-core/src/createStartHandler.ts index 293eda1d43..6d71bc1a43 100644 --- a/packages/start-server-core/src/createStartHandler.ts +++ b/packages/start-server-core/src/createStartHandler.ts @@ -1,8 +1,6 @@ import { createMemoryHistory } from '@tanstack/history' import { - createCsrfMiddleware, createNullProtoObject, - csrfSymbol, flattenMiddlewares, mergeHeaders, safeObjectMerge, @@ -21,6 +19,7 @@ import { getStartContext, runWithStartContext, } from '@tanstack/start-storage-context' +import { createCsrfMiddleware, csrfSymbol } from './createCsrfMiddleware' import { requestHandler } from './request-response' import { getStartManifest } from './router-manifest' import { handleServerAction } from './server-functions-handler' diff --git a/packages/start-client-core/src/tests/createCsrfMiddleware.test.ts b/packages/start-server-core/tests/createCsrfMiddleware.test.ts similarity index 98% rename from packages/start-client-core/src/tests/createCsrfMiddleware.test.ts rename to packages/start-server-core/tests/createCsrfMiddleware.test.ts index f152e82144..b4c79a1ef5 100644 --- a/packages/start-client-core/src/tests/createCsrfMiddleware.test.ts +++ b/packages/start-server-core/tests/createCsrfMiddleware.test.ts @@ -4,8 +4,8 @@ import { csrfSymbol, getCsrfRequestValidationResult, isCsrfRequestAllowed, -} from '../createCsrfMiddleware' -import type { RequestServerOptions } from '../createMiddleware' +} from '../src/createCsrfMiddleware' +import type { RequestServerOptions } from '@tanstack/start-client-core' import type { Register } from '@tanstack/router-core' const requestOrigin = 'https://app.example.com' diff --git a/packages/start-server-core/vite.config.ts b/packages/start-server-core/vite.config.ts index 7953e5a067..be88227ea3 100644 --- a/packages/start-server-core/vite.config.ts +++ b/packages/start-server-core/vite.config.ts @@ -21,6 +21,7 @@ export default mergeConfig( srcDir: './src', entry: [ './src/index.tsx', + './src/createCsrfMiddleware.ts', './src/createServerRpc.ts', './src/createSsrRpc.ts', './src/fake-start-server-fn-resolver.ts', diff --git a/packages/vue-start/src/index.ts b/packages/vue-start/src/index.ts index 8b51b6c783..ec2dac01de 100644 --- a/packages/vue-start/src/index.ts +++ b/packages/vue-start/src/index.ts @@ -1,2 +1,13 @@ export { useServerFn } from './useServerFn' export * from '@tanstack/start-client-core' +export { + createCsrfMiddleware, + csrfSymbol, + getCsrfRequestValidationResult, + isCsrfRequestAllowed, +} from '@tanstack/start-server-core/createCsrfMiddleware' +export type { + CsrfMatcher, + CsrfMiddlewareOptions, + CsrfSecFetchSite, +} from '@tanstack/start-server-core/createCsrfMiddleware' From 51c796ef9645fad8c7da7e28add3a6e4007b1bfc Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Fri, 15 May 2026 15:22:29 +0200 Subject: [PATCH 7/9] fix compiler --- packages/react-start/src/index.ts | 11 - packages/solid-start/src/index.ts | 11 - .../src/createCsrfMiddleware.ts | 8 +- packages/start-client-core/src/index.tsx | 11 + .../src/start-compiler/compiler.ts | 238 ++++++++++++------ .../start-plugin-core/tests/compiler.test.ts | 69 +++++ .../createMiddleware/createMiddleware.test.ts | 110 ++++++++ .../createServerFn/createServerFn.test.ts | 55 ++++ packages/start-server-core/package.json | 6 - .../src/createStartHandler.ts | 3 +- .../tests/createCsrfMiddleware.test.ts | 2 +- packages/start-server-core/vite.config.ts | 1 - packages/vue-start/src/index.ts | 11 - 13 files changed, 418 insertions(+), 118 deletions(-) rename packages/{start-server-core => start-client-core}/src/createCsrfMiddleware.ts (97%) diff --git a/packages/react-start/src/index.ts b/packages/react-start/src/index.ts index ec2dac01de..8b51b6c783 100644 --- a/packages/react-start/src/index.ts +++ b/packages/react-start/src/index.ts @@ -1,13 +1,2 @@ export { useServerFn } from './useServerFn' export * from '@tanstack/start-client-core' -export { - createCsrfMiddleware, - csrfSymbol, - getCsrfRequestValidationResult, - isCsrfRequestAllowed, -} from '@tanstack/start-server-core/createCsrfMiddleware' -export type { - CsrfMatcher, - CsrfMiddlewareOptions, - CsrfSecFetchSite, -} from '@tanstack/start-server-core/createCsrfMiddleware' diff --git a/packages/solid-start/src/index.ts b/packages/solid-start/src/index.ts index ec2dac01de..8b51b6c783 100644 --- a/packages/solid-start/src/index.ts +++ b/packages/solid-start/src/index.ts @@ -1,13 +1,2 @@ export { useServerFn } from './useServerFn' export * from '@tanstack/start-client-core' -export { - createCsrfMiddleware, - csrfSymbol, - getCsrfRequestValidationResult, - isCsrfRequestAllowed, -} from '@tanstack/start-server-core/createCsrfMiddleware' -export type { - CsrfMatcher, - CsrfMiddlewareOptions, - CsrfSecFetchSite, -} from '@tanstack/start-server-core/createCsrfMiddleware' diff --git a/packages/start-server-core/src/createCsrfMiddleware.ts b/packages/start-client-core/src/createCsrfMiddleware.ts similarity index 97% rename from packages/start-server-core/src/createCsrfMiddleware.ts rename to packages/start-client-core/src/createCsrfMiddleware.ts index 54e4201ca8..0715dd7e63 100644 --- a/packages/start-server-core/src/createCsrfMiddleware.ts +++ b/packages/start-client-core/src/createCsrfMiddleware.ts @@ -1,11 +1,9 @@ -import { - createIsomorphicFn, - createMiddleware, -} from '@tanstack/start-client-core' +import { createIsomorphicFn } from '@tanstack/start-fn-stubs' +import { createMiddleware } from './createMiddleware' import type { RequestMiddlewareAfterServer, RequestServerOptions, -} from '@tanstack/start-client-core' +} from './createMiddleware' import type { Register } from '@tanstack/router-core' export const csrfSymbol = Symbol.for('tanstack-start:csrf-middleware') diff --git a/packages/start-client-core/src/index.tsx b/packages/start-client-core/src/index.tsx index f7835c9859..5bf09c4440 100644 --- a/packages/start-client-core/src/index.tsx +++ b/packages/start-client-core/src/index.tsx @@ -84,6 +84,17 @@ export { flattenMiddlewares, executeMiddleware, } from './createServerFn' +export { + createCsrfMiddleware, + csrfSymbol, + getCsrfRequestValidationResult, + isCsrfRequestAllowed, +} from './createCsrfMiddleware' +export type { + CsrfMatcher, + CsrfMiddlewareOptions, + CsrfSecFetchSite, +} from './createCsrfMiddleware' export { TSS_FORMDATA_CONTEXT, diff --git a/packages/start-plugin-core/src/start-compiler/compiler.ts b/packages/start-plugin-core/src/start-compiler/compiler.ts index 6cd2f026e6..e742a75d41 100644 --- a/packages/start-plugin-core/src/start-compiler/compiler.ts +++ b/packages/start-plugin-core/src/start-compiler/compiler.ts @@ -40,6 +40,8 @@ type Binding = resolvedKind?: Kind } +type ImportBinding = Extract + type Kind = 'None' | `Root` | `Builder` | LookupKind export type BuiltInLookupKind = @@ -270,6 +272,12 @@ export type LookupConfig = { kind: LookupKind | 'Root' // 'Root' for builder pattern, LookupKind for direct call } +interface ExportResolution { + moduleInfo: ModuleInfo + localName: string + binding: Binding +} + interface ModuleInfo { id: string bindings: Map @@ -463,7 +471,7 @@ export class StartCompiler { private resolveIdCache = new Map() private exportResolutionCache = new Map< string, - Map + Map >() // Fast lookup for direct imports from known libraries (e.g., '@tanstack/react-start') // Maps: libName → (exportName → Kind) @@ -702,10 +710,12 @@ export class StartCompiler { this.knownRootImports.set( '@tanstack/start-client-core', new Map([ + ['createServerFn', 'Root'], ['createIsomorphicFn', 'IsomorphicFn'], ['createServerOnlyFn', 'ServerOnlyFn'], ['createClientOnlyFn', 'ClientOnlyFn'], ['createMiddleware', 'Middleware'], + ['createStart', 'Root'], ]), ) @@ -1456,7 +1466,7 @@ export class StartCompiler { // TODO improve cycle detection? should we throw here instead of returning 'None'? // prevent cycles - const vKey = `${id}:${ident}` + const vKey = `${cleanId(id)}:${ident}` if (visited.has(vKey)) { return 'None' } @@ -1475,7 +1485,7 @@ export class StartCompiler { moduleInfo: ModuleInfo, exportName: string, visitedModules = new Set(), - ): Promise<{ moduleInfo: ModuleInfo; binding: Binding } | undefined> { + ): Promise { const isBuildMode = this.mode === 'build' // Check cache first (only for top-level calls in build mode) @@ -1500,7 +1510,7 @@ export class StartCompiler { if (localBindingName) { const binding = moduleInfo.bindings.get(localBindingName) if (binding) { - const result = { moduleInfo, binding } + const result = { moduleInfo, localName: localBindingName, binding } // Cache the result (build mode only) if (isBuildMode) { this.getExportResolutionCache(moduleInfo.id).set(exportName, result) @@ -1549,58 +1559,165 @@ export class StartCompiler { return undefined } - private async resolveBindingKind( - binding: Binding, - fileId: string, + private async resolveBindingTarget( + resolution: ExportResolution, visited = new Set(), + ): Promise { + const key = `${cleanId(resolution.moduleInfo.id)}:${resolution.localName}` + if (visited.has(key)) { + return undefined + } + visited.add(key) + + if (resolution.binding.type !== 'import') { + return resolution + } + + const target = await this.resolveIdCached( + resolution.binding.source, + resolution.moduleInfo.id, + ) + if (!target) { + return undefined + } + + const importedModule = await this.getModuleInfo(target) + const found = await this.findExportInModule( + importedModule, + resolution.binding.importedName, + ) + if (!found) { + return undefined + } + + return this.resolveBindingTarget(found, visited) + } + + private async resolveKnownImportKind( + binding: ImportBinding, + resolved?: ExportResolution, ): Promise { - if (binding.resolvedKind) { - return binding.resolvedKind + const directKind = + this.knownRootImports.get(binding.source)?.get(binding.importedName) ?? + 'None' + if (directKind !== 'None') { + return directKind } - if (binding.type === 'import') { - // Fast path: check if this is a direct import from a known library - // (e.g., import { createServerFn } from '@tanstack/react-start') - // This avoids async resolveId calls for the common case - const knownExports = this.knownRootImports.get(binding.source) - if (knownExports) { - const kind = knownExports.get(binding.importedName) - if (kind) { - binding.resolvedKind = kind - return kind - } + + if (!resolved) { + return 'None' + } + + for (const [source, exports] of this.knownRootImports) { + const kind = exports.get(binding.importedName) + if (!kind) { + continue } - // Slow path: resolve through the module graph - const target = await this.resolveIdCached(binding.source, fileId) - if (!target) { - return 'None' + let targetId: string | null + try { + targetId = await this.resolveIdCached(source, resolved.moduleInfo.id) + } catch { + continue } - const importedModule = await this.getModuleInfo(target) + if (!targetId) { + continue + } - // Find the export, recursively searching through export * from chains - const found = await this.findExportInModule( - importedModule, - binding.importedName, - ) + try { + const rootModule = await this.getModuleInfo(targetId) + const found = await this.findExportInModule( + rootModule, + binding.importedName, + ) + const target = found + ? ((await this.resolveBindingTarget(found)) ?? found) + : undefined - if (!found) { - return 'None' + // Match by resolved binding identity, not by export name alone. + if ( + target && + cleanId(resolved.moduleInfo.id) === cleanId(target.moduleInfo.id) && + resolved.localName === target.localName + ) { + return kind + } + } catch { + continue } + } - const { moduleInfo: foundModule, binding: foundBinding } = found + return 'None' + } - if (foundBinding.resolvedKind) { - return foundBinding.resolvedKind - } + private async resolveImportKind( + binding: ImportBinding, + fileId: string, + visited: Set, + ): Promise { + const directKnownKind = await this.resolveKnownImportKind(binding) + if (directKnownKind !== 'None') { + binding.resolvedKind = directKnownKind + return directKnownKind + } - const resolvedKind = await this.resolveBindingKind( - foundBinding, - foundModule.id, - visited, - ) - foundBinding.resolvedKind = resolvedKind - return resolvedKind + if (binding.importedName === '*') { + return 'None' + } + + const target = await this.resolveIdCached(binding.source, fileId) + if (!target) { + return 'None' + } + + const importedModule = await this.getModuleInfo(target) + const found = await this.findExportInModule( + importedModule, + binding.importedName, + ) + if (!found) { + return 'None' + } + + const knownKind = await this.resolveKnownImportKind(binding, found) + if (knownKind !== 'None') { + found.binding.resolvedKind = knownKind + binding.resolvedKind = knownKind + return knownKind + } + + if (found.binding.resolvedKind) { + return found.binding.resolvedKind + } + + // Import aliases can form cycles, e.g. A re-exports from B while B + // re-exports from A. Track the exported binding before following it. + const vKey = `${cleanId(found.moduleInfo.id)}:${found.localName}` + if (visited.has(vKey)) { + return 'None' + } + visited.add(vKey) + + const resolvedKind = await this.resolveBindingKind( + found.binding, + found.moduleInfo.id, + visited, + ) + found.binding.resolvedKind = resolvedKind + return resolvedKind + } + + private async resolveBindingKind( + binding: Binding, + fileId: string, + visited = new Set(), + ): Promise { + if (binding.resolvedKind) { + return binding.resolvedKind + } + if (binding.type === 'import') { + return this.resolveImportKind(binding, fileId, visited) } const resolvedKind = await this.resolveExprKind( @@ -1744,36 +1861,15 @@ export class StartCompiler { binding.type === 'import' && binding.importedName === '*' ) { - const knownExports = this.knownRootImports.get(binding.source) - const knownKind = knownExports?.get(callee.property.name) - if (knownKind) { - return knownKind - } - - // resolve the property from the target module - const targetModuleId = await this.resolveIdCached( - binding.source, + return this.resolveImportKind( + { + type: 'import', + source: binding.source, + importedName: callee.property.name, + }, fileId, + visited, ) - if (targetModuleId) { - const targetModule = await this.getModuleInfo(targetModuleId) - const localBindingName = targetModule.exports.get( - callee.property.name, - ) - if (localBindingName) { - const exportedBinding = - targetModule.bindings.get(localBindingName) - if (exportedBinding) { - return await this.resolveBindingKind( - exportedBinding, - targetModule.id, - visited, - ) - } - } - } else { - return 'None' - } } } return this.resolveExprKind(callee.object, fileId, visited) diff --git a/packages/start-plugin-core/tests/compiler.test.ts b/packages/start-plugin-core/tests/compiler.test.ts index 58a91e3e1d..e5c99fd257 100644 --- a/packages/start-plugin-core/tests/compiler.test.ts +++ b/packages/start-plugin-core/tests/compiler.test.ts @@ -886,6 +886,75 @@ describe('re-export chain resolution', () => { expect(result!.code).not.toContain('deep-server') }) + test.each([ + { + name: 'named re-export cycle', + virtualModules: { + './factory-a': ` + export { createServerOnlyFn } from './factory-b' + `, + './factory-b': ` + export { createServerOnlyFn } from './factory-a' + `, + }, + }, + { + name: 'import alias cycle', + virtualModules: { + './factory-a': ` + import { createServerOnlyFn } from './factory-b' + export { createServerOnlyFn } + `, + './factory-b': ` + import { createServerOnlyFn } from './factory-a' + export { createServerOnlyFn } + `, + }, + }, + { + name: 'export-star cycle', + virtualModules: { + './factory-a': ` + export * from './factory-b' + `, + './factory-b': ` + export * from './factory-a' + `, + }, + }, + ])('handles circular import chain: $name', async ({ virtualModules }) => { + const compiler: StartCompiler = new StartCompiler({ + env: 'server', + envName: 'ssr', + root: '/test', + framework: 'react' as const, + providerEnvName: 'ssr', + lookupKinds: new Set(['ServerOnlyFn']), + lookupConfigurations: [], + getKnownServerFns: () => ({}), + loadModule: async (id) => { + const code = virtualModules[id as keyof typeof virtualModules] + if (code) { + compiler.ingestModule({ code, id }) + } + }, + resolveId: async (id) => { + return id in virtualModules ? id : null + }, + mode: 'build', + }) + + const result = await compiler.compile({ + id: 'circular-import-test.ts', + code: ` + import { createServerOnlyFn } from './factory-a' + const myFn = createServerOnlyFn(() => 'server-only-value') + `, + }) + + expect(result).toBeNull() + }) + test('ingestModule populates module metadata for later resolution', async () => { const compiler: StartCompiler = new StartCompiler({ env: 'server', diff --git a/packages/start-plugin-core/tests/createMiddleware/createMiddleware.test.ts b/packages/start-plugin-core/tests/createMiddleware/createMiddleware.test.ts index 8844dfbb80..e300baf6a9 100644 --- a/packages/start-plugin-core/tests/createMiddleware/createMiddleware.test.ts +++ b/packages/start-plugin-core/tests/createMiddleware/createMiddleware.test.ts @@ -158,4 +158,114 @@ describe('createMiddleware compiles correctly', async () => { expect(resolveIdMock).toHaveBeenCalledTimes(1) expect(resolveIdMock).toHaveBeenNthCalledWith(1, './factory', 'test.ts') }) + + test('should resolve createMiddleware from start-client-core implementation file', async () => { + const virtualModules: Record = { + '@tanstack/start-client-core': ` + export { createMiddleware } from './createMiddleware' + export { createIsomorphicFn } from '@tanstack/start-fn-stubs' + `, + '/virtual/compiler-known/middleware-factory.ts': ` + export const createMiddleware = () => ({ + server: () => createMiddleware(), + }) + `, + } + + const compiler = new StartCompiler({ + env: 'client', + ...getDefaultTestOptions('client'), + loadModule: async (id) => { + const code = virtualModules[id] + if (code) { + compiler.ingestModule({ code, id }) + } + }, + lookupKinds: new Set(['Middleware', 'IsomorphicFn']), + lookupConfigurations: [], + getKnownServerFns: () => ({}), + resolveId: async (source) => { + if (source === '@tanstack/start-client-core') { + return '@tanstack/start-client-core' + } + + if (source === './createMiddleware') { + return '/virtual/compiler-known/middleware-factory.ts' + } + + return null + }, + }) + + const result = await compiler.compile({ + id: '/repo/packages/start-client-core/src/createCsrfMiddleware.ts', + code: ` + import { createIsomorphicFn } from '@tanstack/start-fn-stubs' + import { createMiddleware } from './createMiddleware' + + const innerCreateCsrfMiddleware = () => { + return createMiddleware().server(() => 'server-only-middleware') + } + + export const createCsrfMiddleware = createIsomorphicFn() + .server(innerCreateCsrfMiddleware) + `, + }) + + expect(result).not.toBeNull() + expect(result!.code).not.toContain('server-only-middleware') + expect(result!.code).not.toContain('createIsomorphicFn') + }) + + test('should resolve namespace createMiddleware from start-client-core implementation file', async () => { + const virtualModules: Record = { + '@tanstack/start-client-core': ` + export { createMiddleware } from './createMiddleware' + `, + '/virtual/compiler-known/middleware-factory.ts': ` + export const createMiddleware = () => ({ + server: () => createMiddleware(), + }) + `, + } + + const compiler = new StartCompiler({ + env: 'client', + ...getDefaultTestOptions('client'), + loadModule: async (id) => { + const code = virtualModules[id] + if (code) { + compiler.ingestModule({ code, id }) + } + }, + lookupKinds: new Set(['Middleware']), + lookupConfigurations: [], + getKnownServerFns: () => ({}), + resolveId: async (source) => { + if (source === '@tanstack/start-client-core') { + return '@tanstack/start-client-core' + } + + if (source === './createMiddleware') { + return '/virtual/compiler-known/middleware-factory.ts' + } + + return null + }, + }) + + const result = await compiler.compile({ + id: '/repo/packages/start-client-core/src/internal.ts', + code: ` + import * as middlewareModule from './createMiddleware' + + export const middleware = middlewareModule.createMiddleware().server(() => { + return 'server-only-middleware' + }) + `, + }) + + expect(result).not.toBeNull() + expect(result!.code).not.toContain('server-only-middleware') + }) }) diff --git a/packages/start-plugin-core/tests/createServerFn/createServerFn.test.ts b/packages/start-plugin-core/tests/createServerFn/createServerFn.test.ts index ce46b064b4..8b2716db77 100644 --- a/packages/start-plugin-core/tests/createServerFn/createServerFn.test.ts +++ b/packages/start-plugin-core/tests/createServerFn/createServerFn.test.ts @@ -520,4 +520,59 @@ describe('createServerFn compiles correctly', async () => { expect(firstResult!.code).toContain('createSsrRpc("constant_id"') expect(secondResult!.code).toContain('createSsrRpc("constant_id_1"') }) + + test('should resolve createServerFn from the same binding as a known root export', async () => { + const virtualModules: Record = { + '@tanstack/start-client-core': ` + export { createServerFn } from './createServerFn' + `, + '/virtual/compiler-known/server-fn-factory.ts': ` + export const createServerFn = () => ({ + handler: () => createServerFn(), + }) + `, + } + + const compiler = new StartCompiler({ + env: 'client', + ...getDefaultTestOptions('client'), + root: '/test', + mode: 'build', + loadModule: async (id) => { + const code = virtualModules[id] + if (code) { + compiler.ingestModule({ code, id }) + } + }, + lookupKinds: new Set(['ServerFn']), + lookupConfigurations: [], + getKnownServerFns: () => ({}), + resolveId: async (source) => { + if (source === '@tanstack/start-client-core') { + return '@tanstack/start-client-core' + } + + if (source === './createServerFn') { + return '/virtual/compiler-known/server-fn-factory.ts' + } + + return null + }, + }) + + const result = await compiler.compile({ + id: '/test/src/internal-server-fn.ts', + code: ` + import { createServerFn } from './createServerFn' + + export const getMessage = createServerFn().handler(() => { + return 'server-only-value' + }) + `, + }) + + expect(result).not.toBeNull() + expect(result!.code).toContain('createClientRpc') + expect(result!.code).not.toContain('server-only-value') + }) }) diff --git a/packages/start-server-core/package.json b/packages/start-server-core/package.json index b18ed0ee1b..18588e650e 100644 --- a/packages/start-server-core/package.json +++ b/packages/start-server-core/package.json @@ -47,12 +47,6 @@ "default": "./dist/esm/index.js" } }, - "./createCsrfMiddleware": { - "import": { - "types": "./dist/esm/createCsrfMiddleware.d.ts", - "default": "./dist/esm/createCsrfMiddleware.js" - } - }, "./createServerRpc": { "import": { "types": "./dist/esm/createServerRpc.d.ts", diff --git a/packages/start-server-core/src/createStartHandler.ts b/packages/start-server-core/src/createStartHandler.ts index 6d71bc1a43..293eda1d43 100644 --- a/packages/start-server-core/src/createStartHandler.ts +++ b/packages/start-server-core/src/createStartHandler.ts @@ -1,6 +1,8 @@ import { createMemoryHistory } from '@tanstack/history' import { + createCsrfMiddleware, createNullProtoObject, + csrfSymbol, flattenMiddlewares, mergeHeaders, safeObjectMerge, @@ -19,7 +21,6 @@ import { getStartContext, runWithStartContext, } from '@tanstack/start-storage-context' -import { createCsrfMiddleware, csrfSymbol } from './createCsrfMiddleware' import { requestHandler } from './request-response' import { getStartManifest } from './router-manifest' import { handleServerAction } from './server-functions-handler' diff --git a/packages/start-server-core/tests/createCsrfMiddleware.test.ts b/packages/start-server-core/tests/createCsrfMiddleware.test.ts index b4c79a1ef5..a46aa444d2 100644 --- a/packages/start-server-core/tests/createCsrfMiddleware.test.ts +++ b/packages/start-server-core/tests/createCsrfMiddleware.test.ts @@ -4,7 +4,7 @@ import { csrfSymbol, getCsrfRequestValidationResult, isCsrfRequestAllowed, -} from '../src/createCsrfMiddleware' +} from '@tanstack/start-client-core' import type { RequestServerOptions } from '@tanstack/start-client-core' import type { Register } from '@tanstack/router-core' diff --git a/packages/start-server-core/vite.config.ts b/packages/start-server-core/vite.config.ts index be88227ea3..7953e5a067 100644 --- a/packages/start-server-core/vite.config.ts +++ b/packages/start-server-core/vite.config.ts @@ -21,7 +21,6 @@ export default mergeConfig( srcDir: './src', entry: [ './src/index.tsx', - './src/createCsrfMiddleware.ts', './src/createServerRpc.ts', './src/createSsrRpc.ts', './src/fake-start-server-fn-resolver.ts', diff --git a/packages/vue-start/src/index.ts b/packages/vue-start/src/index.ts index ec2dac01de..8b51b6c783 100644 --- a/packages/vue-start/src/index.ts +++ b/packages/vue-start/src/index.ts @@ -1,13 +1,2 @@ export { useServerFn } from './useServerFn' export * from '@tanstack/start-client-core' -export { - createCsrfMiddleware, - csrfSymbol, - getCsrfRequestValidationResult, - isCsrfRequestAllowed, -} from '@tanstack/start-server-core/createCsrfMiddleware' -export type { - CsrfMatcher, - CsrfMiddlewareOptions, - CsrfSecFetchSite, -} from '@tanstack/start-server-core/createCsrfMiddleware' From 81cdab891c84999aad35df5b44ac91b033ee4695 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Fri, 15 May 2026 15:58:25 +0200 Subject: [PATCH 8/9] fix rolldown issue --- .../src/vite/start-compiler-plugin/plugin.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/start-plugin-core/src/vite/start-compiler-plugin/plugin.ts b/packages/start-plugin-core/src/vite/start-compiler-plugin/plugin.ts index 3130ca47c1..698ab5ae1a 100644 --- a/packages/start-plugin-core/src/vite/start-compiler-plugin/plugin.ts +++ b/packages/start-plugin-core/src/vite/start-compiler-plugin/plugin.ts @@ -228,6 +228,14 @@ export function startCompilerPlugin( configResolved(config) { root = config.root }, + buildStart() { + if (this.environment.mode === 'build') { + // Vite app builds can run multiple Rolldown build phases with fresh + // plugin drivers. The compiler host closes over this hook context for + // load/resolve, so do not reuse it after a previous driver was closed. + compilers.delete(this.environment.name) + } + }, transform: { filter: { id: { From 604a9f4fecfe7b7003e027e5f45aaf35e4c66b03 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Fri, 15 May 2026 16:25:08 +0200 Subject: [PATCH 9/9] fix flaky test --- e2e/react-start/hmr/package.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/e2e/react-start/hmr/package.json b/e2e/react-start/hmr/package.json index 04d505c2d7..0bd3da5fd0 100644 --- a/e2e/react-start/hmr/package.json +++ b/e2e/react-start/hmr/package.json @@ -35,6 +35,17 @@ "vite": "^8.0.0" }, "nx": { + "targets": { + "test:e2e": { + "parallelism": false + }, + "test:e2e--vite-ssr": { + "parallelism": false + }, + "test:e2e--rsbuild-ssr": { + "parallelism": false + } + }, "metadata": { "playwrightModes": [ {