From ff79e33f199fe97ead5c01c9feb2db8a69d1d749 Mon Sep 17 00:00:00 2001 From: bkellam Date: Fri, 24 Jan 2025 14:11:46 -0800 Subject: [PATCH] fix --- packages/web/src/app/api/(client)/client.ts | 15 +++++++++++++-- .../web/src/app/api/(server)/version/route.ts | 15 +++++++++++++++ .../web/src/app/components/upgradeToast.tsx | 17 ++++++++++++++--- packages/web/src/lib/environment.ts | 1 + packages/web/src/lib/schemas.ts | 4 ++++ packages/web/src/lib/types.ts | 4 +++- 6 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 packages/web/src/app/api/(server)/version/route.ts diff --git a/packages/web/src/app/api/(client)/client.ts b/packages/web/src/app/api/(client)/client.ts index 889ecd42..a2a68583 100644 --- a/packages/web/src/app/api/(client)/client.ts +++ b/packages/web/src/app/api/(client)/client.ts @@ -1,8 +1,8 @@ 'use client'; import { NEXT_PUBLIC_DOMAIN_SUB_PATH } from "@/lib/environment.client"; -import { fileSourceResponseSchema, listRepositoriesResponseSchema, searchResponseSchema } from "@/lib/schemas"; -import { FileSourceRequest, FileSourceResponse, ListRepositoriesResponse, SearchRequest, SearchResponse } from "@/lib/types"; +import { fileSourceResponseSchema, getVersionResponseSchema, listRepositoriesResponseSchema, searchResponseSchema } from "@/lib/schemas"; +import { FileSourceRequest, FileSourceResponse, GetVersionResponse, ListRepositoriesResponse, SearchRequest, SearchResponse } from "@/lib/types"; import assert from "assert"; export const search = async (body: SearchRequest): Promise => { @@ -43,6 +43,17 @@ export const getRepos = async (): Promise => { return listRepositoriesResponseSchema.parse(result); } +export const getVersion = async (): Promise => { + const path = resolveServerPath("/api/version"); + const result = await fetch(path, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }).then(response => response.json()); + return getVersionResponseSchema.parse(result); +} + /** * Given a subpath to a api route on the server (e.g., /api/search), * returns the full path to that route on the server, taking into account diff --git a/packages/web/src/app/api/(server)/version/route.ts b/packages/web/src/app/api/(server)/version/route.ts new file mode 100644 index 00000000..309ffa19 --- /dev/null +++ b/packages/web/src/app/api/(server)/version/route.ts @@ -0,0 +1,15 @@ +import { SOURCEBOT_VERSION } from "@/lib/environment"; +import { GetVersionResponse } from "@/lib/types"; + +// Note: In Next.JS 14, GET methods with no params are cached by default at build time. +// This creates issues since environment variables (like SOURCEBOT_VERSION) are +// not available until runtime. To work around this, we fore the route to be +// dynamic and evaluate on each request. +// @see: https://nextjs.org/docs/14/app/building-your-application/routing/route-handlers#caching +export const dynamic = "force-dynamic"; + +export const GET = async () => { + return Response.json({ + version: SOURCEBOT_VERSION, + } satisfies GetVersionResponse); +} \ No newline at end of file diff --git a/packages/web/src/app/components/upgradeToast.tsx b/packages/web/src/app/components/upgradeToast.tsx index 73342266..d5b2da60 100644 --- a/packages/web/src/app/components/upgradeToast.tsx +++ b/packages/web/src/app/components/upgradeToast.tsx @@ -2,9 +2,10 @@ import { useToast } from "@/components/hooks/use-toast"; import { ToastAction } from "@/components/ui/toast"; -import { NEXT_PUBLIC_SOURCEBOT_VERSION } from "@/lib/environment.client"; import { useEffect } from "react"; import { useLocalStorage } from "usehooks-ts"; +import { getVersion } from "../api/(client)/client"; +import { useQuery } from "@tanstack/react-query"; const GITHUB_TAGS_URL = "https://api.github.com/repos/sourcebot-dev/sourcebot/tags"; const SEMVER_REGEX = /^v(\d+)\.(\d+)\.(\d+)$/; @@ -23,8 +24,18 @@ export const UpgradeToast = () => { new Date(0).toUTCString() ); + const { data: versionString } = useQuery({ + queryKey: ["version"], + queryFn: () => getVersion(), + select: (data) => data.version, + }) + useEffect(() => { - const currentVersion = getVersionFromString(NEXT_PUBLIC_SOURCEBOT_VERSION); + if (!versionString) { + return; + } + + const currentVersion = getVersionFromString(versionString); if (!currentVersion) { return; } @@ -71,7 +82,7 @@ export const UpgradeToast = () => { setUpgradeToastLastShownDate(new Date().toUTCString()); }); - }, [setUpgradeToastLastShownDate, toast, upgradeToastLastShownDate]); + }, [setUpgradeToastLastShownDate, toast, upgradeToastLastShownDate, versionString]); return null; } diff --git a/packages/web/src/lib/environment.ts b/packages/web/src/lib/environment.ts index 0102da6d..7f23b0a5 100644 --- a/packages/web/src/lib/environment.ts +++ b/packages/web/src/lib/environment.ts @@ -5,4 +5,5 @@ import { getEnv, getEnvNumber } from "./utils"; export const ZOEKT_WEBSERVER_URL = getEnv(process.env.ZOEKT_WEBSERVER_URL, "http://localhost:6070")!; export const SHARD_MAX_MATCH_COUNT = getEnvNumber(process.env.SHARD_MAX_MATCH_COUNT, 10000); export const TOTAL_MAX_MATCH_COUNT = getEnvNumber(process.env.TOTAL_MAX_MATCH_COUNT, 100000); +export const SOURCEBOT_VERSION = getEnv(process.env.SOURCEBOT_VERSION, 'unknown')!; export const NODE_ENV = process.env.NODE_ENV; diff --git a/packages/web/src/lib/schemas.ts b/packages/web/src/lib/schemas.ts index 25526f6b..4bf82ad2 100644 --- a/packages/web/src/lib/schemas.ts +++ b/packages/web/src/lib/schemas.ts @@ -153,3 +153,7 @@ export const listRepositoriesResponseSchema = z.object({ Stats: repoStatsSchema, }) }); + +export const getVersionResponseSchema = z.object({ + version: z.string(), +}); diff --git a/packages/web/src/lib/types.ts b/packages/web/src/lib/types.ts index c1d8bccd..bc79426d 100644 --- a/packages/web/src/lib/types.ts +++ b/packages/web/src/lib/types.ts @@ -1,5 +1,5 @@ import { z } from "zod"; -import { fileSourceRequestSchema, fileSourceResponseSchema, listRepositoriesResponseSchema, locationSchema, rangeSchema, repositorySchema, searchRequestSchema, searchResponseSchema, symbolSchema } from "./schemas"; +import { fileSourceRequestSchema, fileSourceResponseSchema, getVersionResponseSchema, listRepositoriesResponseSchema, locationSchema, rangeSchema, repositorySchema, searchRequestSchema, searchResponseSchema, symbolSchema } from "./schemas"; export type KeymapType = "default" | "vim"; @@ -20,6 +20,8 @@ export type Repository = z.infer; export type Symbol = z.infer; +export type GetVersionResponse = z.infer; + export enum SearchQueryParams { query = "query", maxMatchDisplayCount = "maxMatchDisplayCount",