| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- import { useMemo } from 'react'
- import { useEdgeFunctionsDiff, type EdgeFunctionsDiffResult } from './useEdgeFunctionsDiff'
- import { useIsPgDeltaDiffEnabled } from '@/components/interfaces/App/FeaturePreview/FeaturePreviewContext'
- import { useBranchDiffQuery } from '@/data/branches/branch-diff-query'
- import { useMigrationsQuery } from '@/data/database/migrations-query'
- interface UseBranchMergeDiffProps {
- currentBranchRef?: string
- parentProjectRef?: string
- currentBranchConnectionString?: string
- parentBranchConnectionString?: string
- currentBranchCreatedAt?: string
- }
- export interface BranchMergeDiffResult {
- // Database diff
- diffContent: string | undefined
- isDatabaseDiffLoading: boolean
- isDatabaseDiffRefetching: boolean
- databaseDiffError: any
- refetchDatabaseDiff: () => void
- // Edge functions diff
- edgeFunctionsDiff: EdgeFunctionsDiffResult
- // Migrations
- currentBranchMigrations: any[] | undefined
- mainBranchMigrations: any[] | undefined
- refetchCurrentBranchMigrations: () => void
- refetchMainBranchMigrations: () => void
- // Branch state
- isBranchOutOfDateMigrations: boolean
- hasEdgeFunctionModifications: boolean
- missingFunctionsCount: number
- hasMissingFunctions: boolean
- outOfDateFunctionsCount: number
- hasOutOfDateFunctions: boolean
- isBranchOutOfDateOverall: boolean
- missingMigrationsCount: number
- modifiedFunctionsCount: number
- // Combined states
- isLoading: boolean
- hasChanges: boolean
- }
- export const useBranchMergeDiff = ({
- currentBranchRef,
- parentProjectRef,
- currentBranchConnectionString,
- parentBranchConnectionString,
- currentBranchCreatedAt,
- }: UseBranchMergeDiffProps): BranchMergeDiffResult => {
- const pgDeltaDiffEnabled = useIsPgDeltaDiffEnabled()
- // Get database diff
- const {
- data: diffContent,
- isPending: isDatabaseDiffLoading,
- isRefetching: isDatabaseDiffRefetching,
- error: databaseDiffError,
- refetch: refetchDatabaseDiff,
- } = useBranchDiffQuery(
- {
- branchRef: currentBranchRef || '',
- projectRef: parentProjectRef || '',
- pgdelta: pgDeltaDiffEnabled,
- },
- {
- enabled: !!currentBranchRef && !!parentProjectRef,
- refetchOnMount: 'always',
- refetchOnWindowFocus: false,
- staleTime: 0,
- }
- )
- // Get migrations for both current branch and main branch
- const { data: currentBranchMigrations, refetch: refetchCurrentBranchMigrations } =
- useMigrationsQuery(
- {
- projectRef: currentBranchRef,
- connectionString: currentBranchConnectionString,
- },
- {
- enabled: !!currentBranchRef,
- staleTime: 3000,
- }
- )
- const { data: mainBranchMigrations, refetch: refetchMainBranchMigrations } = useMigrationsQuery(
- {
- projectRef: parentProjectRef,
- connectionString: parentBranchConnectionString,
- },
- {
- enabled: !!parentProjectRef,
- staleTime: 3000,
- }
- )
- // Get edge functions diff
- const edgeFunctionsDiff = useEdgeFunctionsDiff({
- currentBranchRef,
- mainBranchRef: parentProjectRef,
- })
- // Check if current branch is out of date with main branch (migrations)
- const isBranchOutOfDateMigrations = useMemo(() => {
- if (!currentBranchMigrations || !mainBranchMigrations) return false
- // Get the latest migration version from main branch
- const latestMainMigration = mainBranchMigrations[0] // migrations are ordered by version desc
- if (!latestMainMigration) return false
- // Check if current branch has this latest migration
- const hasLatestMigration = currentBranchMigrations.some(
- (migration) => migration.version === latestMainMigration.version
- )
- return !hasLatestMigration
- }, [currentBranchMigrations, mainBranchMigrations])
- // Check if main branch has functions that are newer than the current branch versions
- const outOfDateFunctionsCount = useMemo(() => {
- if (!edgeFunctionsDiff.modifiedSlugs.length) return 0
- return edgeFunctionsDiff.modifiedSlugs.filter((slug) => {
- // Get both main and current branch function data
- const mainFunction = edgeFunctionsDiff.mainBranchFunctions?.find((func) => func.slug === slug)
- const currentFunction = edgeFunctionsDiff.currentBranchFunctions?.find(
- (func) => func.slug === slug
- )
- if (!mainFunction || !currentFunction) return false
- // Compare updated_at timestamps - if main branch function is newer, it was modified after current branch
- const mainUpdatedAt = mainFunction.updated_at * 1000 // Convert to milliseconds
- const currentUpdatedAt = currentFunction.updated_at * 1000 // Convert to milliseconds
- return mainUpdatedAt > currentUpdatedAt
- }).length
- }, [
- edgeFunctionsDiff.modifiedSlugs,
- edgeFunctionsDiff.mainBranchFunctions,
- edgeFunctionsDiff.currentBranchFunctions,
- ])
- // Check if main branch has functions that are newer than the current branch versions
- const hasOutOfDateFunctions = outOfDateFunctionsCount > 0
- // Check if current branch has any edge function modifications (not additions/removals)
- // This only includes functions where the current branch version is newer than the main branch version
- const hasEdgeFunctionModifications =
- edgeFunctionsDiff.modifiedSlugs.length > outOfDateFunctionsCount
- // Count of removed functions that were updated on main branch after this branch was created
- // Note: For removed functions, we use branch creation date since there's no current branch version to compare to
- const missingFunctionsCount = useMemo(() => {
- if (!currentBranchCreatedAt || !edgeFunctionsDiff.removedSlugs.length) return 0
- const branchCreatedAt = new Date(currentBranchCreatedAt).getTime()
- return edgeFunctionsDiff.removedSlugs.filter((slug) => {
- // Access main branch function data from the original functions list
- const mainFunction = edgeFunctionsDiff.mainBranchFunctions?.find((func) => func.slug === slug)
- if (!mainFunction) return false
- // Check if function was updated after branch creation
- const functionUpdatedAt = mainFunction.updated_at * 1000 // Convert to milliseconds
- return functionUpdatedAt > branchCreatedAt
- }).length
- }, [
- currentBranchCreatedAt,
- edgeFunctionsDiff.removedSlugs,
- edgeFunctionsDiff.mainBranchFunctions,
- ])
- // Check if main branch has functions removed from current branch that were updated after branch creation
- const hasMissingFunctions = missingFunctionsCount > 0
- // Update overall out-of-date check to include newer removed functions and newer modified functions
- const isBranchOutOfDateOverall =
- isBranchOutOfDateMigrations || hasMissingFunctions || hasOutOfDateFunctions
- // Get the count of migrations that the branch is missing
- const missingMigrationsCount = useMemo(() => {
- if (!currentBranchMigrations || !mainBranchMigrations || !isBranchOutOfDateMigrations) return 0
- const currentVersions = new Set(currentBranchMigrations.map((m) => m.version))
- return mainBranchMigrations.filter((m) => !currentVersions.has(m.version)).length
- }, [currentBranchMigrations, mainBranchMigrations, isBranchOutOfDateMigrations])
- // Get count of modified functions
- const modifiedFunctionsCount = edgeFunctionsDiff.modifiedSlugs.length
- // Check if there are any changes (database or edge functions)
- const hasChanges = useMemo(() => {
- // Check database changes
- const hasDatabaseChanges = diffContent && diffContent.trim() !== ''
- // Check edge function changes
- const hasEdgeFunctionChanges = edgeFunctionsDiff.hasChanges
- return hasDatabaseChanges || hasEdgeFunctionChanges
- }, [diffContent, edgeFunctionsDiff.hasChanges])
- const isLoading = isDatabaseDiffLoading || edgeFunctionsDiff.isLoading
- return {
- // Database diff
- diffContent,
- isDatabaseDiffLoading,
- isDatabaseDiffRefetching,
- databaseDiffError,
- refetchDatabaseDiff,
- // Edge functions diff
- edgeFunctionsDiff,
- // Migrations
- currentBranchMigrations,
- mainBranchMigrations,
- refetchCurrentBranchMigrations,
- refetchMainBranchMigrations,
- // Branch state
- isBranchOutOfDateMigrations,
- hasEdgeFunctionModifications,
- missingFunctionsCount,
- hasMissingFunctions,
- outOfDateFunctionsCount,
- hasOutOfDateFunctions,
- isBranchOutOfDateOverall,
- missingMigrationsCount,
- modifiedFunctionsCount,
- // Combined states
- isLoading,
- hasChanges,
- }
- }
|