diff --git a/server/index.ts b/server/index.ts index 029ac14..c2de64b 100644 --- a/server/index.ts +++ b/server/index.ts @@ -1,6 +1,7 @@ const path = require('path') const fs = require('fs').promises import express, { Express } from 'express' +import http from 'http' const { createProxyMiddleware } = require('http-proxy-middleware') import dotenv from 'dotenv' import { getDynamicIndex } from './getDynamicIndex' @@ -66,6 +67,16 @@ if (process.env.LOGGER === 'true') { ) } +const bffFormProxy = + process.env.LOCAL === 'true' + ? createProxyMiddleware({ + target: BFF_URL, + changeOrigin: true, + secure: false, + ws: false, + }) + : undefined + // Only add proxies if LOCAL=true if (process.env.LOCAL === 'true') { console.log('✅ Proxies are enabled.') @@ -114,6 +125,9 @@ if (process.env.LOCAL === 'true') { // }, }), ) + + // Proxy: bffFormProxy + app.use('/openapi-bff-ws/forms', bffFormProxy) } else { console.log('🚫 Proxies are disabled.') } @@ -177,6 +191,16 @@ app.get('*', (req, res, next) => { tryFiles(req, res, next) }) -app.listen(port, () => { - console.log(`Server is running on http://localhost:${port}`) +// app.listen(port, () => { +// console.log(`Server is running on http://localhost:${port}`) +// }) +const server = http.createServer(app) +server.listen(port, () => { + console.log(`[server]: Server is running at port: ${port}`) +}) + +server.on('upgrade', (req, socket, head) => { + if (process.env.LOCAL === 'true' && req.url?.indexOf('/openapi-bff-ws/forms') === 0) { + bffFormProxy.upgrade(req, socket, head) + } }) diff --git a/src/App.tsx b/src/App.tsx index 7f1aa1c..c477a60 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,10 +5,8 @@ import { BrowserRouter, Routes, Route } from 'react-router-dom' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { ReactQueryDevtools } from '@tanstack/react-query-devtools' import { ConfigProvider, theme as antdtheme } from 'antd' -import { getSwagger } from '@prorobotech/openapi-k8s-toolkit' import { useSelector, useDispatch } from 'react-redux' import type { RootState } from 'store/store' -import { setSwagger } from 'store/swagger/swagger/swagger' import { setIsFederation } from 'store/federation/federation/federation' import { setBaseprefix } from 'store/federation/federation/baseprefix' import { @@ -42,7 +40,6 @@ const queryClient = new QueryClient() export const App: FC = ({ isFederation, forcedTheme }) => { const dispatch = useDispatch() const theme = useSelector((state: RootState) => state.openapiTheme.theme) - const cluster = useSelector((state: RootState) => state.cluster.cluster) const basePrefix = getBasePrefix(isFederation) @@ -54,20 +51,6 @@ export const App: FC = ({ isFederation, forcedTheme }) => { dispatch(setBaseprefix(basePrefix)) }, [dispatch, isFederation]) - useEffect(() => { - if (!cluster) { - return - } - getSwagger({ clusterName: cluster }) - .then(({ data }) => { - dispatch(setSwagger(data)) - }) - - .catch(error => { - console.log('Swagger: fetch error', error) - }) - }, [cluster, dispatch]) - const renderRoutes = (prefix = '') => ( } /> diff --git a/src/components/molecules/BlackholeForm/BlackholeForm.tsx b/src/components/molecules/BlackholeForm/BlackholeForm.tsx index 41ddabd..8d781b0 100644 --- a/src/components/molecules/BlackholeForm/BlackholeForm.tsx +++ b/src/components/molecules/BlackholeForm/BlackholeForm.tsx @@ -56,7 +56,6 @@ type TBlackholeFormProps = { export const BlackholeForm: FC = ({ data, isCreate, backlink, modeData }) => { const theme = useSelector((state: RootState) => state.openapiTheme.theme) const cluster = useSelector((state: RootState) => state.cluster.cluster) - const swagger = useSelector((state: RootState) => state.swagger.swagger) const params = useParams() const [height, setHeight] = useState(0) @@ -132,7 +131,6 @@ export const BlackholeForm: FC = ({ data, isCreate, backlin urlParams={urlParams} urlParamsForPermissions={urlParamsForPermissions} formsPrefillsData={formsPrefillsData.data} - swagger={swagger} namespacesData={namespacesData.data} formsOverridesData={formsOverridesData.data} data={data} diff --git a/src/components/organisms/ListInsideAllResources/ListInsideAllResources.tsx b/src/components/organisms/ListInsideAllResources/ListInsideAllResources.tsx index 2e61d06..28ae77a 100644 --- a/src/components/organisms/ListInsideAllResources/ListInsideAllResources.tsx +++ b/src/components/organisms/ListInsideAllResources/ListInsideAllResources.tsx @@ -1,4 +1,4 @@ -import React, { FC } from 'react' +import React, { FC, useState, useEffect } from 'react' import { useNavigate } from 'react-router-dom' import { getGroupsByCategory, @@ -8,6 +8,8 @@ import { useApisResourceTypes, useBuiltinResourceTypes, Spacer, + TApiGroupList, + TBuiltinResourceTypeList, } from '@prorobotech/openapi-k8s-toolkit' import { Spin, Alert, Flex } from 'antd' import { useSelector } from 'react-redux' @@ -22,8 +24,13 @@ type TListInsideAllResourcesProps = { export const ListInsideAllResources: FC = ({ namespace }) => { const navigate = useNavigate() const cluster = useSelector((state: RootState) => state.cluster.cluster) - const swagger = useSelector((state: RootState) => state.swagger.swagger) const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix) + const [groupsByCategory, setGroupsByCategory] = useState<{ + crdGroups?: TApiGroupList['groups'] + nonCrdGroups?: TApiGroupList['groups'] + builtinGroups?: TBuiltinResourceTypeList['resources'] + apiExtensionVersion?: string + }>() const apiGroupList = useApisResourceTypes({ clusterName: cluster, @@ -33,12 +40,18 @@ export const ListInsideAllResources: FC = ({ names clusterName: cluster, }) - const { crdGroups, nonCrdGroups, builtinGroups, apiExtensionVersion } = getGroupsByCategory({ - swagger, - namespace, - apiGroupListData: apiGroupList.data, - builtinResourceTypesData: builtInData.data, - }) + useEffect(() => { + getGroupsByCategory({ + clusterName: cluster, + namespace, + apiGroupListData: apiGroupList.data, + builtinResourceTypesData: builtInData.data, + }).then(data => { + setGroupsByCategory(data) + }) + }, [cluster, namespace, apiGroupList.data, builtInData.data]) + + const { crdGroups, nonCrdGroups, builtinGroups, apiExtensionVersion } = groupsByCategory || {} return ( diff --git a/src/components/organisms/ListInsideApisByApiGroup/ListInsideApisByApiGroup.tsx b/src/components/organisms/ListInsideApisByApiGroup/ListInsideApisByApiGroup.tsx index 38f8691..86588bf 100644 --- a/src/components/organisms/ListInsideApisByApiGroup/ListInsideApisByApiGroup.tsx +++ b/src/components/organisms/ListInsideApisByApiGroup/ListInsideApisByApiGroup.tsx @@ -1,7 +1,12 @@ -import React, { FC, Fragment, useState } from 'react' +import React, { FC, Fragment, useState, useEffect } from 'react' import { useNavigate } from 'react-router-dom' import { Spin, Alert, Input, Typography } from 'antd' -import { Spacer, useApiResourceTypesByGroup, checkIfApiInstanceNamespaceScoped } from '@prorobotech/openapi-k8s-toolkit' +import { + Spacer, + useApiResourceTypesByGroup, + TApiGroupResourceTypeList, + filterIfApiInstanceNamespaceScoped, +} from '@prorobotech/openapi-k8s-toolkit' import { useSelector } from 'react-redux' import { RootState } from 'store/store' import { TitleWithNoTopMargin } from 'components/atoms' @@ -15,8 +20,8 @@ type TListInsideApisByApiGroupProps = { export const ListInsideApisByApiGroup: FC = ({ namespace, apiGroup, apiVersion }) => { const cluster = useSelector((state: RootState) => state.cluster.cluster) - const swagger = useSelector((state: RootState) => state.swagger.swagger) const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix) + const [filteredResources, setFilteredResources] = useState() const [limit, setLimit] = useState('') const navigate = useNavigate() @@ -27,13 +32,11 @@ export const ListInsideApisByApiGroup: FC = ({ n apiVersion, }) - const filteredResources = - namespace && swagger - ? data?.resources.filter( - ({ name }) => - checkIfApiInstanceNamespaceScoped({ typeName: name, apiGroup, apiVersion, swagger }).isNamespaceScoped, - ) - : data?.resources + useEffect(() => { + filterIfApiInstanceNamespaceScoped({ namespace, data, apiGroup, apiVersion, clusterName: cluster }).then(data => + setFilteredResources(data), + ) + }, [namespace, data, apiGroup, apiVersion, cluster]) return ( <> diff --git a/src/components/organisms/ListInsideCrdsByApiGroup/ListInsideCrdsByApiGroup.tsx b/src/components/organisms/ListInsideCrdsByApiGroup/ListInsideCrdsByApiGroup.tsx index 6253908..ed850b2 100644 --- a/src/components/organisms/ListInsideCrdsByApiGroup/ListInsideCrdsByApiGroup.tsx +++ b/src/components/organisms/ListInsideCrdsByApiGroup/ListInsideCrdsByApiGroup.tsx @@ -1,10 +1,15 @@ -import React, { FC } from 'react' +import React, { FC, useState, useEffect } from 'react' import { useNavigate } from 'react-router-dom' import { Spin, Alert, Typography } from 'antd' -import { Spacer, useApiResourceTypesByGroup, checkIfApiInstanceNamespaceScoped } from '@prorobotech/openapi-k8s-toolkit' +import { + Spacer, + useApiResourceTypesByGroup, + TApiGroupResourceTypeList, + filterIfApiInstanceNamespaceScoped, +} from '@prorobotech/openapi-k8s-toolkit' import { useSelector } from 'react-redux' -import { TitleWithNoTopMargin } from 'components/atoms' import { RootState } from 'store/store' +import { TitleWithNoTopMargin } from 'components/atoms' type TListInsideCrdsByApiGroupProps = { namespace?: string @@ -21,8 +26,8 @@ export const ListInsideCrdsByApiGroup: FC = ({ }) => { const navigate = useNavigate() const cluster = useSelector((state: RootState) => state.cluster.cluster) - const swagger = useSelector((state: RootState) => state.swagger.swagger) const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix) + const [filteredResources, setFilteredResources] = useState() const { isPending, error, data } = useApiResourceTypesByGroup({ clusterName: cluster, @@ -30,13 +35,11 @@ export const ListInsideCrdsByApiGroup: FC = ({ apiVersion, }) - const filteredResources = - namespace && swagger - ? data?.resources.filter( - ({ name }) => - checkIfApiInstanceNamespaceScoped({ typeName: name, apiGroup, apiVersion, swagger }).isNamespaceScoped, - ) - : data?.resources + useEffect(() => { + filterIfApiInstanceNamespaceScoped({ namespace, data, apiGroup, apiVersion, clusterName: cluster }).then(data => + setFilteredResources(data), + ) + }, [namespace, data, apiGroup, apiVersion, cluster]) return ( <> diff --git a/src/components/organisms/TableBuiltinInfo/TableBuiltinInfo.tsx b/src/components/organisms/TableBuiltinInfo/TableBuiltinInfo.tsx index d62f3a0..972b8e3 100644 --- a/src/components/organisms/TableBuiltinInfo/TableBuiltinInfo.tsx +++ b/src/components/organisms/TableBuiltinInfo/TableBuiltinInfo.tsx @@ -35,7 +35,6 @@ export const TableBuiltinInfo: FC = ({ namespace, typeNa const params = useParams() const cluster = useSelector((state: RootState) => state.cluster.cluster) - const swagger = useSelector((state: RootState) => state.swagger.swagger) const theme = useSelector((state: RootState) => state.openapiTheme.theme) const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix) @@ -75,16 +74,15 @@ export const TableBuiltinInfo: FC = ({ namespace, typeNa }) useEffect(() => { - if (swagger) { - const { isNamespaceScoped } = checkIfBuiltInInstanceNamespaceScoped({ - typeName, - swagger, - }) + checkIfBuiltInInstanceNamespaceScoped({ + typeName, + clusterName: cluster, + }).then(({ isNamespaceScoped }) => { if (isNamespaceScoped) { setIsNamespaced(isNamespaceScoped) } - } - }, [swagger, typeName]) + }) + }, [cluster, typeName]) const { isPending, error, data } = useBuiltinResources({ clusterName: cluster, diff --git a/src/components/organisms/TableCrdInfo/TableCrdInfo.tsx b/src/components/organisms/TableCrdInfo/TableCrdInfo.tsx index 0303e86..08132a1 100644 --- a/src/components/organisms/TableCrdInfo/TableCrdInfo.tsx +++ b/src/components/organisms/TableCrdInfo/TableCrdInfo.tsx @@ -24,7 +24,6 @@ export const TableCrdInfo: FC = ({ inside, }) => { const cluster = useSelector((state: RootState) => state.cluster.cluster) - const swagger = useSelector((state: RootState) => state.swagger.swagger) const [isNamespaced, setIsNamespaced] = useState() @@ -35,18 +34,19 @@ export const TableCrdInfo: FC = ({ }) useEffect(() => { - if (swagger && data && !isPending && !error) { - const { isNamespaceScoped } = checkIfApiInstanceNamespaceScoped({ + if (data && !isPending && !error) { + checkIfApiInstanceNamespaceScoped({ apiGroup, apiVersion, typeName: data.spec.names.plural, - swagger, + clusterName: cluster, + }).then(({ isNamespaceScoped }) => { + if (isNamespaceScoped) { + setIsNamespaced(true) + } }) - if (isNamespaceScoped) { - setIsNamespaced(true) - } } - }, [swagger, data, isPending, error, apiGroup, apiVersion]) + }, [cluster, data, isPending, error, apiGroup, apiVersion]) const createPermission = usePermissions({ apiGroup, diff --git a/src/components/organisms/TableNonCrdInfo/TableNonCrdInfo.tsx b/src/components/organisms/TableNonCrdInfo/TableNonCrdInfo.tsx index f51bec1..d8855f8 100644 --- a/src/components/organisms/TableNonCrdInfo/TableNonCrdInfo.tsx +++ b/src/components/organisms/TableNonCrdInfo/TableNonCrdInfo.tsx @@ -43,7 +43,6 @@ export const TableNonCrdInfo: FC = ({ const { pathname } = useLocation() const params = useParams() const cluster = useSelector((state: RootState) => state.cluster.cluster) - const swagger = useSelector((state: RootState) => state.swagger.swagger) const theme = useSelector((state: RootState) => state.openapiTheme.theme) const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix) @@ -56,18 +55,17 @@ export const TableNonCrdInfo: FC = ({ const [isNamespaced, setIsNamespaced] = useState() useEffect(() => { - if (swagger) { - const { isNamespaceScoped } = checkIfApiInstanceNamespaceScoped({ - apiGroup, - apiVersion, - typeName, - swagger, - }) + checkIfApiInstanceNamespaceScoped({ + apiGroup, + apiVersion, + typeName, + clusterName: cluster, + }).then(({ isNamespaceScoped }) => { if (isNamespaceScoped) { setIsNamespaced(true) } - } - }, [swagger, typeName, apiGroup, apiVersion]) + }) + }, [cluster, typeName, apiGroup, apiVersion]) const createPermission = usePermissions({ apiGroup, diff --git a/src/localTypes/marketplace.ts b/src/localTypes/marketplace.ts deleted file mode 100644 index 416b220..0000000 --- a/src/localTypes/marketplace.ts +++ /dev/null @@ -1,29 +0,0 @@ -export type TMarketPlacePanel = { - name: string - description: string - icon: string - type: 'crd' | 'nonCrd' | 'built-in' | 'direct' - apiGroup?: string - apiVersion?: string - typeName?: string - pathToNav?: string - tags: string[] - disabled?: boolean - hidden?: boolean -} - -export type TMarketPlacePanelResource = { - metadata: { - name: string - resourceVersion: string - uid: string - } - spec: TMarketPlacePanel -} - -export type TMarketPlacePanelResponse = { - metadata: { - name: string - } - items: TMarketPlacePanelResource[] -} diff --git a/src/store/store.ts b/src/store/store.ts index e0b5aa0..01c9607 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -2,7 +2,6 @@ import { configureStore } from '@reduxjs/toolkit' import { themeSlice } from './theme/theme/theme' import { federationSlice } from './federation/federation/federation' import { baseprefixSlice } from './federation/federation/baseprefix' -import { swaggerSlice } from './swagger/swagger/swagger' import { clusterListSlice } from './clusterList/clusterList/clusterList' import { clusterSlice } from './cluster/cluster/cluster' @@ -11,7 +10,6 @@ export const store = configureStore({ openapiTheme: themeSlice.reducer, federation: federationSlice.reducer, baseprefix: baseprefixSlice.reducer, - swagger: swaggerSlice.reducer, clusterList: clusterListSlice.reducer, cluster: clusterSlice.reducer, }, diff --git a/src/store/swagger/swagger/swagger.ts b/src/store/swagger/swagger/swagger.ts deleted file mode 100644 index 12bdf35..0000000 --- a/src/store/swagger/swagger/swagger.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* eslint-disable no-param-reassign */ -import { OpenAPIV2 } from 'openapi-types' -import { createSlice } from '@reduxjs/toolkit' -import type { PayloadAction } from '@reduxjs/toolkit' - -export type TState = { - swagger: OpenAPIV2.Document | undefined -} - -const initialState: TState = { - swagger: undefined, -} - -export const swaggerSlice = createSlice({ - name: 'swagger', - initialState, - reducers: { - setSwagger: (state, action: PayloadAction) => { - state.swagger = action.payload - }, - }, -}) - -export const { setSwagger } = swaggerSlice.actions