mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-12 04:15:30 +00:00
Add PostHog telemetry support
This commit is contained in:
parent
9a8d17b4c0
commit
3ef9be2b6b
18 changed files with 317 additions and 43 deletions
|
|
@ -8,3 +8,4 @@ README.md
|
||||||
!.next/standalone
|
!.next/standalone
|
||||||
.git
|
.git
|
||||||
.sourcebot
|
.sourcebot
|
||||||
|
.env.local
|
||||||
4
.env
Normal file
4
.env
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
NEXT_PUBLIC_POSTHOG_KEY=phc_VFn4CkEGHRdlVyOOw8mfkoj1DKVoG6y1007EClvzAnS
|
||||||
|
NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
|
||||||
|
NEXT_PUBLIC_POSTHOG_ASSET_HOST=https://us-assets.i.posthog.com
|
||||||
|
NEXT_PUBLIC_POSTHOG_UI_HOST=https://us.posthog.com
|
||||||
|
|
@ -22,6 +22,8 @@ RUN yarn config set network-timeout 1200000
|
||||||
RUN yarn --frozen-lockfile
|
RUN yarn --frozen-lockfile
|
||||||
COPY . .
|
COPY . .
|
||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
# @see: https://phase.dev/blog/nextjs-public-runtime-variables/
|
||||||
|
ARG NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED=BAKED_NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED
|
||||||
RUN yarn run build
|
RUN yarn run build
|
||||||
|
|
||||||
# ------ Runner ------
|
# ------ Runner ------
|
||||||
|
|
@ -33,6 +35,9 @@ ENV DATA_DIR=/data
|
||||||
ENV CONFIG_PATH=$DATA_DIR/config.json
|
ENV CONFIG_PATH=$DATA_DIR/config.json
|
||||||
ENV DATA_CACHE_DIR=$DATA_DIR/.sourcebot
|
ENV DATA_CACHE_DIR=$DATA_DIR/.sourcebot
|
||||||
|
|
||||||
|
# Sourcebot collects anonymous usage data using [PostHog](https://posthog.com/). Uncomment this line to disable.
|
||||||
|
# ENV SOURCEBOT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
# Configure dependencies
|
# Configure dependencies
|
||||||
RUN apk add --no-cache git ca-certificates bind-tools tini jansson wget supervisor
|
RUN apk add --no-cache git ca-certificates bind-tools tini jansson wget supervisor
|
||||||
|
|
||||||
|
|
|
||||||
16
README.md
16
README.md
|
|
@ -65,20 +65,26 @@ zoekt will now index your repositories (at `HEAD`). By default, it will re-index
|
||||||
|
|
||||||
4. Go to `http://localhost:3000` - once a index has been created, you should get results.
|
4. Go to `http://localhost:3000` - once a index has been created, you should get results.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Building Sourcebot
|
## Building Sourcebot
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
|
||||||
## GitLab
|
## Disabling Telemetry
|
||||||
|
|
||||||
|
By default, Sourcebot collects anonymous usage data using [PostHog](https://posthog.com/). You can disable this by setting the environment variable `SOURCEBOT_TELEMETRY_DISABLED` to `1` in the docker run command. Example:
|
||||||
|
```sh
|
||||||
|
docker run -e SOURCEBOT_TELEMETRY_DISABLED=1 ...stuff... ghcr.io/taqlaai/sourcebot:main
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
# GitLab
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
|
||||||
## BitBucket
|
# BitBucket
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
|
||||||
### Todos
|
# Todos
|
||||||
- Add instructions on using GitLab and BitBucket
|
- Add instructions on using GitLab and BitBucket
|
||||||
- Add instructions on building Sourcebot locally
|
- Add instructions on building Sourcebot locally
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
|
||||||
# Check if CONFIG_PATH is set
|
# Check if CONFIG_PATH is set
|
||||||
if [ -z "$CONFIG_PATH" ]; then
|
if [ -z "$CONFIG_PATH" ]; then
|
||||||
echo "\e[33mWarning: CONFIG_PATH environment variable is not set.\e[0m"
|
echo "\e[33mWarning: CONFIG_PATH environment variable is not set.\e[0m"
|
||||||
|
|
@ -35,4 +34,17 @@ else
|
||||||
echo -e "\e[33mWarning: GitLab repositories will not be indexed since GITLAB_TOKEN was not set. If you are not using GitLab, disregard.\e[0m"
|
echo -e "\e[33mWarning: GitLab repositories will not be indexed since GITLAB_TOKEN was not set. If you are not using GitLab, disregard.\e[0m"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Update nextjs public env variables w/o requiring a rebuild.
|
||||||
|
# @see: https://phase.dev/blog/nextjs-public-runtime-variables/
|
||||||
|
|
||||||
|
# Infer NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED if it is not set
|
||||||
|
if [ -z "$NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED" ] && [ ! -z "$SOURCEBOT_TELEMETRY_DISABLED" ]; then
|
||||||
|
export NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED="$SOURCEBOT_TELEMETRY_DISABLED"
|
||||||
|
fi
|
||||||
|
|
||||||
|
find /app/public /app/.next -type f -name "*.js" |
|
||||||
|
while read file; do
|
||||||
|
sed -i "s|BAKED_NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED|${NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED}|g" "$file"
|
||||||
|
done
|
||||||
|
|
||||||
exec supervisord -c /etc/supervisor/conf.d/supervisord.conf
|
exec supervisord -c /etc/supervisor/conf.d/supervisord.conf
|
||||||
|
|
@ -1,6 +1,26 @@
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
output: "standalone"
|
output: "standalone",
|
||||||
|
|
||||||
|
// @see : https://posthog.com/docs/advanced/proxy/nextjs
|
||||||
|
async rewrites() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
source: "/ingest/static/:path*",
|
||||||
|
destination: `${process.env.NEXT_PUBLIC_POSTHOG_ASSET_HOST}/static/:path*`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: "/ingest/:path*",
|
||||||
|
destination: `${process.env.NEXT_PUBLIC_POSTHOG_HOST}/:path*`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: "/ingest/decide",
|
||||||
|
destination: `${process.env.NEXT_PUBLIC_POSTHOG_HOST}/decide`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
// This is required to support PostHog trailing slash API requests
|
||||||
|
skipTrailingSlashRedirect: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|
|
||||||
|
|
@ -27,17 +27,20 @@
|
||||||
"@tanstack/react-table": "^8.20.5",
|
"@tanstack/react-table": "^8.20.5",
|
||||||
"@uiw/react-codemirror": "^4.23.0",
|
"@uiw/react-codemirror": "^4.23.0",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
|
"client-only": "^0.0.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"escape-string-regexp": "^5.0.0",
|
"escape-string-regexp": "^5.0.0",
|
||||||
"http-status-codes": "^2.3.0",
|
"http-status-codes": "^2.3.0",
|
||||||
"lucide-react": "^0.435.0",
|
"lucide-react": "^0.435.0",
|
||||||
"next": "14.2.6",
|
"next": "14.2.6",
|
||||||
"next-themes": "^0.3.0",
|
"next-themes": "^0.3.0",
|
||||||
|
"posthog-js": "^1.161.5",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
"react-hook-form": "^7.53.0",
|
"react-hook-form": "^7.53.0",
|
||||||
"react-hotkeys-hook": "^4.5.1",
|
"react-hotkeys-hook": "^4.5.1",
|
||||||
"react-resizable-panels": "^2.1.1",
|
"react-resizable-panels": "^2.1.1",
|
||||||
|
"server-only": "^0.0.1",
|
||||||
"sharp": "^0.33.5",
|
"sharp": "^0.33.5",
|
||||||
"tailwind-merge": "^2.5.2",
|
"tailwind-merge": "^2.5.2",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,15 @@ import "./globals.css";
|
||||||
import { ThemeProvider } from "next-themes";
|
import { ThemeProvider } from "next-themes";
|
||||||
import { Suspense } from "react";
|
import { Suspense } from "react";
|
||||||
import { QueryClientProvider } from "./queryClientProvider";
|
import { QueryClientProvider } from "./queryClientProvider";
|
||||||
|
import { PHProvider } from "./posthogProvider";
|
||||||
|
import dynamic from "next/dynamic";
|
||||||
|
|
||||||
const inter = Inter({ subsets: ["latin"] });
|
const inter = Inter({ subsets: ["latin"] });
|
||||||
|
|
||||||
|
const PostHogPageView = dynamic(() => import('./posthogPageView'), {
|
||||||
|
ssr: false,
|
||||||
|
})
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Sourcebot",
|
title: "Sourcebot",
|
||||||
description: "Sourcebot",
|
description: "Sourcebot",
|
||||||
|
|
@ -24,6 +30,8 @@ export default function RootLayout({
|
||||||
suppressHydrationWarning
|
suppressHydrationWarning
|
||||||
>
|
>
|
||||||
<body className={inter.className}>
|
<body className={inter.className}>
|
||||||
|
<PHProvider>
|
||||||
|
<PostHogPageView />
|
||||||
<ThemeProvider
|
<ThemeProvider
|
||||||
attribute="class"
|
attribute="class"
|
||||||
defaultTheme="system"
|
defaultTheme="system"
|
||||||
|
|
@ -40,6 +48,7 @@ export default function RootLayout({
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
</PHProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
28
src/app/posthogPageView.tsx
Normal file
28
src/app/posthogPageView.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import { usePathname, useSearchParams } from "next/navigation";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import { usePostHog } from 'posthog-js/react';
|
||||||
|
|
||||||
|
export default function PostHogPageView(): null {
|
||||||
|
const pathname = usePathname();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const posthog = usePostHog();
|
||||||
|
useEffect(() => {
|
||||||
|
// Track pageviews
|
||||||
|
if (pathname && posthog) {
|
||||||
|
let url = window.origin + pathname
|
||||||
|
if (searchParams.toString()) {
|
||||||
|
url = url + `?${searchParams.toString()}`
|
||||||
|
}
|
||||||
|
posthog.capture(
|
||||||
|
'$pageview',
|
||||||
|
{
|
||||||
|
'$current_url': url,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}, [pathname, searchParams, posthog])
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
25
src/app/posthogProvider.tsx
Normal file
25
src/app/posthogProvider.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
'use client'
|
||||||
|
import { NEXT_PUBLIC_POSTHOG_KEY, NEXT_PUBLIC_POSTHOG_UI_HOST, NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED } from '@/lib/environment.client'
|
||||||
|
import posthog from 'posthog-js'
|
||||||
|
import { PostHogProvider } from 'posthog-js/react'
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
if (!NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED) {
|
||||||
|
posthog.init(NEXT_PUBLIC_POSTHOG_KEY!, {
|
||||||
|
api_host: "/ingest",
|
||||||
|
ui_host: NEXT_PUBLIC_POSTHOG_UI_HOST,
|
||||||
|
person_profiles: 'identified_only',
|
||||||
|
capture_pageview: false, // Disable automatic pageview capture, as we capture manually
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log("PostHog telemetry disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PHProvider({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode
|
||||||
|
}) {
|
||||||
|
return <PostHogProvider client={posthog}>{children}</PostHogProvider>
|
||||||
|
}
|
||||||
|
|
@ -13,7 +13,7 @@ import { SymbolIcon } from "@radix-ui/react-icons";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import logoDark from "../../../public/sb_logo_dark.png";
|
import logoDark from "../../../public/sb_logo_dark.png";
|
||||||
import logoLight from "../../../public/sb_logo_light.png";
|
import logoLight from "../../../public/sb_logo_light.png";
|
||||||
import { fetchFileSource, search } from "../api/(client)/client";
|
import { fetchFileSource, search } from "../api/(client)/client";
|
||||||
|
|
@ -21,6 +21,7 @@ import { SearchBar } from "../searchBar";
|
||||||
import { SettingsDropdown } from "../settingsDropdown";
|
import { SettingsDropdown } from "../settingsDropdown";
|
||||||
import { CodePreviewFile, CodePreviewPanel } from "./codePreviewPanel";
|
import { CodePreviewFile, CodePreviewPanel } from "./codePreviewPanel";
|
||||||
import { SearchResultsPanel } from "./searchResultsPanel";
|
import { SearchResultsPanel } from "./searchResultsPanel";
|
||||||
|
import useCaptureEvent from "@/hooks/useCaptureEvent";
|
||||||
|
|
||||||
const DEFAULT_NUM_RESULTS = 100;
|
const DEFAULT_NUM_RESULTS = 100;
|
||||||
|
|
||||||
|
|
@ -33,6 +34,8 @@ export default function SearchPage() {
|
||||||
const [selectedMatchIndex, setSelectedMatchIndex] = useState(0);
|
const [selectedMatchIndex, setSelectedMatchIndex] = useState(0);
|
||||||
const [selectedFile, setSelectedFile] = useState<SearchResultFile | undefined>(undefined);
|
const [selectedFile, setSelectedFile] = useState<SearchResultFile | undefined>(undefined);
|
||||||
|
|
||||||
|
const captureEvent = useCaptureEvent();
|
||||||
|
|
||||||
const { data: searchResponse, isLoading } = useQuery({
|
const { data: searchResponse, isLoading } = useQuery({
|
||||||
queryKey: ["search", searchQuery, numResults],
|
queryKey: ["search", searchQuery, numResults],
|
||||||
queryFn: () => search({
|
queryFn: () => search({
|
||||||
|
|
@ -40,8 +43,41 @@ export default function SearchPage() {
|
||||||
numResults,
|
numResults,
|
||||||
}),
|
}),
|
||||||
enabled: searchQuery.length > 0,
|
enabled: searchQuery.length > 0,
|
||||||
|
refetchOnWindowFocus: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!searchResponse) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileLanguages = searchResponse.Result.Files?.map(file => file.Language) || [];
|
||||||
|
|
||||||
|
captureEvent("search_finished", {
|
||||||
|
contentBytesLoaded: searchResponse.Result.ContentBytesLoaded,
|
||||||
|
indexBytesLoaded: searchResponse.Result.IndexBytesLoaded,
|
||||||
|
crashes: searchResponse.Result.Crashes,
|
||||||
|
durationMs: searchResponse.Result.Duration / 1000000,
|
||||||
|
fileCount: searchResponse.Result.FileCount,
|
||||||
|
shardFilesConsidered: searchResponse.Result.ShardFilesConsidered,
|
||||||
|
filesConsidered: searchResponse.Result.FilesConsidered,
|
||||||
|
filesLoaded: searchResponse.Result.FilesLoaded,
|
||||||
|
filesSkipped: searchResponse.Result.FilesSkipped,
|
||||||
|
shardsScanned: searchResponse.Result.ShardsScanned,
|
||||||
|
shardsSkipped: searchResponse.Result.ShardsSkipped,
|
||||||
|
shardsSkippedFilter: searchResponse.Result.ShardsSkippedFilter,
|
||||||
|
matchCount: searchResponse.Result.MatchCount,
|
||||||
|
ngramMatches: searchResponse.Result.NgramMatches,
|
||||||
|
ngramLookups: searchResponse.Result.NgramLookups,
|
||||||
|
wait: searchResponse.Result.Wait,
|
||||||
|
matchTreeConstruction: searchResponse.Result.MatchTreeConstruction,
|
||||||
|
matchTreeSearch: searchResponse.Result.MatchTreeSearch,
|
||||||
|
regexpsConsidered: searchResponse.Result.RegexpsConsidered,
|
||||||
|
flushReason: searchResponse.Result.FlushReason,
|
||||||
|
fileLanguages,
|
||||||
|
});
|
||||||
|
}, [captureEvent, searchResponse]);
|
||||||
|
|
||||||
const { fileMatches, searchDurationMs } = useMemo((): { fileMatches: SearchResultFile[], searchDurationMs: number } => {
|
const { fileMatches, searchDurationMs } = useMemo((): { fileMatches: SearchResultFile[], searchDurationMs: number } => {
|
||||||
if (!searchResponse) {
|
if (!searchResponse) {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
26
src/hooks/useCaptureEvent.ts
Normal file
26
src/hooks/useCaptureEvent.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { CaptureOptions } from "posthog-js";
|
||||||
|
import posthog from "posthog-js";
|
||||||
|
import { PosthogEvent, PosthogEventMap } from "../lib/posthogEvents";
|
||||||
|
|
||||||
|
export function captureEvent<E extends PosthogEvent>(event: E, properties: PosthogEventMap[E], options?: CaptureOptions) {
|
||||||
|
if(!options) {
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
options.send_instantly = true;
|
||||||
|
posthog.capture(event, properties, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Captures a distinct action as a event and forwards it to the event service
|
||||||
|
* (i.e., PostHog).
|
||||||
|
*
|
||||||
|
* @returns A callback for capturing events.
|
||||||
|
* @see: https://posthog.com/docs/libraries/js#capturing-events
|
||||||
|
*/
|
||||||
|
const useCaptureEvent = () => {
|
||||||
|
return captureEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useCaptureEvent;
|
||||||
9
src/lib/environment.client.ts
Normal file
9
src/lib/environment.client.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import 'client-only';
|
||||||
|
|
||||||
|
import { getEnv, getEnvBoolean } from "./utils";
|
||||||
|
|
||||||
|
export const NEXT_PUBLIC_POSTHOG_KEY = getEnv(process.env.NEXT_PUBLIC_POSTHOG_KEY);
|
||||||
|
export const NEXT_PUBLIC_POSTHOG_HOST = getEnv(process.env.NEXT_PUBLIC_POSTHOG_HOST);
|
||||||
|
export const NEXT_PUBLIC_POSTHOG_UI_HOST = getEnv(process.env.NEXT_PUBLIC_POSTHOG_UI_HOST);
|
||||||
|
export const NEXT_PUBLIC_POSTHOG_ASSET_HOST = getEnv(process.env.NEXT_PUBLIC_POSTHOG_ASSET_HOST);
|
||||||
|
export const NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED = getEnvBoolean(process.env.NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED, false);
|
||||||
|
|
@ -1,14 +1,8 @@
|
||||||
|
import 'server-only';
|
||||||
|
|
||||||
const getEnv = (env: string | undefined, defaultValue = '') => {
|
import { getEnv, getEnvNumber } from "./utils";
|
||||||
return env ?? defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getEnvNumber = (env: string | undefined, defaultValue: number = 0) => {
|
|
||||||
return Number(env) ?? defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ZOEKT_WEBSERVER_URL = getEnv(process.env.ZOEKT_WEBSERVER_URL, "http://localhost:6070");
|
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 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 TOTAL_MAX_MATCH_COUNT = getEnvNumber(process.env.TOTAL_MAX_MATCH_COUNT, 100000);
|
||||||
|
|
||||||
export const NODE_ENV = process.env.NODE_ENV;
|
export const NODE_ENV = process.env.NODE_ENV;
|
||||||
|
|
|
||||||
29
src/lib/posthogEvents.ts
Normal file
29
src/lib/posthogEvents.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
||||||
|
|
||||||
|
export type PosthogEventMap = {
|
||||||
|
search_finished: {
|
||||||
|
contentBytesLoaded: number,
|
||||||
|
indexBytesLoaded: number,
|
||||||
|
crashes: number,
|
||||||
|
durationMs: number,
|
||||||
|
fileCount: number,
|
||||||
|
shardFilesConsidered: number,
|
||||||
|
filesConsidered: number,
|
||||||
|
filesLoaded: number,
|
||||||
|
filesSkipped: number,
|
||||||
|
shardsScanned: number,
|
||||||
|
shardsSkipped: number,
|
||||||
|
shardsSkippedFilter: number,
|
||||||
|
matchCount: number,
|
||||||
|
ngramMatches: number,
|
||||||
|
ngramLookups: number,
|
||||||
|
wait: number,
|
||||||
|
matchTreeConstruction: number,
|
||||||
|
matchTreeSearch: number,
|
||||||
|
regexpsConsidered: number,
|
||||||
|
flushReason: number,
|
||||||
|
fileLanguages: string[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PosthogEvent = keyof PosthogEventMap;
|
||||||
|
|
@ -30,11 +30,34 @@ const rangeSchema = z.object({
|
||||||
End: locationSchema,
|
End: locationSchema,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const searchResponseSchema = z.object({
|
// @see : https://github.com/TaqlaAI/zoekt/blob/3780e68cdb537d5a7ed2c84d9b3784f80c7c5d04/api.go#L350
|
||||||
Result: z.object({
|
export const searchResponseStats = {
|
||||||
|
ContentBytesLoaded: z.number(),
|
||||||
|
IndexBytesLoaded: z.number(),
|
||||||
|
Crashes: z.number(),
|
||||||
Duration: z.number(),
|
Duration: z.number(),
|
||||||
FileCount: z.number(),
|
FileCount: z.number(),
|
||||||
|
ShardFilesConsidered: z.number(),
|
||||||
|
FilesConsidered: z.number(),
|
||||||
|
FilesLoaded: z.number(),
|
||||||
|
FilesSkipped: z.number(),
|
||||||
|
ShardsScanned: z.number(),
|
||||||
|
ShardsSkipped: z.number(),
|
||||||
|
ShardsSkippedFilter: z.number(),
|
||||||
MatchCount: z.number(),
|
MatchCount: z.number(),
|
||||||
|
NgramMatches: z.number(),
|
||||||
|
NgramLookups: z.number(),
|
||||||
|
Wait: z.number(),
|
||||||
|
MatchTreeConstruction: z.number(),
|
||||||
|
MatchTreeSearch: z.number(),
|
||||||
|
RegexpsConsidered: z.number(),
|
||||||
|
FlushReason: z.number(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// @see : https://github.com/TaqlaAI/zoekt/blob/3780e68cdb537d5a7ed2c84d9b3784f80c7c5d04/api.go#L497
|
||||||
|
export const searchResponseSchema = z.object({
|
||||||
|
Result: z.object({
|
||||||
|
...searchResponseStats,
|
||||||
Files: z.array(z.object({
|
Files: z.array(z.object({
|
||||||
FileName: z.string(),
|
FileName: z.string(),
|
||||||
Repository: z.string(),
|
Repository: z.string(),
|
||||||
|
|
@ -72,7 +95,7 @@ export const fileSourceResponseSchema = z.object({
|
||||||
export type ListRepositoriesResponse = z.infer<typeof listRepositoriesResponseSchema>;
|
export type ListRepositoriesResponse = z.infer<typeof listRepositoriesResponseSchema>;
|
||||||
|
|
||||||
// @see : https://github.com/TaqlaAI/zoekt/blob/3780e68cdb537d5a7ed2c84d9b3784f80c7c5d04/api.go#L728
|
// @see : https://github.com/TaqlaAI/zoekt/blob/3780e68cdb537d5a7ed2c84d9b3784f80c7c5d04/api.go#L728
|
||||||
export const statsSchema = z.object({
|
const repoStatsSchema = z.object({
|
||||||
Repos: z.number(),
|
Repos: z.number(),
|
||||||
Shards: z.number(),
|
Shards: z.number(),
|
||||||
Documents: z.number(),
|
Documents: z.number(),
|
||||||
|
|
@ -84,7 +107,7 @@ export const statsSchema = z.object({
|
||||||
});
|
});
|
||||||
|
|
||||||
// @see : https://github.com/TaqlaAI/zoekt/blob/3780e68cdb537d5a7ed2c84d9b3784f80c7c5d04/api.go#L716
|
// @see : https://github.com/TaqlaAI/zoekt/blob/3780e68cdb537d5a7ed2c84d9b3784f80c7c5d04/api.go#L716
|
||||||
export const indexMetadataSchema = z.object({
|
const indexMetadataSchema = z.object({
|
||||||
IndexFormatVersion: z.number(),
|
IndexFormatVersion: z.number(),
|
||||||
IndexFeatureVersion: z.number(),
|
IndexFeatureVersion: z.number(),
|
||||||
IndexMinReaderVersion: z.number(),
|
IndexMinReaderVersion: z.number(),
|
||||||
|
|
@ -96,7 +119,7 @@ export const indexMetadataSchema = z.object({
|
||||||
});
|
});
|
||||||
|
|
||||||
// @see : https://github.com/TaqlaAI/zoekt/blob/3780e68cdb537d5a7ed2c84d9b3784f80c7c5d04/api.go#L555
|
// @see : https://github.com/TaqlaAI/zoekt/blob/3780e68cdb537d5a7ed2c84d9b3784f80c7c5d04/api.go#L555
|
||||||
export const repositorySchema = z.object({
|
const repositorySchema = z.object({
|
||||||
Name: z.string(),
|
Name: z.string(),
|
||||||
URL: z.string(),
|
URL: z.string(),
|
||||||
Source: z.string(),
|
Source: z.string(),
|
||||||
|
|
@ -121,8 +144,8 @@ export const listRepositoriesResponseSchema = z.object({
|
||||||
Repos: z.array(z.object({
|
Repos: z.array(z.object({
|
||||||
Repository: repositorySchema,
|
Repository: repositorySchema,
|
||||||
IndexMetadata: indexMetadataSchema,
|
IndexMetadata: indexMetadataSchema,
|
||||||
Stats: statsSchema,
|
Stats: repoStatsSchema,
|
||||||
})),
|
})),
|
||||||
Stats: statsSchema,
|
Stats: repoStatsSchema,
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -81,3 +81,18 @@ export const isServiceError = (data: unknown): data is ServiceError => {
|
||||||
'errorCode' in data &&
|
'errorCode' in data &&
|
||||||
'message' in data;
|
'message' in data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getEnv = (env: string | undefined, defaultValue = '') => {
|
||||||
|
return env ?? defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getEnvNumber = (env: string | undefined, defaultValue: number = 0) => {
|
||||||
|
return Number(env) ?? defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getEnvBoolean = (env: string | undefined, defaultValue: boolean) => {
|
||||||
|
if (!env) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
return env === 'true' || env === '1';
|
||||||
|
}
|
||||||
31
yarn.lock
31
yarn.lock
|
|
@ -1268,7 +1268,7 @@ class-variance-authority@^0.7.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
clsx "2.0.0"
|
clsx "2.0.0"
|
||||||
|
|
||||||
client-only@0.0.1:
|
client-only@0.0.1, client-only@^0.0.1:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
|
resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
|
||||||
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
|
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
|
||||||
|
|
@ -1897,6 +1897,11 @@ fastq@^1.6.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
reusify "^1.0.4"
|
reusify "^1.0.4"
|
||||||
|
|
||||||
|
fflate@^0.4.8:
|
||||||
|
version "0.4.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae"
|
||||||
|
integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==
|
||||||
|
|
||||||
file-entry-cache@^6.0.1:
|
file-entry-cache@^6.0.1:
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
|
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
|
||||||
|
|
@ -2901,6 +2906,20 @@ postcss@^8, postcss@^8.4.23:
|
||||||
picocolors "^1.0.1"
|
picocolors "^1.0.1"
|
||||||
source-map-js "^1.2.0"
|
source-map-js "^1.2.0"
|
||||||
|
|
||||||
|
posthog-js@^1.161.5:
|
||||||
|
version "1.161.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.161.5.tgz#3c07acf622c0719cd8e0e78ab4b0f3e85914c7ef"
|
||||||
|
integrity sha512-KGkb12grSQvGRauH6z+AUB83c4dgWqzmJFDjyMXarWRafaLN80HzjN1jk806x27HvdDXi21jtwiXekioWzEQ9g==
|
||||||
|
dependencies:
|
||||||
|
fflate "^0.4.8"
|
||||||
|
preact "^10.19.3"
|
||||||
|
web-vitals "^4.0.1"
|
||||||
|
|
||||||
|
preact@^10.19.3:
|
||||||
|
version "10.24.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/preact/-/preact-10.24.0.tgz#bd8139bee35aafede3c6de96d2453982610dfeef"
|
||||||
|
integrity sha512-aK8Cf+jkfyuZ0ZZRG9FbYqwmEiGQ4y/PUO4SuTWoyWL244nZZh7bd5h2APd4rSNDYTBNghg1L+5iJN3Skxtbsw==
|
||||||
|
|
||||||
prelude-ls@^1.2.1:
|
prelude-ls@^1.2.1:
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
||||||
|
|
@ -3113,6 +3132,11 @@ semver@^7.5.4, semver@^7.6.0, semver@^7.6.3:
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
|
||||||
integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
|
integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
|
||||||
|
|
||||||
|
server-only@^0.0.1:
|
||||||
|
version "0.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/server-only/-/server-only-0.0.1.tgz#0f366bb6afb618c37c9255a314535dc412cd1c9e"
|
||||||
|
integrity sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==
|
||||||
|
|
||||||
set-function-length@^1.2.1:
|
set-function-length@^1.2.1:
|
||||||
version "1.2.2"
|
version "1.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"
|
resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"
|
||||||
|
|
@ -3572,6 +3596,11 @@ w3c-keyname@^2.2.4:
|
||||||
resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz#7b17c8c6883d4e8b86ac8aba79d39e880f8869c5"
|
resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz#7b17c8c6883d4e8b86ac8aba79d39e880f8869c5"
|
||||||
integrity sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==
|
integrity sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==
|
||||||
|
|
||||||
|
web-vitals@^4.0.1:
|
||||||
|
version "4.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.3.tgz#270c4baecfbc6ec6fc15da1989e465e5f9b94fb7"
|
||||||
|
integrity sha512-/CFAm1mNxSmOj6i0Co+iGFJ58OS4NRGVP+AWS/l509uIK5a1bSoIVaHz/ZumpHTfHSZBpgrJ+wjfpAOrTHok5Q==
|
||||||
|
|
||||||
which-boxed-primitive@^1.0.2:
|
which-boxed-primitive@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
|
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue