1
+ import React from 'react' ;
2
+
1
3
import type { Reducer , Selector } from '@reduxjs/toolkit' ;
2
4
import { createSelector } from '@reduxjs/toolkit' ;
3
5
@@ -51,61 +53,60 @@ export const schemaApi = api.injectEndpoints({
51
53
}
52
54
} ,
53
55
} ) ,
54
- getSchema : builder . query < TEvDescribeSchemeResult & { partial ?: boolean } , { path : string } > ( {
56
+ getSchema : builder . query <
57
+ { [ path : string ] : TEvDescribeSchemeResult & { partial ?: boolean } } ,
58
+ { path : string }
59
+ > ( {
55
60
queryFn : async ( { path} , { signal} ) => {
56
61
try {
57
62
const data = await window . api . getSchema ( { path} , { signal} ) ;
58
- return { data : data ?? { } } ;
63
+ return { data : data ? { [ path ] : data , ... getSchemaChildren ( data ) } : { } } ;
59
64
} catch ( error ) {
60
65
return { error} ;
61
66
}
62
67
} ,
63
68
keepUnusedDataFor : Infinity ,
64
- forceRefetch : ( { endpointState} ) => {
65
- const data = endpointState ?. data ;
66
- if ( data && typeof data === 'object' && 'partial' in data && data . partial ) {
67
- return true ;
68
- }
69
- return false ;
69
+ serializeQueryArgs : ( { queryArgs : { path} } ) => {
70
+ const parts = path . split ( '/' ) ;
71
+ return { path : parts [ 0 ] || parts [ 1 ] } ;
70
72
} ,
71
- onQueryStarted : async ( { path } , { dispatch , getState , queryFulfilled } ) => {
72
- const { data} = await queryFulfilled ;
73
+ merge : ( existing , incoming , { arg : { path } } ) => {
74
+ const { [ path ] : data , ... children } = incoming ;
73
75
if ( data ) {
74
- const state = getState ( ) ;
75
- const { PathDescription : { Children = [ ] } = { } } = data ;
76
- for ( const child of Children ) {
77
- const { Name = '' } = child ;
78
- const childPath = `${ path } /${ Name } ` ;
79
- const cachedData = schemaApi . endpoints . getSchema . select ( { path : childPath } ) (
80
- state ,
81
- ) . data ;
82
- if ( ! cachedData ) {
83
- // not full data, but it contains PathType, which ensures seamless switch between nodes
84
- dispatch (
85
- schemaApi . util . upsertQueryData (
86
- 'getSchema' ,
87
- { path : childPath } ,
88
- { PathDescription : { Self : child } , partial : true } ,
89
- ) ,
90
- ) ;
91
- }
92
- }
76
+ return {
77
+ ...children ,
78
+ ...existing ,
79
+ [ path ] : data ,
80
+ } ;
93
81
}
82
+ return existing ;
94
83
} ,
95
84
} ) ,
96
85
} ) ,
97
86
overrideExisting : 'throw' ,
98
87
} ) ;
99
88
89
+ function getSchemaChildren ( data : TEvDescribeSchemeResult ) {
90
+ const children : { [ path : string ] : TEvDescribeSchemeResult & { partial ?: boolean } } = { } ;
91
+ const { PathDescription : { Children = [ ] } = { } , Path : path } = data ;
92
+ for ( const child of Children ) {
93
+ const { Name = '' } = child ;
94
+ const childPath = `${ path } /${ Name } ` ;
95
+ children [ childPath ] = { PathDescription : { Self : child } , Path : childPath , partial : true } ;
96
+ }
97
+ return children ;
98
+ }
99
+
100
100
const getSchemaSelector = createSelector (
101
101
( path : string ) => path ,
102
102
( path ) => schemaApi . endpoints . getSchema . select ( { path} ) ,
103
103
) ;
104
104
105
105
const selectGetSchema = createSelector (
106
106
( state : RootState ) => state ,
107
+ ( _state : RootState , path : string ) => path ,
107
108
( _state : RootState , path : string ) => getSchemaSelector ( path ) ,
108
- ( state , selectTabletsInfo ) => selectTabletsInfo ( state ) . data ,
109
+ ( state , path , selectTabletsInfo ) => selectTabletsInfo ( state ) . data ?. [ path ] ,
109
110
) ;
110
111
111
112
const selectSchemaChildren = ( state : RootState , path : string ) =>
@@ -127,3 +128,19 @@ export const selectSchemaMergedChildrenPaths: Selector<
127
128
: undefined ;
128
129
} ,
129
130
) ;
131
+
132
+ export function useGetSchemaQuery ( { path} : { path : string } ) {
133
+ const { currentData, isFetching, error, refetch} = schemaApi . useGetSchemaQuery ( { path} ) ;
134
+
135
+ const data = currentData ?. [ path ] ;
136
+ const isLoading = isFetching && data === undefined ;
137
+
138
+ const shouldLoad = ! isLoading && ( ( ! data && ! error ) || data ?. partial ) ;
139
+ React . useEffect ( ( ) => {
140
+ if ( shouldLoad ) {
141
+ refetch ( ) ;
142
+ }
143
+ } , [ refetch , path , shouldLoad ] ) ;
144
+
145
+ return { data, isLoading, error} ;
146
+ }
0 commit comments