mirror of
https://github.com/supabase/supabase.git
synced 2026-10-17 23:29:08 +03:00
There were two bugs when trying to run the integrations page locally with NEXT_PUBLIC_IS_PLATFORM=false: 1. The IS_PLATFORM check imported from common was not evaluating correctly to a boolean. This is because I slapped a 'use client' on the entire common package last year -_-""" which caused all its imports to be evaluated to functions when used in server components. I have now moved the 'use client's down to the submodules that actually need it. 2. When the integrations submenu is empty, the navigation menu errors out because it expects all navigation items to either have children or have links. Have updated this to gracefully hide empty headers.
221 lines
5.8 KiB
TypeScript
221 lines
5.8 KiB
TypeScript
'use client'
|
|
|
|
import { components } from 'api-types'
|
|
import { useRouter } from 'next/compat/router'
|
|
import { usePathname } from 'next/navigation'
|
|
import { useCallback, useEffect, useRef } from 'react'
|
|
import { LOCAL_STORAGE_KEYS } from './constants'
|
|
import { useFeatureFlags } from './feature-flags'
|
|
import { post } from './fetchWrappers'
|
|
import { ensurePlatformSuffix, isBrowser } from './helpers'
|
|
import { useTelemetryCookie } from './hooks'
|
|
import { TelemetryEvent } from './telemetry-constants'
|
|
import { useUser } from './auth'
|
|
import { getSharedTelemetryData } from './telemetry-utils'
|
|
|
|
//---
|
|
// PAGE TELEMETRY
|
|
//---
|
|
|
|
export function handlePageTelemetry(
|
|
API_URL: string,
|
|
pathname?: string,
|
|
featureFlags?: {
|
|
[key: string]: unknown
|
|
},
|
|
telemetryDataOverride?: components['schemas']['TelemetryPageBodyV2Dto']
|
|
) {
|
|
return post(
|
|
`${ensurePlatformSuffix(API_URL)}/telemetry/page`,
|
|
telemetryDataOverride !== undefined
|
|
? { feature_flags: featureFlags, ...telemetryDataOverride }
|
|
: {
|
|
...getSharedTelemetryData(pathname),
|
|
feature_flags: featureFlags,
|
|
},
|
|
{ headers: { Version: '2' } }
|
|
)
|
|
}
|
|
|
|
export function handlePageLeaveTelemetry(
|
|
API_URL: string,
|
|
pathname: string,
|
|
featureFlags?: {
|
|
[key: string]: unknown
|
|
}
|
|
) {
|
|
return post(`${ensurePlatformSuffix(API_URL)}/telemetry/page-leave`, {
|
|
body: {
|
|
pathname,
|
|
page_url: isBrowser ? window.location.href : '',
|
|
page_title: isBrowser ? document?.title : '',
|
|
feature_flags: featureFlags,
|
|
},
|
|
})
|
|
}
|
|
|
|
export const PageTelemetry = ({
|
|
API_URL,
|
|
hasAcceptedConsent,
|
|
enabled = true,
|
|
}: {
|
|
API_URL: string
|
|
hasAcceptedConsent: boolean
|
|
enabled?: boolean
|
|
}) => {
|
|
const router = useRouter()
|
|
|
|
const pagesPathname = router?.pathname
|
|
const appPathname = usePathname()
|
|
|
|
const featureFlags = useFeatureFlags()
|
|
|
|
const title = typeof document !== 'undefined' ? document?.title : ''
|
|
const referrer = typeof document !== 'undefined' ? document?.referrer : ''
|
|
useTelemetryCookie({ hasAcceptedConsent, title, referrer })
|
|
|
|
const sendPageTelemetry = useCallback(() => {
|
|
if (!(enabled && hasAcceptedConsent)) return Promise.resolve()
|
|
|
|
return handlePageTelemetry(
|
|
API_URL,
|
|
pagesPathname ?? appPathname ?? undefined,
|
|
featureFlags.posthog
|
|
).catch((e) => {
|
|
console.error('Problem sending telemetry page:', e)
|
|
})
|
|
}, [API_URL, pagesPathname, appPathname, hasAcceptedConsent, featureFlags.posthog])
|
|
|
|
const sendPageLeaveTelemetry = useCallback(() => {
|
|
if (!(enabled && hasAcceptedConsent)) return Promise.resolve()
|
|
|
|
return handlePageTelemetry(
|
|
API_URL,
|
|
pagesPathname ?? appPathname ?? undefined,
|
|
featureFlags.posthog
|
|
).catch((e) => {
|
|
console.error('Problem sending telemetry page-leave:', e)
|
|
})
|
|
}, [pagesPathname, appPathname, hasAcceptedConsent, featureFlags.posthog])
|
|
|
|
const hasSentInitialPageTelemetryRef = useRef(false)
|
|
|
|
useEffect(() => {
|
|
// Send page telemetry on first page load
|
|
// Waiting for router ready before sending page_view
|
|
// if not the path will be dynamic route instead of the browser url
|
|
if (
|
|
(router?.isReady ?? true) &&
|
|
featureFlags.hasLoaded &&
|
|
!hasSentInitialPageTelemetryRef.current
|
|
) {
|
|
sendPageTelemetry()
|
|
hasSentInitialPageTelemetryRef.current = true
|
|
}
|
|
}, [router?.isReady, featureFlags.hasLoaded])
|
|
|
|
useEffect(() => {
|
|
// For pages router
|
|
if (router === null) return
|
|
|
|
function handleRouteChange() {
|
|
sendPageTelemetry()
|
|
}
|
|
|
|
// Listen for page changes after a navigation or when the query changes
|
|
router.events.on('routeChangeComplete', handleRouteChange)
|
|
|
|
return () => {
|
|
router.events.off('routeChangeComplete', handleRouteChange)
|
|
}
|
|
}, [router])
|
|
|
|
useEffect(() => {
|
|
// For app router
|
|
if (router !== null) return
|
|
|
|
if (appPathname) {
|
|
sendPageTelemetry()
|
|
}
|
|
}, [appPathname, router, sendPageTelemetry])
|
|
|
|
useEffect(() => {
|
|
if (!enabled) return
|
|
|
|
const handleBeforeUnload = () => sendPageLeaveTelemetry()
|
|
|
|
window.addEventListener('beforeunload', handleBeforeUnload)
|
|
return () => window.removeEventListener('beforeunload', handleBeforeUnload)
|
|
}, [enabled, sendPageLeaveTelemetry])
|
|
|
|
// Identify the user
|
|
useTelemetryIdentify(API_URL)
|
|
|
|
return null
|
|
}
|
|
|
|
// ---
|
|
// EVENT TELEMETRY
|
|
// ---
|
|
|
|
type EventBody = components['schemas']['TelemetryEventBodyV2Dto']
|
|
|
|
export function sendTelemetryEvent(API_URL: string, event: TelemetryEvent, pathname?: string) {
|
|
const consent =
|
|
(typeof window !== 'undefined'
|
|
? localStorage.getItem(LOCAL_STORAGE_KEYS.TELEMETRY_CONSENT)
|
|
: null) === 'true'
|
|
|
|
if (!consent) return
|
|
|
|
const body: EventBody = {
|
|
...getSharedTelemetryData(pathname),
|
|
action: event.action,
|
|
custom_properties: 'properties' in event ? event.properties : {},
|
|
groups: 'groups' in event ? event.groups : {},
|
|
}
|
|
|
|
return post(`${ensurePlatformSuffix(API_URL)}/telemetry/event`, body, {
|
|
headers: { Version: '2' },
|
|
})
|
|
}
|
|
|
|
//---
|
|
// TELEMETRY IDENTIFY
|
|
//---
|
|
|
|
type IdentifyBody = components['schemas']['TelemetryIdentifyBodyV2']
|
|
|
|
export function sendTelemetryIdentify(API_URL: string, body: IdentifyBody) {
|
|
const consent =
|
|
(typeof window !== 'undefined'
|
|
? localStorage.getItem(LOCAL_STORAGE_KEYS.TELEMETRY_CONSENT)
|
|
: null) === 'true'
|
|
|
|
if (!consent) return Promise.resolve()
|
|
|
|
return post(`${ensurePlatformSuffix(API_URL)}/telemetry/identify`, body, {
|
|
headers: { Version: '2' },
|
|
})
|
|
}
|
|
|
|
export function useTelemetryIdentify(API_URL: string) {
|
|
const user = useUser()
|
|
|
|
useEffect(() => {
|
|
if (user?.id) {
|
|
sendTelemetryIdentify(API_URL, {
|
|
user_id: user.id,
|
|
})
|
|
}
|
|
}, [API_URL, user?.id])
|
|
}
|
|
|
|
//---
|
|
// TELEMETRY RESET
|
|
//---
|
|
|
|
export function handleResetTelemetry(API_URL: string) {
|
|
return post(`${API_URL}/telemetry/reset`, {})
|
|
}
|