66import type { DevEnvironment , Plugin , ViteDevServer } from 'vite'
77import type {
88 DirectiveFn ,
9- FunctionIdFn ,
9+ GenerateFunctionIdFn ,
1010 ReplacerFn ,
1111} from '@tanstack/directive-functions-plugin'
1212
@@ -19,7 +19,7 @@ export type ServerFnPluginOpts = {
1919 * and its modules.
2020 */
2121 manifestVirtualImportId : string
22- functionId ?: FunctionIdFn
22+ generateFunctionId ?: GenerateFunctionIdFn
2323 client : ServerFnPluginEnvOpts
2424 ssr : ServerFnPluginEnvOpts
2525 server : ServerFnPluginEnvOpts
@@ -58,8 +58,12 @@ export function createTanStackServerFnPlugin(opts: ServerFnPluginOpts): {
5858 }
5959 } ,
6060 } )
61- const functionId = buildFunctionId ( ( functionIdOpts , next ) =>
62- next ( Boolean ( viteDevServer ) , opts . functionId ?.( functionIdOpts ) ) ,
61+ const generateFunctionId = buildGenerateFunctionId (
62+ ( generateFunctionIdOpts , next ) =>
63+ next (
64+ Boolean ( viteDevServer ) ,
65+ opts . generateFunctionId ?.( generateFunctionIdOpts ) ,
66+ ) ,
6367 )
6468
6569 const directive = 'use server'
@@ -74,7 +78,7 @@ export function createTanStackServerFnPlugin(opts: ServerFnPluginOpts): {
7478 directive,
7579 directiveLabel,
7680 getRuntimeCode : opts . client . getRuntimeCode ,
77- functionId ,
81+ generateFunctionId ,
7882 replacer : opts . client . replacer ,
7983 onDirectiveFnsById,
8084 } ) ,
@@ -86,7 +90,7 @@ export function createTanStackServerFnPlugin(opts: ServerFnPluginOpts): {
8690 directive,
8791 directiveLabel,
8892 getRuntimeCode : opts . ssr . getRuntimeCode ,
89- functionId ,
93+ generateFunctionId ,
9094 replacer : opts . ssr . replacer ,
9195 onDirectiveFnsById,
9296 } ) ,
@@ -136,7 +140,7 @@ export function createTanStackServerFnPlugin(opts: ServerFnPluginOpts): {
136140 directive,
137141 directiveLabel,
138142 getRuntimeCode : opts . server . getRuntimeCode ,
139- functionId ,
143+ generateFunctionId ,
140144 replacer : opts . server . replacer ,
141145 onDirectiveFnsById,
142146 } ) ,
@@ -182,8 +186,12 @@ export function TanStackServerFnPluginEnv(
182186 } ,
183187 } )
184188
185- const functionId = buildFunctionId ( ( functionIdOpts , next ) =>
186- next ( Boolean ( serverDevEnv ) , opts . functionId ?.( functionIdOpts ) ) ,
189+ const generateFunctionId = buildGenerateFunctionId (
190+ ( generateFunctionIdOpts , next ) =>
191+ next (
192+ Boolean ( serverDevEnv ) ,
193+ opts . generateFunctionId ?.( generateFunctionIdOpts ) ,
194+ ) ,
187195 )
188196
189197 const directive = 'use server'
@@ -196,7 +204,7 @@ export function TanStackServerFnPluginEnv(
196204 directive,
197205 directiveLabel,
198206 onDirectiveFnsById,
199- functionId ,
207+ generateFunctionId ,
200208 environments : {
201209 client : {
202210 envLabel : 'Client' ,
@@ -260,12 +268,20 @@ function resolveViteId(id: string) {
260268 return `\0${ id } `
261269}
262270
263- function buildFunctionId (
271+ function makeFunctionIdUrlSafe ( location : string ) : string {
272+ return location
273+ . replace ( / [ ^ a - z A - Z 0 - 9 - _ ] / g, '_' ) // Replace unsafe chars with underscore
274+ . replace ( / _ { 2 , } / g, '_' ) // Collapse multiple underscores
275+ . replace ( / ^ _ | _ $ / g, '' ) // Trim leading/trailing underscores
276+ . replace ( / _ - - / g, '--' ) // Clean up the joiner
277+ }
278+
279+ function buildGenerateFunctionId (
264280 delegate : (
265- opts : Parameters < FunctionIdFn > [ 0 ] ,
281+ opts : Parameters < GenerateFunctionIdFn > [ 0 ] ,
266282 next : ( dev : boolean , value ?: string ) => string ,
267283 ) => string ,
268- ) : FunctionIdFn {
284+ ) : GenerateFunctionIdFn {
269285 const currentIdToGeneratedId = new Map < string , string > ( )
270286 const generatedIds = new Set < string > ( )
271287 return ( opts ) => {
@@ -274,10 +290,10 @@ function buildFunctionId(
274290 let generatedId = currentIdToGeneratedId . get ( opts . currentId )
275291 if ( generatedId === undefined ) {
276292 generatedId = delegate ( opts , ( dev , newId ) => {
277- // If no value provided, then return the currentId on development
293+ // If no value provided, then return the url-safe currentId on development
278294 // and SHA256 using the currentId as seed on production
279295 if ( newId === undefined ) {
280- if ( dev ) newId = opts . currentId
296+ if ( dev ) newId = makeFunctionIdUrlSafe ( opts . currentId )
281297 else
282298 newId = crypto
283299 . createHash ( 'sha256' )
@@ -286,7 +302,6 @@ function buildFunctionId(
286302 }
287303 return newId
288304 } )
289-
290305 // Deduplicate in case the generated id conflicts with an existing id
291306 if ( generatedIds . has ( generatedId ) ) {
292307 let deduplicatedId
0 commit comments