@@ -12,12 +12,60 @@ function isNumeric(str: string | number | undefined) {
1212 return `${ + str } ` === `${ str } `
1313}
1414
15+ interface RpcCacheOptions {
16+ functions : string [ ]
17+ }
18+
19+ // @TODO : should be moved to birpc-x?
20+ class RpcCacheManager {
21+ private cacheMap = new Map < string , Map < string , unknown > > ( )
22+ private options : RpcCacheOptions
23+
24+ constructor ( options : RpcCacheOptions ) {
25+ this . options = options
26+ }
27+
28+ updateOptions ( options : Partial < RpcCacheOptions > ) {
29+ this . options = {
30+ ...this . options ,
31+ ...options ,
32+ }
33+ }
34+
35+ cached ( m : string , a : unknown [ ] ) {
36+ const methodCache = this . cacheMap . get ( m )
37+ if ( methodCache ) {
38+ return methodCache . get ( JSON . stringify ( a ) )
39+ }
40+ return undefined
41+ }
42+
43+ apply ( req : { m : string , a : unknown [ ] } , res : unknown ) {
44+ const methodCache = this . cacheMap . get ( req . m ) || new Map < string , unknown > ( )
45+ methodCache . set ( JSON . stringify ( req . a ) , res )
46+ this . cacheMap . set ( req . m , methodCache )
47+ }
48+
49+ validate ( m : string ) {
50+ return this . options . functions . includes ( m )
51+ }
52+
53+ invalidate ( key ?: string ) {
54+ if ( key ) {
55+ this . cacheMap . delete ( key )
56+ }
57+ else {
58+ this . cacheMap . clear ( )
59+ }
60+ }
61+ }
62+
1563export interface DevToolsRpcClientOptions {
1664 connectionMeta ?: ConnectionMeta
1765 baseURL ?: string [ ]
18- cacheResponse ?: boolean
1966 wsOptions ?: Partial < WebSocketRpcClientOptions >
2067 rpcOptions ?: Partial < BirpcOptions < DevToolsRpcServerFunctions > >
68+ cacheOptions ?: boolean | Partial < RpcCacheOptions >
2169}
2270
2371export type DevToolsRpcClient = BirpcReturn < DevToolsRpcServerFunctions , DevToolsRpcClientFunctions >
@@ -26,19 +74,29 @@ export interface ClientRpcReturn {
2674 connectionMeta : ConnectionMeta
2775 rpc : DevToolsRpcClient
2876 clientRpc : DevToolsClientRpcHost
29- invalidateCache : ( ) => void
3077}
3178
79+ export async function getDevToolsRpcClient (
80+ options : DevToolsRpcClientOptions & { cacheOptions : false } ,
81+ ) : Promise < ClientRpcReturn >
82+ export async function getDevToolsRpcClient (
83+ options : DevToolsRpcClientOptions & { cacheOptions : true } ,
84+ ) : Promise < ClientRpcReturn & { cacheManager : RpcCacheManager } >
85+ export async function getDevToolsRpcClient (
86+ options : DevToolsRpcClientOptions & { cacheOptions : Partial < RpcCacheOptions > } ,
87+ ) : Promise < ClientRpcReturn & { cacheManager : RpcCacheManager } >
88+ export async function getDevToolsRpcClient (
89+ options ?: DevToolsRpcClientOptions ,
90+ ) : Promise < ClientRpcReturn >
3291export async function getDevToolsRpcClient (
3392 options : DevToolsRpcClientOptions = { } ,
3493) : Promise < ClientRpcReturn > {
3594 const {
3695 baseURL = '/.devtools/' ,
3796 rpcOptions = { } ,
38- cacheResponse = false ,
97+ cacheOptions = false ,
3998 } = options
4099 const urls = Array . isArray ( baseURL ) ? baseURL : [ baseURL ]
41- const responseCacheMap = new Map < string , unknown > ( )
42100 let connectionMeta : ConnectionMeta | undefined = options . connectionMeta
43101
44102 if ( ! connectionMeta ) {
@@ -64,6 +122,7 @@ export async function getDevToolsRpcClient(
64122 ? `${ location . protocol . replace ( 'http' , 'ws' ) } //${ location . hostname } :${ connectionMeta . websocket } `
65123 : connectionMeta . websocket as string
66124
125+ const cacheManager = cacheOptions ? new RpcCacheManager ( { functions : [ ] , ...( typeof options . cacheOptions === 'object' ? options . cacheOptions : { } ) } ) : null
67126 const context : DevToolsClientContext = {
68127 rpc : undefined ! ,
69128 }
@@ -79,13 +138,14 @@ export async function getDevToolsRpcClient(
79138 ...rpcOptions ,
80139 onRequest : async ( req , next , resolve ) => {
81140 await rpcOptions . onRequest ?.( req , next , resolve )
82- if ( cacheResponse ) {
83- const cacheKey = ` ${ req . m } - ${ JSON . stringify ( req . a ) } `
84- if ( responseCacheMap . has ( cacheKey ) ) {
85- resolve ( responseCacheMap . get ( cacheKey ) )
141+ if ( cacheOptions && cacheManager ?. validate ( req . m ) ) {
142+ const cached = cacheManager . cached ( req . m , req . a )
143+ if ( cached ) {
144+ return resolve ( cached )
86145 }
87146 else {
88- responseCacheMap . set ( cacheKey , await next ( req ) )
147+ const res = await next ( req )
148+ cacheManager ?. apply ( req , res )
89149 }
90150 }
91151 else {
@@ -98,19 +158,10 @@ export async function getDevToolsRpcClient(
98158 // @ts -expect-error assign to readonly property
99159 context . rpc = rpc
100160
101- function invalidateCache ( key ?: string ) {
102- if ( key ) {
103- responseCacheMap . delete ( key )
104- }
105- else {
106- responseCacheMap . clear ( )
107- }
108- }
109-
110161 return {
111162 connectionMeta,
112163 rpc,
113164 clientRpc,
114- invalidateCache ,
165+ ... ( cacheOptions ? { cacheManager } : { } ) ,
115166 }
116167}
0 commit comments