Skip to content

Commit ac2aea7

Browse files
committed
refactor(ui): delegate hooks to kubernetesjs react
1 parent cf4a56f commit ac2aea7

File tree

11 files changed

+352
-728
lines changed

11 files changed

+352
-728
lines changed

ui/contexts/KubernetesContext.tsx

Lines changed: 39 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
'use client'
22

3-
import React, { createContext, useContext, useMemo, useState } from 'react'
3+
import React, { createContext, useContext, useState } from 'react'
4+
import {
5+
KubernetesProvider as BaseKubernetesProvider,
6+
useKubernetes as useBaseKubernetes,
7+
queryClient
8+
} from '@kubernetesjs/react'
49
import { KubernetesClient } from 'kubernetesjs'
5-
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
610

711
// Configuration types
812
export interface KubernetesConfig {
@@ -23,17 +27,7 @@ interface KubernetesContextValue {
2327
// Create context
2428
const KubernetesContext = createContext<KubernetesContextValue | undefined>(undefined)
2529

26-
// Query client for TanStack Query
27-
const queryClient = new QueryClient({
28-
defaultOptions: {
29-
queries: {
30-
refetchOnWindowFocus: false,
31-
retry: 3,
32-
staleTime: 30 * 1000, // 30 seconds
33-
gcTime: 5 * 60 * 1000, // 5 minutes
34-
},
35-
},
36-
})
30+
3731

3832
// Provider props
3933
interface KubernetesProviderProps {
@@ -42,48 +36,46 @@ interface KubernetesProviderProps {
4236
}
4337

4438
// Provider component
45-
export function KubernetesProvider({
46-
children,
47-
initialConfig
48-
}: KubernetesProviderProps) {
49-
const [config, setConfig] = useState<KubernetesConfig>({
50-
restEndpoint: initialConfig?.restEndpoint || process.env.NEXT_PUBLIC_K8S_API_URL || '/api/k8s',
51-
namespace: initialConfig?.namespace || 'default',
52-
headers: initialConfig?.headers || {},
53-
})
54-
55-
const [namespace, setNamespace] = useState(config.namespace || 'default')
56-
57-
// Create client instance
58-
const client = useMemo(() => {
59-
return new KubernetesClient({
60-
restEndpoint: config.restEndpoint,
61-
})
62-
}, [config.restEndpoint])
63-
64-
// Update config function
65-
const updateConfig = (newConfig: Partial<KubernetesConfig>) => {
66-
setConfig(prev => ({ ...prev, ...newConfig }))
67-
if (newConfig.namespace) {
68-
setNamespace(newConfig.namespace)
39+
export function KubernetesProvider({ children, initialConfig }: KubernetesProviderProps) {
40+
const [namespace, setNamespace] = useState(initialConfig?.namespace || 'default')
41+
42+
return (
43+
<BaseKubernetesProvider
44+
initialConfig={{
45+
restEndpoint: initialConfig?.restEndpoint || process.env.NEXT_PUBLIC_K8S_API_URL || '/api/k8s',
46+
headers: initialConfig?.headers || {}
47+
}}
48+
>
49+
<InnerProvider namespace={namespace} setNamespace={setNamespace}>{children}</InnerProvider>
50+
</BaseKubernetesProvider>
51+
)
52+
}
53+
54+
interface InnerProviderProps {
55+
children: React.ReactNode
56+
namespace: string
57+
setNamespace: (namespace: string) => void
58+
}
59+
60+
function InnerProvider({ children, namespace, setNamespace }: InnerProviderProps) {
61+
const base = useBaseKubernetes()
62+
63+
const updateConfig = (config: Partial<KubernetesConfig>) => {
64+
base.updateConfig(config)
65+
if (config.namespace) {
66+
setNamespace(config.namespace)
6967
}
7068
}
7169

7270
const contextValue: KubernetesContextValue = {
73-
client,
74-
config,
71+
client: base.client as KubernetesClient,
72+
config: { ...base.config, namespace },
7573
namespace,
7674
setNamespace,
7775
updateConfig,
7876
}
7977

80-
return (
81-
<QueryClientProvider client={queryClient}>
82-
<KubernetesContext.Provider value={contextValue}>
83-
{children}
84-
</KubernetesContext.Provider>
85-
</QueryClientProvider>
86-
)
78+
return <KubernetesContext.Provider value={contextValue}>{children}</KubernetesContext.Provider>
8779
}
8880

8981
// Hook to use Kubernetes context
@@ -96,4 +88,4 @@ export function useKubernetes() {
9688
}
9789

9890
// Export query client for use in hooks
99-
export { queryClient }
91+
export { queryClient }

ui/hooks/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ export * from './useDaemonSets'
99
export * from './useReplicaSets'
1010

1111
// Re-export context hook
12-
export { useKubernetes } from '../contexts/KubernetesContext'
12+
export { useKubernetes } from '../contexts/KubernetesContext'

ui/hooks/useConfigMaps.ts

Lines changed: 43 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,62 @@
1-
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
1+
import {
2+
useListCoreV1ConfigMapForAllNamespacesQuery,
3+
useListCoreV1NamespacedConfigMapQuery,
4+
useReadCoreV1NamespacedConfigMapQuery,
5+
useCreateCoreV1NamespacedConfigMap,
6+
useReplaceCoreV1NamespacedConfigMap,
7+
useDeleteCoreV1NamespacedConfigMap
8+
} from '@kubernetesjs/react'
29
import { useKubernetes } from '../contexts/KubernetesContext'
3-
import type { ConfigMap, ConfigMapList } from 'kubernetesjs'
4-
5-
// Query keys
6-
const CONFIGMAPS_KEY = ['configmaps'] as const
10+
import type { ConfigMap } from 'kubernetesjs'
711

812
export function useConfigMaps(namespace?: string) {
9-
const { client, namespace: defaultNamespace } = useKubernetes()
13+
const { namespace: defaultNamespace } = useKubernetes()
1014
const ns = namespace || defaultNamespace
1115

12-
return useQuery<ConfigMapList, Error>({
13-
queryKey: [...CONFIGMAPS_KEY, ns],
14-
queryFn: async () => {
15-
if (ns === '_all') {
16-
const result = await client.listCoreV1ConfigMapForAllNamespaces({
17-
query: {},
18-
})
19-
return result
20-
} else {
21-
const result = await client.listCoreV1NamespacedConfigMap({
22-
path: { namespace: ns },
23-
query: {},
24-
})
25-
return result
26-
}
27-
},
28-
refetchOnMount: 'always',
29-
staleTime: 0,
30-
})
16+
if (ns === '_all') {
17+
return useListCoreV1ConfigMapForAllNamespacesQuery({ query: {} })
18+
}
19+
return useListCoreV1NamespacedConfigMapQuery({ path: { namespace: ns }, query: {} })
3120
}
3221

3322
export function useConfigMap(name: string, namespace?: string) {
34-
const { client, namespace: defaultNamespace } = useKubernetes()
23+
const { namespace: defaultNamespace } = useKubernetes()
3524
const ns = namespace || defaultNamespace
36-
37-
return useQuery<ConfigMap, Error>({
38-
queryKey: [...CONFIGMAPS_KEY, ns, name],
39-
queryFn: async () => {
40-
const result = await client.readCoreV1NamespacedConfigMap({
41-
path: { namespace: ns, name },
42-
query: {},
43-
})
44-
return result
45-
},
46-
enabled: !!name,
47-
refetchOnMount: 'always',
48-
staleTime: 0,
49-
})
25+
return useReadCoreV1NamespacedConfigMapQuery({ path: { namespace: ns, name }, query: {} })
5026
}
5127

5228
export function useCreateConfigMap() {
53-
const { client, namespace: defaultNamespace } = useKubernetes()
54-
const queryClient = useQueryClient()
55-
56-
return useMutation<ConfigMap, Error, { configMap: ConfigMap; namespace?: string }>({
57-
mutationFn: async ({ configMap, namespace }) => {
58-
const ns = namespace || defaultNamespace
59-
const result = await client.createCoreV1NamespacedConfigMap({
60-
path: { namespace: ns },
61-
query: {},
62-
body: configMap,
63-
})
64-
return result
65-
},
66-
onSuccess: (_, variables) => {
67-
const ns = variables.namespace || defaultNamespace
68-
queryClient.invalidateQueries({ queryKey: [...CONFIGMAPS_KEY, ns] })
69-
},
70-
})
29+
const { namespace: defaultNamespace } = useKubernetes()
30+
const mutation = useCreateCoreV1NamespacedConfigMap()
31+
return {
32+
...mutation,
33+
mutate: ({ configMap, namespace }) =>
34+
mutation.mutate({ path: { namespace: namespace || defaultNamespace }, query: {}, body: configMap }),
35+
mutateAsync: ({ configMap, namespace }) =>
36+
mutation.mutateAsync({ path: { namespace: namespace || defaultNamespace }, query: {}, body: configMap }),
37+
}
7138
}
7239

7340
export function useUpdateConfigMap() {
74-
const { client, namespace: defaultNamespace } = useKubernetes()
75-
const queryClient = useQueryClient()
76-
77-
return useMutation<ConfigMap, Error, { name: string; configMap: ConfigMap; namespace?: string }>({
78-
mutationFn: async ({ name, configMap, namespace }) => {
79-
const ns = namespace || defaultNamespace
80-
const result = await client.replaceCoreV1NamespacedConfigMap({
81-
path: { namespace: ns, name },
82-
query: {},
83-
body: configMap,
84-
})
85-
return result
86-
},
87-
onSuccess: (_, variables) => {
88-
const ns = variables.namespace || defaultNamespace
89-
queryClient.invalidateQueries({ queryKey: [...CONFIGMAPS_KEY, ns] })
90-
},
91-
})
41+
const { namespace: defaultNamespace } = useKubernetes()
42+
const mutation = useReplaceCoreV1NamespacedConfigMap()
43+
return {
44+
...mutation,
45+
mutate: ({ name, configMap, namespace }) =>
46+
mutation.mutate({ path: { namespace: namespace || defaultNamespace, name }, query: {}, body: configMap }),
47+
mutateAsync: ({ name, configMap, namespace }) =>
48+
mutation.mutateAsync({ path: { namespace: namespace || defaultNamespace, name }, query: {}, body: configMap }),
49+
}
9250
}
9351

9452
export function useDeleteConfigMap() {
95-
const { client, namespace: defaultNamespace } = useKubernetes()
96-
const queryClient = useQueryClient()
97-
98-
return useMutation<void, Error, { name: string; namespace?: string }>({
99-
mutationFn: async ({ name, namespace }) => {
100-
const ns = namespace || defaultNamespace
101-
await client.deleteCoreV1NamespacedConfigMap({
102-
path: { namespace: ns, name },
103-
query: {},
104-
})
105-
},
106-
onSuccess: (_, variables) => {
107-
const ns = variables.namespace || defaultNamespace
108-
queryClient.invalidateQueries({ queryKey: [...CONFIGMAPS_KEY, ns] })
109-
},
110-
})
53+
const { namespace: defaultNamespace } = useKubernetes()
54+
const mutation = useDeleteCoreV1NamespacedConfigMap()
55+
return {
56+
...mutation,
57+
mutate: ({ name, namespace }) =>
58+
mutation.mutate({ path: { namespace: namespace || defaultNamespace, name }, query: {} }),
59+
mutateAsync: ({ name, namespace }) =>
60+
mutation.mutateAsync({ path: { namespace: namespace || defaultNamespace, name }, query: {} }),
61+
}
11162
}

ui/hooks/useDaemonSets.ts

Lines changed: 23 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,36 @@
1-
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
1+
import {
2+
useListAppsV1DaemonSetForAllNamespacesQuery,
3+
useListAppsV1NamespacedDaemonSetQuery,
4+
useReadAppsV1NamespacedDaemonSetQuery,
5+
useDeleteAppsV1NamespacedDaemonSet
6+
} from '@kubernetesjs/react'
27
import { useKubernetes } from '../contexts/KubernetesContext'
3-
import type { DaemonSet, DaemonSetList } from 'kubernetesjs'
4-
5-
// Query keys
6-
const DAEMONSETS_KEY = ['daemonsets'] as const
8+
import type { DaemonSet } from 'kubernetesjs'
79

810
export function useDaemonSets(namespace?: string) {
9-
const { client, namespace: defaultNamespace } = useKubernetes()
11+
const { namespace: defaultNamespace } = useKubernetes()
1012
const ns = namespace || defaultNamespace
1113

12-
return useQuery<DaemonSetList, Error>({
13-
queryKey: [...DAEMONSETS_KEY, ns],
14-
queryFn: async () => {
15-
if (ns === '_all') {
16-
const result = await client.listAppsV1DaemonSetForAllNamespaces({
17-
query: {},
18-
})
19-
return result
20-
} else {
21-
const result = await client.listAppsV1NamespacedDaemonSet({
22-
path: { namespace: ns },
23-
query: {},
24-
})
25-
return result
26-
}
27-
},
28-
refetchOnMount: 'always',
29-
staleTime: 0,
30-
})
14+
if (ns === '_all') {
15+
return useListAppsV1DaemonSetForAllNamespacesQuery({ query: {} })
16+
}
17+
return useListAppsV1NamespacedDaemonSetQuery({ path: { namespace: ns }, query: {} })
3118
}
3219

3320
export function useDaemonSet(name: string, namespace?: string) {
34-
const { client, namespace: defaultNamespace } = useKubernetes()
21+
const { namespace: defaultNamespace } = useKubernetes()
3522
const ns = namespace || defaultNamespace
36-
37-
return useQuery<DaemonSet, Error>({
38-
queryKey: [...DAEMONSETS_KEY, ns, name],
39-
queryFn: async () => {
40-
const result = await client.readAppsV1NamespacedDaemonSet({
41-
path: { namespace: ns, name },
42-
query: {},
43-
})
44-
return result
45-
},
46-
enabled: !!name,
47-
refetchOnMount: 'always',
48-
staleTime: 0,
49-
})
23+
return useReadAppsV1NamespacedDaemonSetQuery({ path: { namespace: ns, name }, query: {} })
5024
}
5125

5226
export function useDeleteDaemonSet() {
53-
const { client, namespace: defaultNamespace } = useKubernetes()
54-
const queryClient = useQueryClient()
55-
56-
return useMutation<void, Error, { name: string; namespace?: string }>({
57-
mutationFn: async ({ name, namespace }) => {
58-
const ns = namespace || defaultNamespace
59-
await client.deleteAppsV1NamespacedDaemonSet({
60-
path: { namespace: ns, name },
61-
query: {},
62-
})
63-
},
64-
onSuccess: (_, variables) => {
65-
const ns = variables.namespace || defaultNamespace
66-
queryClient.invalidateQueries({ queryKey: [...DAEMONSETS_KEY, ns] })
67-
},
68-
})
27+
const { namespace: defaultNamespace } = useKubernetes()
28+
const mutation = useDeleteAppsV1NamespacedDaemonSet()
29+
return {
30+
...mutation,
31+
mutate: ({ name, namespace }) =>
32+
mutation.mutate({ path: { namespace: namespace || defaultNamespace, name }, query: {} }),
33+
mutateAsync: ({ name, namespace }) =>
34+
mutation.mutateAsync({ path: { namespace: namespace || defaultNamespace, name }, query: {} }),
35+
}
6936
}

0 commit comments

Comments
 (0)