Added posthog provider

This commit is contained in:
Nate Kelley 2025-09-03 12:15:24 -06:00
parent 7dfdb61c28
commit e1fb3e0454
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
6 changed files with 122 additions and 34 deletions

View File

@ -68,10 +68,13 @@ export const prefetchGetUserAttributes = async (userId: string, queryClientProp?
export const useGetUserTeams = ({ userId }: { userId: string }) => {
const queryFn = async () => getUserTeams({ userId });
return useQuery({
const { data } = useQuery({
...userQueryKeys.userGetUserTeams(userId),
queryFn,
enabled: !!userId,
notifyOnChangeProps: ['data'],
});
return data;
};
export const prefetchGetUserTeams = async (userId: string, queryClientProp?: QueryClient) => {

View File

@ -38,7 +38,7 @@ const parseGenericUrl: EmbedUrlParser = (url: string) => {
const urlParsers: EmbedUrlParser[] = [parseTwitterUrl, parseVideoUrl, parseGenericUrl];
const ACCEPTED_DOMAINS = [
process.env.NEXT_PUBLIC_URL,
process.env.VITE_PUBLIC_URL,
'twitter.com',
'x.com',
'youtube.com',

View File

@ -0,0 +1,112 @@
import { isServer } from '@tanstack/react-query';
import { ClientOnly } from '@tanstack/react-router';
import type { PostHogConfig } from 'posthog-js';
import React, { type PropsWithChildren, useEffect, useState } from 'react';
import { useGetUserTeams } from '@/api/buster_rest/users';
import {
useGetUserBasicInfo,
useGetUserOrganization,
} from '@/api/buster_rest/users/useGetUserInfo';
import { isDev } from '@/config/dev';
const POSTHOG_KEY = process.env.VITE_PUBLIC_POSTHOG_KEY;
const DEBUG_POSTHOG = false;
export const BusterPosthogProvider: React.FC<PropsWithChildren> = ({ children }) => {
if ((isDev && !DEBUG_POSTHOG) || !POSTHOG_KEY) {
return <>{children}</>;
}
return <PosthogWrapper>{children}</PosthogWrapper>;
};
BusterPosthogProvider.displayName = 'BusterPosthogProvider';
const options: Partial<PostHogConfig> = {
api_host: process.env.VITE_PUBLIC_POSTHOG_HOST,
person_profiles: 'always',
session_recording: {
recordBody: true,
},
loaded: () => {
console.log(
'%c🚀 Welcome to Buster',
'background: linear-gradient(to right, #a21caf, #8b1cb1, #6b21a8); color: white; font-size: 16px; font-weight: bold; padding: 10px; border-radius: 5px;'
);
console.log(
'%cBuster is your open-source data analytics platform. Found a bug? The code is open-source! Report it at https://github.com/buster-so/buster. Better yet, fix it yourself and send a PR.',
'background: #6b21a8; color: white; font-size: 10px; font-weight: normal; padding: 8px; border-radius: 4px;'
);
},
};
const PosthogWrapper: React.FC<PropsWithChildren> = ({ children }) => {
const user = useGetUserBasicInfo();
const userTeams = useGetUserTeams({ userId: user?.id ?? '' });
const userOrganizations = useGetUserOrganization();
const team = userTeams?.[0];
const [posthogModules, setPosthogModules] = useState<{
posthog: typeof import('posthog-js').default;
PostHogProvider: typeof import('posthog-js/react').PostHogProvider;
} | null>(null);
const [isLoading, setIsLoading] = useState(true);
// Async load posthog-js dependencies
useEffect(() => {
const loadPosthogModules = async () => {
try {
const [{ default: posthog }, { PostHogProvider }] = await Promise.all([
import('posthog-js'),
import('posthog-js/react'),
]);
setPosthogModules({ posthog, PostHogProvider });
} catch (error) {
console.error('Failed to load PostHog modules:', error);
} finally {
setIsLoading(false);
}
};
loadPosthogModules();
}, []);
// Initialize PostHog when modules are loaded and user data is available
useEffect(() => {
if (POSTHOG_KEY && !isServer && user && posthogModules?.posthog && team) {
const { posthog } = posthogModules;
if (posthog.__loaded) {
return;
}
posthog.init(POSTHOG_KEY, options);
const email = user.email;
posthog.identify(email, {
user,
organization: userOrganizations,
team,
});
posthog.group(team?.id, team?.name);
}
}, [user?.id, team?.id, posthogModules]);
// Show children while loading or if modules failed to load
if (isLoading || !posthogModules) {
return <>{children}</>;
}
const { PostHogProvider } = posthogModules;
if (isServer) {
return <>{children}</>;
}
return (
<ClientOnly>
<PostHogProvider client={posthogModules.posthog}>{children}</PostHogProvider>
</ClientOnly>
);
};

View File

@ -0,0 +1 @@
export * from './BusterPosthogProvider';

View File

@ -1,6 +1,7 @@
import type { QueryClient } from '@tanstack/react-query';
import type React from 'react';
import type { PropsWithChildren } from 'react';
import { BusterPosthogProvider } from '@/context/Posthog';
import { BusterStyleProvider } from './BusterStyles';
import { QueryPersister } from './Query/QueryProvider';
import {
@ -8,22 +9,6 @@ import {
type SupabaseContextType,
} from './Supabase/SupabaseContextProvider';
// import type { UseSupabaseUserContextType } from '@/lib/supabase';
// import { BusterAssetsProvider } from './Assets/BusterAssetsProvider';
// import { AppLayoutProvider } from './BusterAppLayout';
// import { BusterReactQueryProvider } from './BusterReactQuery/BusterReactQueryAndApi';
// import { BusterNewChatProvider } from './Chats';
// import { BusterPosthogProvider } from './Posthog';
// import { RoutePrefetcher } from './RoutePrefetcher';
// import { SupabaseContextProvider } from './Supabase/SupabaseContextProvider';
// import { BusterUserConfigProvider } from './Users/BusterUserConfigProvider';
// scan({
// enabled: true,
// log: true, // logs render info to console (default: false)
// clearLog: false // clears the console per group of renders (default: false)
// });
type RootProvidersProps = PropsWithChildren<SupabaseContextType & { queryClient: QueryClient }>;
export const RootProviders: React.FC<RootProvidersProps> = ({
@ -35,21 +20,9 @@ export const RootProviders: React.FC<RootProvidersProps> = ({
return (
<QueryPersister queryClient={queryClient}>
<SupabaseContextProvider user={user} accessToken={accessToken}>
<BusterStyleProvider>{children}</BusterStyleProvider>
{/* <BusterReactQueryProvider>
<HydrationBoundary state={dehydrate(queryClient)}>
<AppLayoutProvider>
<BusterUserConfigProvider>
<BusterAssetsProvider>
<BusterNewChatProvider>
<BusterPosthogProvider>{children}</BusterPosthogProvider>
<RoutePrefetcher />
</BusterNewChatProvider>
</BusterAssetsProvider>
</BusterUserConfigProvider>
</AppLayoutProvider>
</HydrationBoundary>
</BusterReactQueryProvider> */}
<BusterStyleProvider>
<BusterPosthogProvider>{children}</BusterPosthogProvider>
</BusterStyleProvider>
</SupabaseContextProvider>
</QueryPersister>
);

View File

@ -15,7 +15,6 @@ export const env = createEnv({
clientPrefix: 'VITE_',
client: {
VITE_APP_TITLE: z.string().min(1).optional(),
VITE_PUBLIC_API_URL: z.string().url(),
VITE_PUBLIC_API2_URL: z.string().url(),
VITE_PUBLIC_WEB_SOCKET_URL: z.string().url().optional(),