From d10c21bbf7fbfcd61b3a757b074ab44973a86938 Mon Sep 17 00:00:00 2001 From: Yaroslav Grishajev Date: Thu, 28 Nov 2024 14:30:45 +0100 Subject: [PATCH 1/5] refactor(template): utilize new GET /v1/templates/{id} endpoint for template and deployment detail refs #477 --- .commitlintrc.json | 3 +- apps/api/src/routes/v1/templates/byId.ts | 28 ++++++------ .../deployments/DeploymentDetail.tsx | 16 ++++--- .../components/templates/TemplateDetail.tsx | 44 +++++++++---------- .../context/WalletProvider/WalletProvider.tsx | 2 +- .../src/pages/deployments/[dseq]/index.tsx | 30 ++++++++----- .../src/pages/profile/[username]/index.tsx | 4 +- .../pages/templates/[templateId]/index.tsx | 39 +++++++--------- .../src/queries/useAnonymousUserQuery.ts | 2 +- .../src/queries/useStripePricesQuery.ts | 2 +- .../http-factory/http-factory.service.ts | 31 +++++++++++++ .../src/services/http/http-browser.service.ts | 8 ++++ .../src/services/http/http-server.service.ts | 4 ++ .../src/services/http/http.service.ts | 25 ----------- .../src/template/template-http.service.ts | 29 ++++++++++++ 15 files changed, 158 insertions(+), 109 deletions(-) create mode 100644 apps/deploy-web/src/services/http-factory/http-factory.service.ts create mode 100644 apps/deploy-web/src/services/http/http-browser.service.ts create mode 100644 apps/deploy-web/src/services/http/http-server.service.ts delete mode 100644 apps/deploy-web/src/services/http/http.service.ts create mode 100644 packages/http-sdk/src/template/template-http.service.ts diff --git a/.commitlintrc.json b/.commitlintrc.json index 60b0b0b68..8ad736340 100644 --- a/.commitlintrc.json +++ b/.commitlintrc.json @@ -21,7 +21,8 @@ "repo", "styling", "observability", - "analytics" + "analytics", + "template" ] ] } diff --git a/apps/api/src/routes/v1/templates/byId.ts b/apps/api/src/routes/v1/templates/byId.ts index 79afe58a5..6fdb2c8c4 100644 --- a/apps/api/src/routes/v1/templates/byId.ts +++ b/apps/api/src/routes/v1/templates/byId.ts @@ -20,18 +20,20 @@ const route = createRoute({ content: { "application/json": { schema: z.object({ - id: z.string(), - name: z.string(), - path: z.string(), - logoUrl: z.string().nullable(), - summary: z.string(), - readme: z.string().nullable(), - deploy: z.string(), - persistentStorageEnabled: z.boolean(), - guide: z.string().nullable(), - githubUrl: z.string(), - config: z.object({ - ssh: z.boolean().optional() + data: z.object({ + id: z.string(), + name: z.string(), + path: z.string(), + logoUrl: z.string().nullable(), + summary: z.string(), + readme: z.string().nullable(), + deploy: z.string(), + persistentStorageEnabled: z.boolean(), + guide: z.string().nullable(), + githubUrl: z.string(), + config: z.object({ + ssh: z.boolean().optional() + }) }) }) } @@ -51,5 +53,5 @@ export default new OpenAPIHono().openapi(route, async c => { return c.text("Template not found", 404); } - return c.json(template); + return c.json({ data: template }); }); diff --git a/apps/deploy-web/src/components/deployments/DeploymentDetail.tsx b/apps/deploy-web/src/components/deployments/DeploymentDetail.tsx index cd7ca3ec9..4ffe8e226 100644 --- a/apps/deploy-web/src/components/deployments/DeploymentDetail.tsx +++ b/apps/deploy-web/src/components/deployments/DeploymentDetail.tsx @@ -1,6 +1,7 @@ "use client"; -import { createRef, useEffect, useState } from "react"; +import { createRef, FC, useEffect, useState } from "react"; +import type { TemplateOutput } from "@akashnetwork/http-sdk/src/template/template-http.service"; import { Alert, Button, buttonVariants, Spinner, Tabs, TabsList, TabsTrigger } from "@akashnetwork/ui/components"; import { cn } from "@akashnetwork/ui/utils"; import { ArrowLeft } from "iconoir-react"; @@ -9,10 +10,8 @@ import { useRouter, useSearchParams } from "next/navigation"; import { NextSeo } from "next-seo"; import { event } from "nextjs-google-analytics"; -import { CI_CD_TEMPLATE_ID } from "@src/config/remote-deploy.config"; import { useCertificate } from "@src/context/CertificateProvider"; import { useSettings } from "@src/context/SettingsProvider"; -import { useTemplates } from "@src/context/TemplatesProvider"; import { useWallet } from "@src/context/WalletProvider"; import { useDeploymentDetail } from "@src/queries/useDeploymentQuery"; import { useDeploymentLeaseList } from "@src/queries/useLeaseQuery"; @@ -31,7 +30,12 @@ import { DeploymentSubHeader } from "./DeploymentSubHeader"; import { LeaseRow } from "./LeaseRow"; import { ManifestUpdate } from "./ManifestUpdate"; -export function DeploymentDetail({ dseq }: React.PropsWithChildren<{ dseq: string }>) { +export interface DeploymentDetailProps { + dseq: string; + remoteDeployTemplate: TemplateOutput; +} + +export const DeploymentDetail: FC = ({ dseq, remoteDeployTemplate }) => { const router = useRouter(); const [activeTab, setActiveTab] = useState("LEASES"); const [editedManifest, setEditedManifest] = useState(null); @@ -39,8 +43,6 @@ export function DeploymentDetail({ dseq }: React.PropsWithChildren<{ dseq: strin const { isSettingsInit } = useSettings(); const [leaseRefs, setLeaseRefs] = useState>([]); const [deploymentManifest, setDeploymentManifest] = useState(null); - const { getTemplateById } = useTemplates(); - const remoteDeployTemplate = getTemplateById(CI_CD_TEMPLATE_ID); const isRemoteDeploy: boolean = !!editedManifest && !!isImageInYaml(editedManifest, remoteDeployTemplate?.deploy); const repo: string | null = isRemoteDeploy ? extractRepositoryUrl(editedManifest) : null; @@ -255,4 +257,4 @@ export function DeploymentDetail({ dseq }: React.PropsWithChildren<{ dseq: strin )} ); -} +}; diff --git a/apps/deploy-web/src/components/templates/TemplateDetail.tsx b/apps/deploy-web/src/components/templates/TemplateDetail.tsx index d38ab6e9d..85e654424 100644 --- a/apps/deploy-web/src/components/templates/TemplateDetail.tsx +++ b/apps/deploy-web/src/components/templates/TemplateDetail.tsx @@ -1,5 +1,6 @@ "use client"; -import { useState } from "react"; + +import { FC, useCallback, useState } from "react"; import { Button, buttonVariants, Tabs, TabsList, TabsTrigger } from "@akashnetwork/ui/components"; import { cn } from "@akashnetwork/ui/utils"; import GitHubIcon from "@mui/icons-material/GitHub"; @@ -8,10 +9,8 @@ import Link from "next/link"; import { useRouter } from "next/navigation"; import { DynamicMonacoEditor } from "@src/components/shared/DynamicMonacoEditor"; -import { LinearLoadingSkeleton } from "@src/components/shared/LinearLoadingSkeleton"; import Markdown from "@src/components/shared/Markdown"; import ViewPanel from "@src/components/shared/ViewPanel"; -import { useTemplates } from "@src/context/TemplatesProvider"; import { usePreviousRoute } from "@src/hooks/usePreviousRoute"; import { getShortText } from "@src/hooks/useShortText"; import { ApiTemplate } from "@src/types"; @@ -20,37 +19,35 @@ import { domainName, UrlService } from "@src/utils/urlUtils"; import Layout from "../layout/Layout"; import { CustomNextSeo } from "../shared/CustomNextSeo"; -type Props = { +export interface TemplateDetailProps { templateId: string; template: ApiTemplate; -}; +} -export const TemplateDetail: React.FunctionComponent = ({ templateId, template }) => { +export const TemplateDetail: FC = ({ templateId, template }) => { const [activeTab, setActiveTab] = useState("README"); - const { getTemplateById, isLoading } = useTemplates(); const router = useRouter(); - const _template = template || getTemplateById(templateId); const previousRoute = usePreviousRoute(); - function handleBackClick() { + const goBack = useCallback(() => { if (previousRoute) { router.back(); } else { router.push(UrlService.templates()); } - } + }, [previousRoute, router]); - function handleOpenGithub() { - window.open(_template.githubUrl, "_blank"); - } + const openGithub = useCallback(() => { + window.open(template.githubUrl, "_blank"); + }, [template]); return (
@@ -61,32 +58,31 @@ export const TemplateDetail: React.FunctionComponent = ({ templateId, tem View SDL - {_template?.guide && ( + {template.guide && ( Guide )} -
-
-

{_template?.name}

+

{template.name}

-
Deploy  @@ -97,21 +93,21 @@ export const TemplateDetail: React.FunctionComponent = ({ templateId, tem {activeTab === "README" && (
- {_template?.readme} + {template.readme}
)} {activeTab === "SDL" && (
- +
)} {activeTab === "GUIDE" && (
- {_template?.guide} + {template.guide}
)} diff --git a/apps/deploy-web/src/context/WalletProvider/WalletProvider.tsx b/apps/deploy-web/src/context/WalletProvider/WalletProvider.tsx index 7c0d43a2a..0ee880187 100644 --- a/apps/deploy-web/src/context/WalletProvider/WalletProvider.tsx +++ b/apps/deploy-web/src/context/WalletProvider/WalletProvider.tsx @@ -19,7 +19,7 @@ import { useManagedWallet } from "@src/hooks/useManagedWallet"; import { useUser } from "@src/hooks/useUser"; import { useWhen } from "@src/hooks/useWhen"; import { useBalances } from "@src/queries/useBalancesQuery"; -import { txHttpService } from "@src/services/http/http.service"; +import { txHttpService } from "@src/services/http/http-browser.service"; import networkStore from "@src/store/networkStore"; import walletStore from "@src/store/walletStore"; import { AnalyticsCategory, AnalyticsEvents } from "@src/types/analytics"; diff --git a/apps/deploy-web/src/pages/deployments/[dseq]/index.tsx b/apps/deploy-web/src/pages/deployments/[dseq]/index.tsx index 29f44ab3a..e6e2d2e31 100644 --- a/apps/deploy-web/src/pages/deployments/[dseq]/index.tsx +++ b/apps/deploy-web/src/pages/deployments/[dseq]/index.tsx @@ -1,19 +1,27 @@ -import { DeploymentDetail } from "@src/components/deployments/DeploymentDetail"; +import type { GetServerSideProps } from "next"; +import { z } from "zod"; -type Props = { - dseq: string; -}; +import { DeploymentDetail, DeploymentDetailProps } from "@src/components/deployments/DeploymentDetail"; +import { CI_CD_TEMPLATE_ID } from "@src/config/remote-deploy.config"; +import { services } from "@src/services/http/http-server.service"; -const DeploymentDetailPage: React.FunctionComponent = ({ dseq }) => { - return ; -}; +export default DeploymentDetail; -export default DeploymentDetailPage; +const contextSchema = z.object({ + params: z.object({ + dseq: z.string() + }) +}); +type Params = z.infer["params"]; + +export const getServerSideProps: GetServerSideProps = async context => { + const { params } = contextSchema.parse(context); + const remoteDeployTemplate = await services.template.findById(CI_CD_TEMPLATE_ID); -export async function getServerSideProps({ params }) { return { props: { - dseq: params?.dseq + remoteDeployTemplate, + dseq: params.dseq } }; -} +}; diff --git a/apps/deploy-web/src/pages/profile/[username]/index.tsx b/apps/deploy-web/src/pages/profile/[username]/index.tsx index 96fc5ae5b..7db42cd05 100644 --- a/apps/deploy-web/src/pages/profile/[username]/index.tsx +++ b/apps/deploy-web/src/pages/profile/[username]/index.tsx @@ -1,7 +1,7 @@ import axios from "axios"; import { UserProfile } from "@src/components/user/UserProfile"; -import { browserEnvConfig } from "@src/config/browser-env.config"; +import { serverEnvConfig } from "@src/config/server-env.config"; import { IUserSetting } from "@src/types/user"; type Props = { @@ -37,6 +37,6 @@ export async function getServerSideProps({ params }) { } async function fetchUser(username: string) { - const response = await axios.get(`${browserEnvConfig.NEXT_PUBLIC_BASE_API_MAINNET_URL}/user/byUsername/${username}`); + const response = await axios.get(`${serverEnvConfig.BASE_API_MAINNET_URL}/user/byUsername/${username}`); return response.data; } diff --git a/apps/deploy-web/src/pages/templates/[templateId]/index.tsx b/apps/deploy-web/src/pages/templates/[templateId]/index.tsx index 4868a8b65..a6e64e47f 100644 --- a/apps/deploy-web/src/pages/templates/[templateId]/index.tsx +++ b/apps/deploy-web/src/pages/templates/[templateId]/index.tsx @@ -1,28 +1,21 @@ -import axios from "axios"; +import type { GetServerSideProps } from "next"; +import { z } from "zod"; -import { TemplateDetail } from "@src/components/templates/TemplateDetail"; -import { serverEnvConfig } from "@src/config/server-env.config"; -import { ApiTemplate } from "@src/types"; +import { TemplateDetail, TemplateDetailProps } from "@src/components/templates/TemplateDetail"; +import { services } from "@src/services/http/http-server.service"; -type Props = { - templateId: string; - template: ApiTemplate; -}; - -const TemplateDetailPage: React.FunctionComponent = ({ templateId, template }) => { - return ; -}; +export default TemplateDetail; -export default TemplateDetailPage; +const contextSchema = z.object({ + params: z.object({ + templateId: z.string() + }) +}); +type Params = z.infer["params"]; -export async function getServerSideProps({ params }) { - const response = await axios.get(`${serverEnvConfig.BASE_API_MAINNET_URL}/templates`); - const categories = response.data.filter(x => (x.templates || []).length > 0); - categories.forEach(c => { - c.templates.forEach(t => (t.category = c.title)); - }); - const templates = categories.flatMap(x => x.templates); - const template = templates.find(x => x.id === params?.templateId); +export const getServerSideProps: GetServerSideProps = async context => { + const { params } = contextSchema.parse(context); + const template = await services.template.findById(params.templateId); if (!template) { return { @@ -32,8 +25,8 @@ export async function getServerSideProps({ params }) { return { props: { - templateId: params?.templateId, + templateId: params.templateId, template } }; -} +}; diff --git a/apps/deploy-web/src/queries/useAnonymousUserQuery.ts b/apps/deploy-web/src/queries/useAnonymousUserQuery.ts index 002d13596..5f05edaaf 100644 --- a/apps/deploy-web/src/queries/useAnonymousUserQuery.ts +++ b/apps/deploy-web/src/queries/useAnonymousUserQuery.ts @@ -2,7 +2,7 @@ import { useState } from "react"; import * as Sentry from "@sentry/nextjs"; import { useWhen } from "@src/hooks/useWhen"; -import { userHttpService } from "@src/services/http/http.service"; +import { userHttpService } from "@src/services/http/http-browser.service"; export interface UserOutput { id: string; diff --git a/apps/deploy-web/src/queries/useStripePricesQuery.ts b/apps/deploy-web/src/queries/useStripePricesQuery.ts index e2a045816..81bef3703 100644 --- a/apps/deploy-web/src/queries/useStripePricesQuery.ts +++ b/apps/deploy-web/src/queries/useStripePricesQuery.ts @@ -1,6 +1,6 @@ import { useQuery } from "react-query"; -import { stripeService } from "@src/services/http/http.service"; +import { stripeService } from "@src/services/http/http-browser.service"; export function useStripePricesQuery({ enabled = true } = {}) { return useQuery(["StripePrices"], () => stripeService.findPrices(), { diff --git a/apps/deploy-web/src/services/http-factory/http-factory.service.ts b/apps/deploy-web/src/services/http-factory/http-factory.service.ts new file mode 100644 index 000000000..547661c6d --- /dev/null +++ b/apps/deploy-web/src/services/http-factory/http-factory.service.ts @@ -0,0 +1,31 @@ +import { TxHttpService, UserHttpService } from "@akashnetwork/http-sdk"; +import { StripeService } from "@akashnetwork/http-sdk/src/stripe/stripe.service"; +import { TemplateHttpService } from "@akashnetwork/http-sdk/src/template/template-http.service"; +import { event } from "nextjs-google-analytics"; + +import type { BrowserEnvConfig, ServerEnvConfig } from "@src/config/env-config.schema"; +import { authService } from "@src/services/auth/auth.service"; +import { AnalyticsCategory, AnalyticsEvents } from "@src/types/analytics"; +import { customRegistry } from "@src/utils/customRegistry"; + +export const createServices = (config: Pick | Pick) => { + const apiConfig = { baseURL: "BASE_API_MAINNET_URL" in config ? config.BASE_API_MAINNET_URL : config.NEXT_PUBLIC_BASE_API_MAINNET_URL }; + + const user = new UserHttpService(apiConfig); + const stripe = new StripeService(apiConfig); + const tx = new TxHttpService(customRegistry, apiConfig); + const template = new TemplateHttpService(apiConfig); + + user.interceptors.request.use(authService.withAnonymousUserHeader); + stripe.interceptors.request.use(authService.withAnonymousUserHeader); + tx.interceptors.request.use(authService.withAnonymousUserHeader); + + user.interceptors.response.use(response => { + if (response.config.url?.startsWith("/v1/anonymous-users") && response.config.method === "post" && response.status === 200) { + event(AnalyticsEvents.ANONYMOUS_USER_CREATED, { category: AnalyticsCategory.USER, label: "Anonymous User Created" }); + } + return response; + }); + + return { user, stripe, tx, template }; +}; diff --git a/apps/deploy-web/src/services/http/http-browser.service.ts b/apps/deploy-web/src/services/http/http-browser.service.ts new file mode 100644 index 000000000..b22e87613 --- /dev/null +++ b/apps/deploy-web/src/services/http/http-browser.service.ts @@ -0,0 +1,8 @@ +import { browserEnvConfig } from "@src/config/browser-env.config"; +import { createServices } from "@src/services/http-factory/http-factory.service"; + +export const services = createServices(browserEnvConfig); + +export const userHttpService = services.user; +export const stripeService = services.stripe; +export const txHttpService = services.tx; diff --git a/apps/deploy-web/src/services/http/http-server.service.ts b/apps/deploy-web/src/services/http/http-server.service.ts new file mode 100644 index 000000000..08498ea7d --- /dev/null +++ b/apps/deploy-web/src/services/http/http-server.service.ts @@ -0,0 +1,4 @@ +import { serverEnvConfig } from "@src/config/server-env.config"; +import { createServices } from "@src/services/http-factory/http-factory.service"; + +export const services = createServices(serverEnvConfig); diff --git a/apps/deploy-web/src/services/http/http.service.ts b/apps/deploy-web/src/services/http/http.service.ts deleted file mode 100644 index 4f78f697a..000000000 --- a/apps/deploy-web/src/services/http/http.service.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { TxHttpService, UserHttpService } from "@akashnetwork/http-sdk"; -import { StripeService } from "@akashnetwork/http-sdk/src/stripe/stripe.service"; -import { event } from "nextjs-google-analytics"; - -import { browserEnvConfig } from "@src/config/browser-env.config"; -import { authService } from "@src/services/auth/auth.service"; -import { AnalyticsCategory, AnalyticsEvents } from "@src/types/analytics"; -import { customRegistry } from "@src/utils/customRegistry"; - -const apiConfig = { baseURL: browserEnvConfig.NEXT_PUBLIC_API_BASE_URL }; - -export const userHttpService = new UserHttpService(apiConfig); -export const stripeService = new StripeService(apiConfig); -export const txHttpService = new TxHttpService(customRegistry, apiConfig); - -userHttpService.interceptors.request.use(authService.withAnonymousUserHeader); -stripeService.interceptors.request.use(authService.withAnonymousUserHeader); -txHttpService.interceptors.request.use(authService.withAnonymousUserHeader); - -userHttpService.interceptors.response.use(response => { - if (response.config.url?.startsWith("/v1/anonymous-users") && response.config.method === "post" && response.status === 200) { - event(AnalyticsEvents.ANONYMOUS_USER_CREATED, { category: AnalyticsCategory.USER, label: "Anonymous User Created" }); - } - return response; -}); diff --git a/packages/http-sdk/src/template/template-http.service.ts b/packages/http-sdk/src/template/template-http.service.ts new file mode 100644 index 000000000..6f938f32d --- /dev/null +++ b/packages/http-sdk/src/template/template-http.service.ts @@ -0,0 +1,29 @@ +import type { AxiosRequestConfig } from "axios"; + +import { ApiHttpService } from "../api-http/api-http.service"; + +export interface TemplateOutput { + id: string; + name: string; + path: string; + logoUrl: string; + summary: string; + readme: string; + deploy: string; + persistentStorageEnabled: boolean; + guide: string; + githubUrl: string; + config: { + ssh?: boolean; + }; +} + +export class TemplateHttpService extends ApiHttpService { + constructor(config?: Pick) { + super(config); + } + + async findById(id: string) { + return await this.extractApiData(await this.get(`/v1/templates/${id}`)); + } +} From 8c46a87d88413d6ee44dc41de993353c9d949e2e Mon Sep 17 00:00:00 2001 From: Yaroslav Grishajev Date: Thu, 28 Nov 2024 15:00:55 +0100 Subject: [PATCH 2/5] refactor: add getServerSideProps validation --- .../lib/nextjs/getValidatedServerSIdeProps.ts | 20 +++++++++++++++++++ .../src/pages/deployments/[dseq]/index.tsx | 12 +++++------ .../pages/templates/[templateId]/index.tsx | 8 +++----- 3 files changed, 28 insertions(+), 12 deletions(-) create mode 100644 apps/deploy-web/src/lib/nextjs/getValidatedServerSIdeProps.ts diff --git a/apps/deploy-web/src/lib/nextjs/getValidatedServerSIdeProps.ts b/apps/deploy-web/src/lib/nextjs/getValidatedServerSIdeProps.ts new file mode 100644 index 000000000..537c74227 --- /dev/null +++ b/apps/deploy-web/src/lib/nextjs/getValidatedServerSIdeProps.ts @@ -0,0 +1,20 @@ +import { GetServerSidePropsContext, GetServerSidePropsResult, PreviewData } from "next/types"; +import type { ParsedUrlQuery } from "querystring"; +import { z } from "zod"; + +export const getValidatedServerSideProps = < + Props extends { [key: string]: any } = { [key: string]: any }, + Params extends ParsedUrlQuery = ParsedUrlQuery, + Preview extends PreviewData = PreviewData, + Schema extends z.ZodObject = z.ZodObject<{ params: z.ZodObject }, any, any> +>( + schema: Schema, + handler: ( + context: Omit, "params"> & { params: z.infer["params"] } + ) => Promise> +): ((context: GetServerSidePropsContext) => Promise>) => { + return context => { + const { params } = schema.parse(context); + return handler({ ...context, params }); + }; +}; diff --git a/apps/deploy-web/src/pages/deployments/[dseq]/index.tsx b/apps/deploy-web/src/pages/deployments/[dseq]/index.tsx index e6e2d2e31..f80655361 100644 --- a/apps/deploy-web/src/pages/deployments/[dseq]/index.tsx +++ b/apps/deploy-web/src/pages/deployments/[dseq]/index.tsx @@ -1,21 +1,19 @@ -import type { GetServerSideProps } from "next"; import { z } from "zod"; -import { DeploymentDetail, DeploymentDetailProps } from "@src/components/deployments/DeploymentDetail"; +import { DeploymentDetail } from "@src/components/deployments/DeploymentDetail"; import { CI_CD_TEMPLATE_ID } from "@src/config/remote-deploy.config"; +import { getValidatedServerSideProps } from "@src/lib/nextjs/getValidatedServerSIdeProps"; import { services } from "@src/services/http/http-server.service"; export default DeploymentDetail; const contextSchema = z.object({ params: z.object({ - dseq: z.string() + dseq: z.string().regex(/^\d+$/) }) }); -type Params = z.infer["params"]; -export const getServerSideProps: GetServerSideProps = async context => { - const { params } = contextSchema.parse(context); +export const getServerSideProps = getValidatedServerSideProps(contextSchema, async ({ params }) => { const remoteDeployTemplate = await services.template.findById(CI_CD_TEMPLATE_ID); return { @@ -24,4 +22,4 @@ export const getServerSideProps: GetServerSideProps["params"]; -export const getServerSideProps: GetServerSideProps = async context => { - const { params } = contextSchema.parse(context); +export const getServerSideProps = getValidatedServerSideProps(contextSchema, async ({ params }) => { const template = await services.template.findById(params.templateId); if (!template) { @@ -29,4 +27,4 @@ export const getServerSideProps: GetServerSideProps template } }; -}; +}); From dd11772c3567b41673c93f44d0763d75630e4644 Mon Sep 17 00:00:00 2001 From: Yaroslav Grishajev Date: Fri, 29 Nov 2024 09:29:01 +0100 Subject: [PATCH 3/5] refactor(template): use env var for cicd template check refs #477 --- apps/deploy-web/env/.env | 4 +- .../deployments/DeploymentDetail.tsx | 8 +-- .../new-deployment/NewDeploymentContainer.tsx | 61 +++++++++---------- .../update/RemoteDeployUpdate.tsx | 13 ++-- .../src/config/browser-env.config.ts | 3 +- .../src/config/env-config.schema.ts | 6 +- .../SdlBuilderProvider/SdlBuilderProvider.tsx | 2 +- .../lib/nextjs/getValidatedServerSIdeProps.ts | 24 ++++---- .../src/pages/deploy-linux/index.tsx | 3 + .../src/pages/deployments/[dseq]/index.tsx | 5 -- .../src/pages/new-deployment/index.tsx | 26 +++++++- apps/deploy-web/src/queries/queryKeys.ts | 1 + .../src/queries/useTemplateQuery.tsx | 7 +++ .../remote-deployment-controller.service.ts | 5 +- package-lock.json | 2 +- 15 files changed, 96 insertions(+), 74 deletions(-) diff --git a/apps/deploy-web/env/.env b/apps/deploy-web/env/.env index 9a707a612..c83a5625b 100644 --- a/apps/deploy-web/env/.env +++ b/apps/deploy-web/env/.env @@ -10,4 +10,6 @@ NEXT_PUBLIC_REDIRECT_URI='https://console.akash.network/new-deployment' NEXT_PUBLIC_GITHUB_APP_INSTALLATION_URL='https://github.com/apps/akash-console-build-and-deploy-app/installations/new' NEXT_PUBLIC_BITBUCKET_CLIENT_ID=tdH2xfRkTcdqVP6cwW NEXT_PUBLIC_GITHUB_CLIENT_ID=Iv23lidSwihrsSL7aGew -NEXT_PUBLIC_GITLAB_CLIENT_ID=beb5370aad2fdb6147edb44248d20d30c3e189ddfb40c26f651c77bbe949d5a8 \ No newline at end of file +NEXT_PUBLIC_GITLAB_CLIENT_ID=beb5370aad2fdb6147edb44248d20d30c3e189ddfb40c26f651c77bbe949d5a8 + +NEXT_PUBLIC_CI_CD_IMAGE_NAME=hoomanhq/automation \ No newline at end of file diff --git a/apps/deploy-web/src/components/deployments/DeploymentDetail.tsx b/apps/deploy-web/src/components/deployments/DeploymentDetail.tsx index 4ffe8e226..d0971795b 100644 --- a/apps/deploy-web/src/components/deployments/DeploymentDetail.tsx +++ b/apps/deploy-web/src/components/deployments/DeploymentDetail.tsx @@ -1,7 +1,6 @@ "use client"; import { createRef, FC, useEffect, useState } from "react"; -import type { TemplateOutput } from "@akashnetwork/http-sdk/src/template/template-http.service"; import { Alert, Button, buttonVariants, Spinner, Tabs, TabsList, TabsTrigger } from "@akashnetwork/ui/components"; import { cn } from "@akashnetwork/ui/utils"; import { ArrowLeft } from "iconoir-react"; @@ -16,7 +15,7 @@ import { useWallet } from "@src/context/WalletProvider"; import { useDeploymentDetail } from "@src/queries/useDeploymentQuery"; import { useDeploymentLeaseList } from "@src/queries/useLeaseQuery"; import { useProviderList } from "@src/queries/useProvidersQuery"; -import { extractRepositoryUrl, isImageInYaml } from "@src/services/remote-deploy/remote-deployment-controller.service"; +import { extractRepositoryUrl, isCiCdImageInYaml } from "@src/services/remote-deploy/remote-deployment-controller.service"; import { AnalyticsCategory, AnalyticsEvents } from "@src/types/analytics"; import { RouteStep } from "@src/types/route-steps.type"; import { getDeploymentLocalData } from "@src/utils/deploymentLocalDataUtils"; @@ -32,10 +31,9 @@ import { ManifestUpdate } from "./ManifestUpdate"; export interface DeploymentDetailProps { dseq: string; - remoteDeployTemplate: TemplateOutput; } -export const DeploymentDetail: FC = ({ dseq, remoteDeployTemplate }) => { +export const DeploymentDetail: FC = ({ dseq }) => { const router = useRouter(); const [activeTab, setActiveTab] = useState("LEASES"); const [editedManifest, setEditedManifest] = useState(null); @@ -43,7 +41,7 @@ export const DeploymentDetail: FC = ({ dseq, remoteDeploy const { isSettingsInit } = useSettings(); const [leaseRefs, setLeaseRefs] = useState>([]); const [deploymentManifest, setDeploymentManifest] = useState(null); - const isRemoteDeploy: boolean = !!editedManifest && !!isImageInYaml(editedManifest, remoteDeployTemplate?.deploy); + const isRemoteDeploy: boolean = !!editedManifest && !!isCiCdImageInYaml(editedManifest); const repo: string | null = isRemoteDeploy ? extractRepositoryUrl(editedManifest) : null; const { diff --git a/apps/deploy-web/src/components/new-deployment/NewDeploymentContainer.tsx b/apps/deploy-web/src/components/new-deployment/NewDeploymentContainer.tsx index d772e4a07..ef1c47563 100644 --- a/apps/deploy-web/src/components/new-deployment/NewDeploymentContainer.tsx +++ b/apps/deploy-web/src/components/new-deployment/NewDeploymentContainer.tsx @@ -1,5 +1,6 @@ "use client"; -import { FC, useEffect, useState } from "react"; +import { FC, useCallback, useEffect, useState } from "react"; +import { TemplateOutput } from "@akashnetwork/http-sdk/src/template/template-http.service"; import { useAtomValue } from "jotai"; import { useRouter, useSearchParams } from "next/navigation"; @@ -8,7 +9,7 @@ import { CI_CD_TEMPLATE_ID } from "@src/config/remote-deploy.config"; import { useLocalNotes } from "@src/context/LocalNoteProvider"; import { useSdlBuilder } from "@src/context/SdlBuilderProvider"; import { useTemplates } from "@src/context/TemplatesProvider"; -import { isImageInYaml } from "@src/services/remote-deploy/remote-deployment-controller.service"; +import { isCiCdImageInYaml } from "@src/services/remote-deploy/remote-deployment-controller.service"; import sdlStore from "@src/store/sdlStore"; import { TemplateCreation } from "@src/types"; import { RouteStep } from "@src/types/route-steps.type"; @@ -20,7 +21,12 @@ import { ManifestEdit } from "./ManifestEdit"; import { CustomizedSteppers } from "./Stepper"; import { TemplateList } from "./TemplateList"; -export const NewDeploymentContainer: FC = () => { +export interface NewDeploymentContainerProps { + template?: TemplateOutput; + templateId?: string; +} + +export const NewDeploymentContainer: FC = ({ template: requestedTemplate, templateId }) => { const [isGitProviderTemplate, setIsGitProviderTemplate] = useState(false); const { isLoading: isLoadingTemplates, templates } = useTemplates(); const [activeStep, setActiveStep] = useState(null); @@ -28,7 +34,6 @@ export const NewDeploymentContainer: FC = () => { const [editedManifest, setEditedManifest] = useState(null); const deploySdl = useAtomValue(sdlStore.deploySdl); const { getDeploymentData } = useLocalNotes(); - const { getTemplateById } = useTemplates(); const router = useRouter(); const searchParams = useSearchParams(); const dseq = searchParams?.get("dseq"); @@ -78,8 +83,7 @@ export const NewDeploymentContainer: FC = () => { toggleCmp("ssh"); } - const cicdTemplate = getTemplateById(CI_CD_TEMPLATE_ID); - const isRemoteYamlImage = isImageInYaml(template?.content as string, cicdTemplate?.deploy); + const isRemoteYamlImage = isCiCdImageInYaml(template?.content as string); const queryStep = searchParams?.get("step"); if (queryStep !== RouteStep.editDeployment) { if (isRemoteYamlImage) { @@ -113,34 +117,25 @@ export const NewDeploymentContainer: FC = () => { return template; }; - const getGalleryTemplate = (): Partial<{ - code: string; - name: string; - content: string; - valuesToChange: any[]; - config: { ssh?: boolean }; - }> | null => { - const queryTemplateId = searchParams?.get("templateId"); - if (queryTemplateId) { - const templateById = getTemplateById(queryTemplateId as string); - if (templateById) { - return { + const getGalleryTemplate = useCallback((): + | Partial<{ + code: string; + name: string; + content: string; + valuesToChange: any[]; + config: { ssh?: boolean }; + }> + | undefined => { + return requestedTemplate + ? { code: "empty", - name: templateById.name, - content: templateById.deploy, - valuesToChange: templateById.valuesToChange || [], - config: templateById.config - }; - } - - const hardCodedTemplate = hardcodedTemplates.find(t => t.code === queryTemplateId); - if (hardCodedTemplate) { - return hardCodedTemplate; - } - } - - return null; - }; + name: requestedTemplate.name, + content: requestedTemplate.deploy, + valuesToChange: [], + config: requestedTemplate.config + } + : hardcodedTemplates.find(t => t.code === templateId); + }, [requestedTemplate, templateId]); function getStepIndexByParam(step: (typeof RouteStep)[keyof typeof RouteStep] | null) { switch (step) { diff --git a/apps/deploy-web/src/components/remote-deploy/update/RemoteDeployUpdate.tsx b/apps/deploy-web/src/components/remote-deploy/update/RemoteDeployUpdate.tsx index f1d8c600c..ab242e426 100644 --- a/apps/deploy-web/src/components/remote-deploy/update/RemoteDeployUpdate.tsx +++ b/apps/deploy-web/src/components/remote-deploy/update/RemoteDeployUpdate.tsx @@ -6,9 +6,9 @@ import { useSnackbar } from "notistack"; import { EnvFormModal } from "@src/components/sdl/EnvFormModal"; import { EnvVarList } from "@src/components/sdl/EnvVarList"; -import { CI_CD_TEMPLATE_ID, CURRENT_SERVICE, protectedEnvironmentVariables } from "@src/config/remote-deploy.config"; +import { browserEnvConfig } from "@src/config/browser-env.config"; +import { CURRENT_SERVICE, protectedEnvironmentVariables } from "@src/config/remote-deploy.config"; import { SdlBuilderProvider } from "@src/context/SdlBuilderProvider"; -import { useTemplates } from "@src/context/TemplatesProvider"; import { EnvVarUpdater } from "@src/services/remote-deploy/remote-deployment-controller.service"; import { tokens } from "@src/store/remoteDeployStore"; import { SdlBuilderFormValuesType, ServiceType } from "@src/types"; @@ -26,8 +26,6 @@ const RemoteDeployUpdate = ({ sdlString, onManifestChange }: { sdlString: string const [isEditingEnv, setIsEditingEnv] = useState(false); const { control, watch, setValue } = useForm({ defaultValues: { services: [defaultService] } }); const { fields: services } = useFieldArray({ control, name: "services", keyName: "id" }); - const { getTemplateById } = useTemplates(); - const remoteDeployTemplate = getTemplateById(CI_CD_TEMPLATE_ID); const envVarUpdater = useMemo(() => new EnvVarUpdater(services), [services]); useEffect(() => { @@ -51,10 +49,7 @@ const RemoteDeployUpdate = ({ sdlString, onManifestChange }: { sdlString: string const createAndValidateSdl = (yamlStr: string) => { try { - if (!yamlStr) return []; - const services = importSimpleSdl(yamlStr); - - return services; + return yamlStr ? importSimpleSdl(yamlStr) : []; } catch (err) { if (err.name === "YAMLException" || err.name === "CustomValidationError") { enqueueSnackbar(, { variant: "error" }); @@ -65,7 +60,7 @@ const RemoteDeployUpdate = ({ sdlString, onManifestChange }: { sdlString: string } } }; - return remoteDeployTemplate?.deploy?.includes(services?.[0]?.image) && services?.[0]?.env && services?.[0]?.env?.length > 0 ? ( + return services?.[0]?.image.startsWith(browserEnvConfig.NEXT_PUBLIC_CI_CD_IMAGE_NAME) && services?.[0]?.env && services?.[0]?.env?.length > 0 ? (
diff --git a/apps/deploy-web/src/config/browser-env.config.ts b/apps/deploy-web/src/config/browser-env.config.ts index 27fa036af..5981e7dfd 100644 --- a/apps/deploy-web/src/config/browser-env.config.ts +++ b/apps/deploy-web/src/config/browser-env.config.ts @@ -22,5 +22,6 @@ export const browserEnvConfig = validateStaticEnvVars({ NEXT_PUBLIC_BITBUCKET_CLIENT_ID: process.env.NEXT_PUBLIC_BITBUCKET_CLIENT_ID, NEXT_PUBLIC_GITLAB_CLIENT_ID: process.env.NEXT_PUBLIC_GITLAB_CLIENT_ID, NEXT_PUBLIC_GITHUB_CLIENT_ID: process.env.NEXT_PUBLIC_GITHUB_CLIENT_ID, - NEXT_PUBLIC_GA_MEASUREMENT_ID: process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID + NEXT_PUBLIC_GA_MEASUREMENT_ID: process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID, + NEXT_PUBLIC_CI_CD_IMAGE_NAME: process.env.NEXT_PUBLIC_CI_CD_IMAGE_NAME }); diff --git a/apps/deploy-web/src/config/env-config.schema.ts b/apps/deploy-web/src/config/env-config.schema.ts index 2d3682f5b..6000539e2 100644 --- a/apps/deploy-web/src/config/env-config.schema.ts +++ b/apps/deploy-web/src/config/env-config.schema.ts @@ -25,7 +25,8 @@ export const browserEnvSchema = z.object({ NEXT_PUBLIC_GITHUB_APP_INSTALLATION_URL: z.string().url(), NEXT_PUBLIC_BITBUCKET_CLIENT_ID: z.string().optional(), NEXT_PUBLIC_GITLAB_CLIENT_ID: z.string().optional(), - NEXT_PUBLIC_GITHUB_CLIENT_ID: z.string().optional() + NEXT_PUBLIC_GITHUB_CLIENT_ID: z.string().optional(), + NEXT_PUBLIC_CI_CD_IMAGE_NAME: z.string() }); export const serverEnvSchema = browserEnvSchema.extend({ @@ -42,7 +43,8 @@ export const serverEnvSchema = browserEnvSchema.extend({ BASE_API_SANDBOX_URL: z.string().url(), GITHUB_CLIENT_SECRET: z.string(), BITBUCKET_CLIENT_SECRET: z.string(), - GITLAB_CLIENT_SECRET: z.string() + GITLAB_CLIENT_SECRET: z.string(), + NEXT_PUBLIC_CI_CD_IMAGE_NAME: z.string() }); export type BrowserEnvConfig = z.infer; diff --git a/apps/deploy-web/src/context/SdlBuilderProvider/SdlBuilderProvider.tsx b/apps/deploy-web/src/context/SdlBuilderProvider/SdlBuilderProvider.tsx index 3f168b53a..cd02100a4 100644 --- a/apps/deploy-web/src/context/SdlBuilderProvider/SdlBuilderProvider.tsx +++ b/apps/deploy-web/src/context/SdlBuilderProvider/SdlBuilderProvider.tsx @@ -68,7 +68,7 @@ export const useSdlBuilder = () => { }; export const withSdlBuilder = (options: SdlBuilderProviderProps = {}) => - function wrapWithSdlBuilder

(Component: React.ComponentType

): FC

| React.ComponentType

{ + function wrapWithSdlBuilder

>(Component: React.ComponentType

): FC

| React.ComponentType

{ return function WrappedComponent(props: P) { return ( diff --git a/apps/deploy-web/src/lib/nextjs/getValidatedServerSIdeProps.ts b/apps/deploy-web/src/lib/nextjs/getValidatedServerSIdeProps.ts index 537c74227..37204a3a7 100644 --- a/apps/deploy-web/src/lib/nextjs/getValidatedServerSIdeProps.ts +++ b/apps/deploy-web/src/lib/nextjs/getValidatedServerSIdeProps.ts @@ -1,20 +1,18 @@ -import { GetServerSidePropsContext, GetServerSidePropsResult, PreviewData } from "next/types"; +import { GetServerSidePropsContext, GetServerSidePropsResult } from "next/types"; import type { ParsedUrlQuery } from "querystring"; import { z } from "zod"; -export const getValidatedServerSideProps = < - Props extends { [key: string]: any } = { [key: string]: any }, - Params extends ParsedUrlQuery = ParsedUrlQuery, - Preview extends PreviewData = PreviewData, - Schema extends z.ZodObject = z.ZodObject<{ params: z.ZodObject }, any, any> ->( +type ContextParamsSchema = z.ZodObject | z.ZodOptional>>; + +type ContextSchema = z.ZodObject<{ params?: ContextParamsSchema; query?: ContextParamsSchema }>; + +export const getValidatedServerSideProps = ( schema: Schema, - handler: ( - context: Omit, "params"> & { params: z.infer["params"] } - ) => Promise> -): ((context: GetServerSidePropsContext) => Promise>) => { + handler: (context: Omit & z.infer) => Promise> +): ((context: GetServerSidePropsContext) => Promise>) => { return context => { - const { params } = schema.parse(context); - return handler({ ...context, params }); + const validated = schema.parse(context); + + return handler({ ...context, ...validated }); }; }; diff --git a/apps/deploy-web/src/pages/deploy-linux/index.tsx b/apps/deploy-web/src/pages/deploy-linux/index.tsx index f45a806ad..6e997c446 100644 --- a/apps/deploy-web/src/pages/deploy-linux/index.tsx +++ b/apps/deploy-web/src/pages/deploy-linux/index.tsx @@ -1,7 +1,10 @@ import { NewDeploymentContainer } from "@src/components/new-deployment/NewDeploymentContainer"; import { withSdlBuilder } from "@src/context/SdlBuilderProvider/SdlBuilderProvider"; +import { getServerSideProps } from "../new-deployment"; export default withSdlBuilder({ componentsSet: "ssh", imageSource: "ssh-vms" })(NewDeploymentContainer); + +export { getServerSideProps }; diff --git a/apps/deploy-web/src/pages/deployments/[dseq]/index.tsx b/apps/deploy-web/src/pages/deployments/[dseq]/index.tsx index f80655361..357cc27b3 100644 --- a/apps/deploy-web/src/pages/deployments/[dseq]/index.tsx +++ b/apps/deploy-web/src/pages/deployments/[dseq]/index.tsx @@ -1,9 +1,7 @@ import { z } from "zod"; import { DeploymentDetail } from "@src/components/deployments/DeploymentDetail"; -import { CI_CD_TEMPLATE_ID } from "@src/config/remote-deploy.config"; import { getValidatedServerSideProps } from "@src/lib/nextjs/getValidatedServerSIdeProps"; -import { services } from "@src/services/http/http-server.service"; export default DeploymentDetail; @@ -14,11 +12,8 @@ const contextSchema = z.object({ }); export const getServerSideProps = getValidatedServerSideProps(contextSchema, async ({ params }) => { - const remoteDeployTemplate = await services.template.findById(CI_CD_TEMPLATE_ID); - return { props: { - remoteDeployTemplate, dseq: params.dseq } }; diff --git a/apps/deploy-web/src/pages/new-deployment/index.tsx b/apps/deploy-web/src/pages/new-deployment/index.tsx index 9f9b50e8b..0feaddf2c 100644 --- a/apps/deploy-web/src/pages/new-deployment/index.tsx +++ b/apps/deploy-web/src/pages/new-deployment/index.tsx @@ -1,4 +1,28 @@ -import { NewDeploymentContainer } from "@src/components/new-deployment/NewDeploymentContainer"; +import { z } from "zod"; + +import { NewDeploymentContainer, NewDeploymentContainerProps } from "@src/components/new-deployment/NewDeploymentContainer"; import { withSdlBuilder } from "@src/context/SdlBuilderProvider/SdlBuilderProvider"; +import { getValidatedServerSideProps } from "@src/lib/nextjs/getValidatedServerSIdeProps"; +import { services } from "@src/services/http/http-server.service"; export default withSdlBuilder()(NewDeploymentContainer); + +const contextSchema = z.object({ + query: z.object({ + templateId: z.string().optional() + }) +}); + +export const getServerSideProps = getValidatedServerSideProps(contextSchema, async ({ query }) => { + if (!query.templateId) { + return { props: {} }; + } + + const template = await services.template.findById(query.templateId); + + if (template && query.templateId) { + return { props: { template, templateId: query.templateId } }; + } + + return { props: {} }; +}); diff --git a/apps/deploy-web/src/queries/queryKeys.ts b/apps/deploy-web/src/queries/queryKeys.ts index efc9b8a51..b45347522 100644 --- a/apps/deploy-web/src/queries/queryKeys.ts +++ b/apps/deploy-web/src/queries/queryKeys.ts @@ -42,6 +42,7 @@ export class QueryKeys { static getBlockKey = (id: string) => ["BLOCK", id]; static getBalancesKey = (address?: string) => (address ? ["BALANCES", address] : []); static getTemplatesKey = () => ["TEMPLATES"]; + static getTemplateKey = (id: string) => ["TEMPLATES", id]; static getProviderAttributesSchema = () => ["PROVIDER_ATTRIBUTES_SCHEMA"]; static getDepositParamsKey = () => ["DEPOSIT_PARAMS"]; static getGpuModelsKey = () => ["GPU_MODELS"]; diff --git a/apps/deploy-web/src/queries/useTemplateQuery.tsx b/apps/deploy-web/src/queries/useTemplateQuery.tsx index e8a24cd68..e4d493810 100644 --- a/apps/deploy-web/src/queries/useTemplateQuery.tsx +++ b/apps/deploy-web/src/queries/useTemplateQuery.tsx @@ -1,10 +1,13 @@ import { QueryKey, useMutation, useQuery, useQueryClient, UseQueryOptions } from "react-query"; +import { UseQueryResult } from "react-query/types/react/types"; +import { TemplateOutput } from "@akashnetwork/http-sdk/src/template/template-http.service"; import { Snackbar } from "@akashnetwork/ui/components"; import axios from "axios"; import { useRouter } from "next/navigation"; import { useSnackbar } from "notistack"; import { useCustomUser } from "@src/hooks/useCustomUser"; +import { services } from "@src/services/http/http-browser.service"; import { ITemplate } from "@src/types"; import { ApiUrlService } from "@src/utils/apiUtils"; import { UrlService } from "@src/utils/urlUtils"; @@ -130,3 +133,7 @@ export function useTemplates(options = {}) { refetchOnReconnect: false }); } + +export function useTemplateById(id: string, options: UseQueryOptions = {}): UseQueryResult { + return useQuery(QueryKeys.getTemplateKey(id), () => services.template.findById(id), options); +} diff --git a/apps/deploy-web/src/services/remote-deploy/remote-deployment-controller.service.ts b/apps/deploy-web/src/services/remote-deploy/remote-deployment-controller.service.ts index 2d341594a..064ddaa2b 100644 --- a/apps/deploy-web/src/services/remote-deploy/remote-deployment-controller.service.ts +++ b/apps/deploy-web/src/services/remote-deploy/remote-deployment-controller.service.ts @@ -1,5 +1,6 @@ import { nanoid } from "nanoid"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { SdlBuilderFormValuesType, ServiceType } from "@src/types"; export class EnvVarUpdater { @@ -35,8 +36,8 @@ export function formatUrlWithoutInitialPath(url?: string): string | undefined { return url?.split("/").slice(-2).join("/"); } -export function isImageInYaml(yml: string, cicdYml?: string): boolean | undefined { - return cicdYml?.includes(yml?.split("service-1:")?.[1]?.split("expose:")?.[0]?.split("image: ")?.[1]); +export function isCiCdImageInYaml(yml: string): boolean | undefined { + return yml.includes(browserEnvConfig.NEXT_PUBLIC_CI_CD_IMAGE_NAME); } export function extractRepositoryUrl(yml?: string | null): string | null { diff --git a/package-lock.json b/package-lock.json index 889cdbcc6..edec3f149 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,7 @@ }, "apps/api": { "name": "@akashnetwork/console-api", - "version": "2.35.2-beta.0", + "version": "2.35.2", "license": "Apache-2.0", "dependencies": { "@akashnetwork/akash-api": "^1.3.0", From 80fdf363e2d0bd79626d26a9753e7466311166d6 Mon Sep 17 00:00:00 2001 From: Yaroslav Grishajev Date: Tue, 3 Dec 2024 09:30:11 +0100 Subject: [PATCH 4/5] fix: ensure proper schema type on server props getter --- apps/deploy-web/src/pages/templates/[templateId]/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/deploy-web/src/pages/templates/[templateId]/index.tsx b/apps/deploy-web/src/pages/templates/[templateId]/index.tsx index aef36c31b..ddf9be498 100644 --- a/apps/deploy-web/src/pages/templates/[templateId]/index.tsx +++ b/apps/deploy-web/src/pages/templates/[templateId]/index.tsx @@ -12,7 +12,7 @@ const contextSchema = z.object({ }) }); -export const getServerSideProps = getValidatedServerSideProps(contextSchema, async ({ params }) => { +export const getServerSideProps = getValidatedServerSideProps(contextSchema, async ({ params }) => { const template = await services.template.findById(params.templateId); if (!template) { From f7fbb550b964460c41b205bd5a67183bf6c778de Mon Sep 17 00:00:00 2001 From: Yaroslav Grishajev Date: Tue, 3 Dec 2024 09:42:50 +0100 Subject: [PATCH 5/5] refactor(template): remove unused hook --- apps/deploy-web/src/queries/queryKeys.ts | 1 - apps/deploy-web/src/queries/useTemplateQuery.tsx | 4 ---- 2 files changed, 5 deletions(-) diff --git a/apps/deploy-web/src/queries/queryKeys.ts b/apps/deploy-web/src/queries/queryKeys.ts index b45347522..efc9b8a51 100644 --- a/apps/deploy-web/src/queries/queryKeys.ts +++ b/apps/deploy-web/src/queries/queryKeys.ts @@ -42,7 +42,6 @@ export class QueryKeys { static getBlockKey = (id: string) => ["BLOCK", id]; static getBalancesKey = (address?: string) => (address ? ["BALANCES", address] : []); static getTemplatesKey = () => ["TEMPLATES"]; - static getTemplateKey = (id: string) => ["TEMPLATES", id]; static getProviderAttributesSchema = () => ["PROVIDER_ATTRIBUTES_SCHEMA"]; static getDepositParamsKey = () => ["DEPOSIT_PARAMS"]; static getGpuModelsKey = () => ["GPU_MODELS"]; diff --git a/apps/deploy-web/src/queries/useTemplateQuery.tsx b/apps/deploy-web/src/queries/useTemplateQuery.tsx index e4d493810..4214ccaaa 100644 --- a/apps/deploy-web/src/queries/useTemplateQuery.tsx +++ b/apps/deploy-web/src/queries/useTemplateQuery.tsx @@ -133,7 +133,3 @@ export function useTemplates(options = {}) { refetchOnReconnect: false }); } - -export function useTemplateById(id: string, options: UseQueryOptions = {}): UseQueryResult { - return useQuery(QueryKeys.getTemplateKey(id), () => services.template.findById(id), options); -}