@@ -2,8 +2,8 @@ import { $TRACK, createMemo, createSignal, JSX, onCleanup, getOwner } from "soli
22import { isServer } from "solid-js/web" ;
33import { useRouter } from "../routing.js" ;
44import { RouterContext , Submission , Navigator } from "../types.js" ;
5- import { redirectStatusCodes , mockBase } from "../utils.js" ;
6- import { cacheKeyOp , hashKey , revalidate } from "./cache.js" ;
5+ import { mockBase } from "../utils.js" ;
6+ import { cacheKeyOp , hashKey , revalidate , cache } from "./cache.js" ;
77
88export type Action < T extends Array < any > , U > = ( T extends [ FormData ] | [ ]
99 ? JSX . SerializableAttributeValue
@@ -60,10 +60,14 @@ export function action<T extends Array<any>, U = void>(
6060 name ?: string
6161) : Action < T , U > {
6262 function mutate ( this : RouterContext , ...variables : T ) {
63- const p = fn ( ...variables ) ;
63+ const router = this ;
64+ const p = (
65+ router . singleFlight && ( fn as any ) . withOptions
66+ ? ( fn as any ) . withOptions ( { headers : { "X-Single-Flight" : "true" } } )
67+ : fn
68+ ) ( ...variables ) ;
6469 const [ result , setResult ] = createSignal < { data ?: U } > ( ) ;
6570 let submission : Submission < T , U > ;
66- const router = this ;
6771 async function handler ( res : any ) {
6872 const data = await handleResponse ( res as any , router . navigatorFactory ( ) ) ;
6973 data ? setResult ( { data } ) : submission . clear ( ) ;
@@ -135,11 +139,24 @@ const hashString = (s: string) =>
135139async function handleResponse ( response : Response , navigate : Navigator ) {
136140 let data : any ;
137141 let keys : string [ ] | undefined ;
142+ let invalidateKeys : string [ ] | undefined ;
138143 if ( response instanceof Response ) {
139144 if ( response . headers . has ( "X-Revalidate" ) )
140- keys = response . headers . get ( "X-Revalidate" ) ! . split ( "," ) ;
141- if ( ( response as any ) . customBody ) data = await ( response as any ) . customBody ( ) ;
142- if ( redirectStatusCodes . has ( response . status ) ) {
145+ keys = invalidateKeys = response . headers . get ( "X-Revalidate" ) ! . split ( "," ) ;
146+ if ( ( response as any ) . customBody ) {
147+ data = await ( response as any ) . customBody ( ) ;
148+ if ( response . headers . has ( "X-Single-Flight" ) ) {
149+ keys || ( keys = [ ] ) ;
150+ invalidateKeys || ( invalidateKeys = [ ] ) ;
151+ Object . keys ( data ) . forEach ( key => {
152+ if ( key === "_$value" ) return ;
153+ keys ! . push ( key ) ;
154+ cache . set ( key , data [ key ] ) ;
155+ } ) ;
156+ data = data . _$value ;
157+ }
158+ }
159+ if ( response . headers . has ( "Location" ) ) {
143160 const locationUrl = response . headers . get ( "Location" ) || "/" ;
144161 if ( locationUrl . startsWith ( "http" ) ) {
145162 window . location . href = locationUrl ;
@@ -149,7 +166,7 @@ async function handleResponse(response: Response, navigate: Navigator) {
149166 }
150167 } else data = response ;
151168 // invalidate
152- cacheKeyOp ( keys , entry => ( entry [ 0 ] = 0 ) ) ;
169+ cacheKeyOp ( invalidateKeys , entry => ( entry [ 0 ] = 0 ) ) ;
153170 // trigger revalidation
154171 await revalidate ( keys , false ) ;
155172 return data ;
0 commit comments