11import useSWR , { useSWRConfig } from 'swr' ;
2- import type { ScopedMutator } from 'swr/dist/types' ;
2+ import type { MutatorCallback , MutatorOptions } from 'swr/dist/types' ;
33
44const fetcher = async ( url : string , options ?: RequestInit ) => {
55 const res = await fetch ( url , options ) ;
@@ -15,17 +15,17 @@ const fetcher = async (url: string, options?: RequestInit) => {
1515} ;
1616
1717function makeUrl ( url : string , args : unknown ) {
18- return args ? url + `q=${ encodeURIComponent ( JSON . stringify ( args ) ) } ` : url ;
18+ return args ? url + `? q=${ encodeURIComponent ( JSON . stringify ( args ) ) } ` : url ;
1919}
2020
21- export function get < Data , Error = any > ( url : string , args ?: unknown ) {
22- return useSWR < Data , Error > ( makeUrl ( url , args ) , fetcher ) ;
21+ export function get < Data , Error = any > ( url : string | null , args ?: unknown ) {
22+ return useSWR < Data , Error > ( url && makeUrl ( url , args ) , fetcher ) ;
2323}
2424
2525export async function post < Data , Result > (
2626 url : string ,
2727 data : Data ,
28- mutate : ScopedMutator < any >
28+ mutate : Mutator
2929) {
3030 const r : Result = await fetcher ( url , {
3131 method : 'POST' ,
@@ -34,14 +34,14 @@ export async function post<Data, Result>(
3434 } ,
3535 body : JSON . stringify ( data ) ,
3636 } ) ;
37- mutate ( url ) ;
37+ mutate ( url , true ) ;
3838 return r ;
3939}
4040
4141export async function put < Data , Result > (
4242 url : string ,
4343 data : Data ,
44- mutate : ScopedMutator < any >
44+ mutate : Mutator
4545) {
4646 const r : Result = await fetcher ( url , {
4747 method : 'PUT' ,
@@ -50,26 +50,52 @@ export async function put<Data, Result>(
5050 } ,
5151 body : JSON . stringify ( data ) ,
5252 } ) ;
53- mutate ( url , r ) ;
53+ mutate ( url , true ) ;
5454 return r ;
5555}
5656
57- export async function del < Result > (
58- url : string ,
59- args : unknown ,
60- mutate : ScopedMutator < any >
61- ) {
57+ export async function del < Result > ( url : string , args : unknown , mutate : Mutator ) {
6258 const reqUrl = makeUrl ( url , args ) ;
6359 const r : Result = await fetcher ( reqUrl , {
6460 method : 'DELETE' ,
6561 } ) ;
6662 const path = url . split ( '/' ) ;
6763 path . pop ( ) ;
68- mutate ( path . join ( '/' ) ) ;
64+ mutate ( path . join ( '/' ) , true ) ;
6965 return r ;
7066}
7167
72- export function getMutate ( ) {
73- const { mutate } = useSWRConfig ( ) ;
74- return mutate ;
68+ type Mutator = (
69+ key : string ,
70+ prefix : boolean ,
71+ data ?: any | Promise < any > | MutatorCallback ,
72+ opts ?: boolean | MutatorOptions
73+ ) => Promise < any [ ] > ;
74+
75+ export function getMutate ( ) : Mutator {
76+ // https://swr.vercel.app/docs/advanced/cache#mutate-multiple-keys-from-regex
77+ const { cache, mutate } = useSWRConfig ( ) ;
78+ return (
79+ key : string ,
80+ prefix : boolean ,
81+ data ?: any | Promise < any > | MutatorCallback ,
82+ opts ?: boolean | MutatorOptions
83+ ) => {
84+ if ( ! prefix ) {
85+ return mutate ( key , data , opts ) ;
86+ }
87+
88+ if ( ! ( cache instanceof Map ) ) {
89+ throw new Error (
90+ 'mutate requires the cache provider to be a Map instance'
91+ ) ;
92+ }
93+
94+ const keys = Array . from ( cache . keys ( ) ) . filter (
95+ ( k ) => typeof k === 'string' && k . startsWith ( key )
96+ ) as string [ ] ;
97+ console . log ( 'Mutating keys:' , JSON . stringify ( keys ) ) ;
98+ const mutations = keys . map ( ( key ) => mutate ( key , data , opts ) ) ;
99+ return Promise . all ( mutations ) ;
100+ } ;
75101}
0 commit comments