Shift useFlag hook and configcat library to common package, remove from Studio (#38203)

* Shift useFlag hook and configcat library to common package, remove from studio

* Fix test

* Fix test
This commit is contained in:
Joshen Lim
2025-08-27 13:42:20 +07:00
committed by GitHub
parent 5e87a858ec
commit 4124f0ed98
45 changed files with 220 additions and 1304 deletions

View File

@@ -1,9 +1,9 @@
import { PropsWithChildren } from 'react'
import { useFlag } from 'common'
import { ClockSkewBanner } from 'components/layouts/AppLayout/ClockSkewBanner'
import IncidentBanner from 'components/layouts/AppLayout/IncidentBanner'
import { NoticeBanner } from 'components/layouts/AppLayout/NoticeBanner'
import { useFlag } from 'hooks/ui/useFlag'
import { OrganizationResourceBanner } from '../Organization/HeaderBanner'
const AppBannerWrapper = ({ children }: PropsWithChildren<{}>) => {

View File

@@ -10,9 +10,8 @@ import {
useState,
} from 'react'
import { FeatureFlagContext, LOCAL_STORAGE_KEYS } from 'common'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useFlag, useIsRealtimeSettingsFFEnabled } from 'hooks/ui/useFlag'
import { FeatureFlagContext, LOCAL_STORAGE_KEYS, useFlag } from 'common'
import { useIsRealtimeSettingsFFEnabled } from 'hooks/ui/useFlag'
import { EMPTY_OBJ } from 'lib/void'
import { FEATURE_PREVIEWS } from './FeaturePreview.constants'

View File

@@ -1,6 +1,7 @@
import { ChevronDown } from 'lucide-react'
import Image from 'next/image'
import { useFlag } from 'common'
import {
Button,
cn,
@@ -11,7 +12,6 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from 'ui'
import { useFlag } from 'hooks/ui/useFlag'
import {
getIntegrationTypeIcon,
getIntegrationTypeLabel,

View File

@@ -10,7 +10,7 @@ import { toast } from 'sonner'
import * as z from 'zod'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import { useIsBranching2Enabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
import { BranchingPITRNotice } from 'components/layouts/AppLayout/EnableBranchingButton/BranchingPITRNotice'
import AlertError from 'components/ui/AlertError'
@@ -27,7 +27,6 @@ import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { useFlag } from 'hooks/ui/useFlag'
import { BASE_PATH, IS_PLATFORM } from 'lib/constants'
import { useAppStateSnapshot } from 'state/app-state'
import {
@@ -51,15 +50,16 @@ import {
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
export const CreateBranchModal = () => {
const allowDataBranching = useFlag('allowDataBranching')
const { ref } = useParams()
const router = useRouter()
const queryClient = useQueryClient()
const { data: projectDetails } = useSelectedProjectQuery()
const { data: selectedOrg } = useSelectedOrganizationQuery()
const gitlessBranching = useIsBranching2Enabled()
const { showCreateBranchModal, setShowCreateBranchModal } = useAppStateSnapshot()
const gitlessBranching = useIsBranching2Enabled()
const allowDataBranching = useFlag('allowDataBranching')
const isProPlanAndUp = selectedOrg?.plan?.id !== 'free'
const promptProPlanUpgrade = IS_PLATFORM && !isProPlanAndUp

View File

@@ -3,7 +3,7 @@ import { RotateCw, Timer } from 'lucide-react'
import { useMemo, useState } from 'react'
import { toast } from 'sonner'
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
import { useLegacyAPIKeysStatusQuery } from 'data/api-keys/legacy-api-keys-status-query'
import { useJWTSigningKeyDeleteMutation } from 'data/jwt-signing-keys/jwt-signing-key-delete-mutation'
@@ -12,7 +12,6 @@ import { JWTSigningKey, useJWTSigningKeysQuery } from 'data/jwt-signing-keys/jwt
import { useLegacyJWTSigningKeyCreateMutation } from 'data/jwt-signing-keys/legacy-jwt-signing-key-create-mutation'
import { useLegacyJWTSigningKeyQuery } from 'data/jwt-signing-keys/legacy-jwt-signing-key-query'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { useFlag } from 'hooks/ui/useFlag'
import {
AlertDialog,
AlertDialogCancel,
@@ -48,7 +47,7 @@ import { SigningKeyRow } from './signing-key-row'
type DialogType = 'legacy' | 'create' | 'rotate' | 'key-details' | 'revoke' | 'delete'
export default function JWTSecretKeysTable() {
export const JWTSecretKeysTable = () => {
const { ref: projectRef } = useParams()
const { data: project, isLoading: isProjectLoading } = useSelectedProjectQuery()

View File

@@ -4,7 +4,8 @@ import {
JwtSecretUpdateProgress,
JwtSecretUpdateStatus,
} from '@supabase/shared-types/out/events'
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
import { FormActions } from 'components/ui/Forms/FormActions'
import Panel from 'components/ui/Panel'
@@ -16,7 +17,6 @@ import { useJwtSecretUpdatingStatusQuery } from 'data/config/jwt-secret-updating
import { useProjectPostgrestConfigQuery } from 'data/config/project-postgrest-config-query'
import { useLegacyJWTSigningKeyQuery } from 'data/jwt-signing-keys/legacy-jwt-signing-key-query'
import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useFlag } from 'hooks/ui/useFlag'
import { uuidv4 } from 'lib/helpers'
import {
AlertCircle,

View File

@@ -4,7 +4,7 @@ import { useTheme } from 'next-themes'
import Image from 'next/image'
import Link from 'next/link'
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import {
ScaffoldSection,
ScaffoldSectionContent,
@@ -17,15 +17,14 @@ import ShimmeringLoader from 'components/ui/ShimmeringLoader'
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useFlag } from 'hooks/ui/useFlag'
import { BASE_PATH } from 'lib/constants'
import { MANAGED_BY } from 'lib/constants/infrastructure'
import { useOrgSettingsPageStateSnapshot } from 'state/organization-settings'
import { Alert, AlertTitle_Shadcn_, Alert_Shadcn_, Button } from 'ui'
import PartnerIcon from 'components/ui/PartnerIcon'
import ProjectUpdateDisabledTooltip from '../ProjectUpdateDisabledTooltip'
import SpendCapSidePanel from './SpendCapSidePanel'
import PartnerIcon from 'components/ui/PartnerIcon'
export interface CostControlProps {}

View File

@@ -1,12 +1,11 @@
import { useState } from 'react'
import { toast } from 'sonner'
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import { CANCELLATION_REASONS } from 'components/interfaces/Billing/Billing.constants'
import { useSendDowngradeFeedbackMutation } from 'data/feedback/exit-survey-send'
import { ProjectInfo } from 'data/projects/projects-query'
import { useOrgSubscriptionUpdateMutation } from 'data/subscriptions/org-subscription-update-mutation'
import { useFlag } from 'hooks/ui/useFlag'
import { Alert, Button, cn, Input, Modal } from 'ui'
import ProjectUpdateDisabledTooltip from '../ProjectUpdateDisabledTooltip'

View File

@@ -14,7 +14,7 @@ import {
} from 'react'
import { toast } from 'sonner'
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import { getStripeElementsAppearanceOptions } from 'components/interfaces/Billing/Payment/Payment.utils'
import { useOrganizationCustomerProfileQuery } from 'data/organizations/organization-customer-profile-query'
import { useOrganizationPaymentMethodSetupIntent } from 'data/organizations/organization-payment-method-setup-intent-mutation'
@@ -22,7 +22,6 @@ import { useOrganizationPaymentMethodsQuery } from 'data/organizations/organizat
import { useOrganizationTaxIdQuery } from 'data/organizations/organization-tax-id-query'
import { SetupIntentResponse } from 'data/stripe/setup-intent-mutation'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useFlag } from 'hooks/ui/useFlag'
import { BASE_PATH, STRIPE_PUBLIC_KEY } from 'lib/constants'
import { Checkbox_Shadcn_, Listbox } from 'ui'
import ShimmeringLoader from 'ui-patterns/ShimmeringLoader'

View File

@@ -1,7 +1,7 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import Link from 'next/link'
import { useFlag, useParams } from 'common'
import {
ScaffoldSection,
ScaffoldSectionContent,
@@ -12,7 +12,6 @@ import NoPermission from 'components/ui/NoPermission'
import ShimmeringLoader from 'components/ui/ShimmeringLoader'
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useFlag } from 'hooks/ui/useFlag'
import { useOrgSettingsPageStateSnapshot } from 'state/organization-settings'
import { Alert, Button } from 'ui'
import { Admonition } from 'ui-patterns'

View File

@@ -1,9 +1,8 @@
import { ControllerRenderProps, UseFormReturn } from 'react-hook-form'
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import { useDefaultRegionQuery } from 'data/misc/get-default-region-query'
import { useOrganizationAvailableRegionsQuery } from 'data/organizations/organization-available-regions-query'
import { useFlag } from 'hooks/ui/useFlag'
import { BASE_PATH, PROVIDERS } from 'lib/constants'
import type { CloudProvider } from 'shared-data'
import {

View File

@@ -5,7 +5,7 @@ import Image from 'next/image'
import Link from 'next/link'
import { useMemo } from 'react'
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import {
getAddons,
subscriptionHasHipaaAddon,
@@ -35,7 +35,6 @@ import {
useProjectByRefQuery,
useSelectedProjectQuery,
} from 'hooks/misc/useSelectedProject'
import { useFlag } from 'hooks/ui/useFlag'
import { getCloudProviderArchitecture } from 'lib/cloudprovider-utils'
import { BASE_PATH, INSTANCE_MICRO_SPECS, INSTANCE_NANO_SPECS } from 'lib/constants'
import { getDatabaseMajorVersion, getSemanticVersion } from 'lib/helpers'

View File

@@ -1,18 +1,17 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { AlertCircle, ExternalLink } from 'lucide-react'
import Link from 'next/link'
import { useEffect, useState } from 'react'
import { toast } from 'sonner'
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import { useProjectAddonRemoveMutation } from 'data/subscriptions/project-addon-remove-mutation'
import { useProjectAddonUpdateMutation } from 'data/subscriptions/project-addon-update-mutation'
import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query'
import type { AddonVariantId } from 'data/subscriptions/types'
import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useFlag } from 'hooks/ui/useFlag'
import { formatCurrency } from 'lib/helpers'
import { AlertCircle, ExternalLink } from 'lucide-react'
import { useAddonsPagePanel } from 'state/addons-page'
import {
Alert,

View File

@@ -1,14 +1,13 @@
import { AlertCircle } from 'lucide-react'
import Link from 'next/link'
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import { FormHeader } from 'components/ui/Forms/FormHeader'
import Panel from 'components/ui/Panel'
import UpgradeToPro from 'components/ui/UpgradeToPro'
import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query'
import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useFlag } from 'hooks/ui/useFlag'
import CustomDomainActivate from './CustomDomainActivate'
import CustomDomainDelete from './CustomDomainDelete'
import CustomDomainVerify from './CustomDomainVerify'

View File

@@ -8,7 +8,7 @@ import { useForm } from 'react-hook-form'
import { toast } from 'sonner'
import { z } from 'zod'
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import { PLAN_DETAILS } from 'components/interfaces/DiskManagement/ui/DiskManagement.constants'
import { Markdown } from 'components/interfaces/Markdown'
import { useDiskAttributesQuery } from 'data/config/disk-attributes-query'
@@ -20,7 +20,6 @@ import { ReleaseChannel } from 'data/projects/new-project.constants'
import { useProjectUpgradeMutation } from 'data/projects/project-upgrade-mutation'
import { setProjectStatus } from 'data/projects/projects-query'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useFlag } from 'hooks/ui/useFlag'
import { PROJECT_STATUS } from 'lib/constants'
import {
AlertDescription_Shadcn_,

View File

@@ -5,6 +5,7 @@ import { useRouter } from 'next/router'
import { useState } from 'react'
import { toast } from 'sonner'
import { useFlag } from 'common'
import { useIsProjectActive } from 'components/layouts/ProjectLayout/ProjectContext'
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
import { useProjectRestartMutation } from 'data/projects/project-restart-mutation'
@@ -12,7 +13,6 @@ import { useProjectRestartServicesMutation } from 'data/projects/project-restart
import { setProjectStatus } from 'data/projects/projects-query'
import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useIsAwsK8sCloudProvider, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { useFlag } from 'hooks/ui/useFlag'
import {
Button,
DropdownMenu,

View File

@@ -3,6 +3,7 @@ import { Loader, Shield, Users, Wrench } from 'lucide-react'
import { useEffect, useState } from 'react'
import { toast } from 'sonner'
import { useFlag } from 'common'
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
import { DocsButton } from 'components/ui/DocsButton'
import { useOrganizationsQuery } from 'data/organizations/organizations-query'
@@ -10,7 +11,6 @@ import { useProjectTransferMutation } from 'data/projects/project-transfer-mutat
import { useProjectTransferPreviewQuery } from 'data/projects/project-transfer-preview-query'
import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { useFlag } from 'hooks/ui/useFlag'
import { Button, InfoIcon, Listbox, Loading, Modal, WarningIcon } from 'ui'
import { Admonition } from 'ui-patterns'

View File

@@ -3,7 +3,7 @@ import { Rewind } from 'lucide-react'
import { useRouter } from 'next/router'
import { PropsWithChildren, useEffect, useState } from 'react'
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import PreviewFilterPanel from 'components/interfaces/Settings/Logs/PreviewFilterPanel'
import LoadingOpacity from 'components/ui/LoadingOpacity'
import ShimmerLine from 'components/ui/ShimmerLine'
@@ -14,7 +14,6 @@ import { useSelectedLog } from 'hooks/analytics/useSelectedLog'
import useSingleLog from 'hooks/analytics/useSingleLog'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useUpgradePrompt } from 'hooks/misc/useUpgradePrompt'
import { useFlag } from 'hooks/ui/useFlag'
import { useDatabaseSelectorStateSnapshot } from 'state/database-selector'
import { Button } from 'ui'
import { LogsBarChart } from 'ui-patterns/LogsBarChart'

View File

@@ -113,7 +113,7 @@ describe(`DeleteBucketModal`, () => {
const input = screen.getByLabelText(/Type/)
await userEvent.type(input, `test`)
const confirmButton = screen.getByRole(`button`, { name: `Delete Bucket` })
const confirmButton = screen.getByRole(`button`, { name: `Delete bucket` })
fireEvent.click(confirmButton)
await waitFor(() => expect(onClose).toHaveBeenCalledOnce())
@@ -131,7 +131,7 @@ describe(`DeleteBucketModal`, () => {
const input = screen.getByLabelText(/Type/)
await userEvent.type(input, `invalid`)
const confirmButton = screen.getByRole(`button`, { name: `Delete Bucket` })
const confirmButton = screen.getByRole(`button`, { name: `Delete bucket` })
fireEvent.click(confirmButton)
await waitFor(() => {

View File

@@ -87,7 +87,7 @@ describe(`EmptyBucketModal`, () => {
await userEvent.click(openButton)
await screen.findByRole(`dialog`)
const confirmButton = screen.getByRole(`button`, { name: `Empty Bucket` })
const confirmButton = screen.getByRole(`button`, { name: `Empty bucket` })
fireEvent.click(confirmButton)

View File

@@ -1,6 +1,7 @@
import { useRouter } from 'next/router'
import { PropsWithChildren } from 'react'
import { useFlag } from 'common'
import { useIsColumnLevelPrivilegesEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
import { ProductMenu } from 'components/ui/ProductMenu'
import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query'
@@ -8,7 +9,6 @@ import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { withAuth } from 'hooks/misc/withAuth'
import { useFlag } from 'hooks/ui/useFlag'
import ProjectLayout from '../ProjectLayout/ProjectLayout'
import { generateDatabaseMenu } from './DatabaseMenu.utils'

View File

@@ -1,6 +1,7 @@
import { useRouter } from 'next/router'
import { PropsWithChildren, useEffect, useRef, useState } from 'react'
import { useFlag } from 'common'
import { useInstalledIntegrations } from 'components/interfaces/Integrations/Landing/useInstalledIntegrations'
import { Header } from 'components/layouts/Integrations/header'
import ProjectLayout from 'components/layouts/ProjectLayout/ProjectLayout'
@@ -11,7 +12,6 @@ import ProductMenuItem from 'components/ui/ProductMenu/ProductMenuItem'
import { useScroll } from 'framer-motion'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { withAuth } from 'hooks/misc/withAuth'
import { useFlag } from 'hooks/ui/useFlag'
import { Menu, Separator } from 'ui'
import { GenericSkeletonLoader } from 'ui-patterns'
import { IntegrationTabs } from './tabs'

View File

@@ -3,7 +3,7 @@ import Link from 'next/link'
import { useRouter } from 'next/router'
import { useState } from 'react'
import { IS_PLATFORM, useParams } from 'common'
import { IS_PLATFORM, useFlag, useParams } from 'common'
import {
useFeaturePreviewModal,
useUnifiedLogsPreview,
@@ -15,7 +15,6 @@ import { useContentQuery } from 'data/content/content-query'
import { useReplicationSourcesQuery } from 'data/replication/sources-query'
import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { useFlag } from 'hooks/ui/useFlag'
import {
Badge,
Button,

View File

@@ -9,7 +9,7 @@ import { useForm } from 'react-hook-form'
import { toast } from 'sonner'
import { z } from 'zod'
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import { PostgresVersionSelector } from 'components/interfaces/ProjectCreation/PostgresVersionSelector'
import AlertError from 'components/ui/AlertError'
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
@@ -21,7 +21,7 @@ import { setProjectStatus } from 'data/projects/projects-query'
import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { useFlag, usePHFlag } from 'hooks/ui/useFlag'
import { usePHFlag } from 'hooks/ui/useFlag'
import { PROJECT_STATUS } from 'lib/constants'
import { AWS_REGIONS, CloudProvider } from 'shared-data'
import {

View File

@@ -2,10 +2,10 @@ import { PermissionAction } from '@supabase/shared-types/out/constants'
import { Plus } from 'lucide-react'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useState, useMemo } from 'react'
import { useMemo, useState } from 'react'
import { toast } from 'sonner'
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import { CreateReportModal } from 'components/interfaces/Reports/CreateReportModal'
import { UpdateCustomReportModal } from 'components/interfaces/Reports/UpdateModal'
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
@@ -18,7 +18,6 @@ import { useProfile } from 'lib/profile'
import { Menu, cn } from 'ui'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
import { ReportMenuItem } from './ReportMenuItem'
import { useFlag } from 'hooks/ui/useFlag'
const ReportsMenu = () => {
const router = useRouter()

View File

@@ -1,13 +1,14 @@
import { useQueryClient } from '@tanstack/react-query'
import { DocsButton } from 'components/ui/DocsButton'
import { useFlag } from 'hooks/ui/useFlag'
import { BASE_PATH } from 'lib/constants'
import { auth, buildPathWithParams, getAccessToken, getReturnToPath } from 'lib/gotrue'
import { useTheme } from 'next-themes'
import Image from 'next/legacy/image'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { PropsWithChildren, useEffect, useState } from 'react'
import { useFlag } from 'common'
import { DocsButton } from 'components/ui/DocsButton'
import { BASE_PATH } from 'lib/constants'
import { auth, buildPathWithParams, getAccessToken, getReturnToPath } from 'lib/gotrue'
import { tweets } from 'shared-data'
type SignInLayoutProps = {

View File

@@ -6,7 +6,7 @@ import { ArrowDown, Eraser, Info, Pencil, Settings, X } from 'lucide-react'
import { useRouter } from 'next/router'
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { LOCAL_STORAGE_KEYS } from 'common'
import { LOCAL_STORAGE_KEYS, useFlag } from 'common'
import { useParams, useSearchParamsShallow } from 'common/hooks'
import { Markdown } from 'components/interfaces/Markdown'
import { useCheckOpenAIKeyQuery } from 'data/ai/check-api-key-query'
@@ -17,7 +17,6 @@ import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
import { useOrgAiOptInLevel } from 'hooks/misc/useOrgOptedIntoAi'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { useFlag } from 'hooks/ui/useFlag'
import { useHotKey } from 'hooks/ui/useHotKey'
import { BASE_PATH, IS_PLATFORM } from 'lib/constants'
import uuidv4 from 'lib/uuid'

View File

@@ -1,8 +1,7 @@
import { useRouter } from 'next/router'
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import { useUnifiedLogsPreview } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
import { useFlag } from 'hooks/ui/useFlag'
import { Button, cn, ResizablePanel } from 'ui'
import { FeaturePreviewSidebarPanel } from '../FeaturePreviewSidebarPanel'
import { DateRangeDisabled } from './DataTable.types'

View File

@@ -2,10 +2,10 @@ import { PermissionAction } from '@supabase/shared-types/out/constants'
import Link from 'next/link'
import { ReactNode } from 'react'
import { useFlag } from 'common'
import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { useFlag } from 'hooks/ui/useFlag'
import { Button, cn } from 'ui'
import { ButtonTooltip } from './ButtonTooltip'

View File

@@ -1,12 +1,12 @@
import { useQuery, UseQueryOptions } from '@tanstack/react-query'
import { useFlag } from 'common'
import { COUNTRY_LAT_LON } from 'components/interfaces/ProjectCreation/ProjectCreation.constants'
import {
AWS_REGIONS_COORDINATES,
FLY_REGIONS_COORDINATES,
} from 'components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.constants'
import { fetchHandler } from 'data/fetchers'
import { useFlag } from 'hooks/ui/useFlag'
import { getDistanceLatLonKM, tryParseJson } from 'lib/helpers'
import type { CloudProvider } from 'shared-data'
import { AWS_REGIONS, FLY_REGIONS } from 'shared-data'

View File

@@ -1,6 +1,6 @@
import * as Sentry from '@sentry/nextjs'
import { useFeatureFlags } from 'common'
import { useFeatureFlags, useFlag } from 'common'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { trackFeatureFlag } from 'lib/posthog'
@@ -9,18 +9,6 @@ const isObjectEmpty = (obj: Object) => {
return Object.keys(obj).length === 0
}
export function useFlag<T = boolean>(name: string) {
const flagStore = useFeatureFlags()
const store = flagStore.configcat
if (!isObjectEmpty(store) && store[name] === undefined) {
console.error(`Flag key "${name}" does not exist in ConfigCat flag store`)
return false
}
return store[name] as T
}
// TODO(Alaister): move this to packages/common/feature-flags.tsx and rename to useFlag
export function usePHFlag<T = string | boolean>(name: string) {
const flagStore = useFeatureFlags()

View File

@@ -3,10 +3,9 @@ import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import { toast } from 'sonner'
import { IS_PLATFORM } from 'common'
import { IS_PLATFORM, useFlag } from 'common'
import { useDeploymentCommitQuery } from 'data/utils/deployment-commit-query'
import { Button, StatusIcon } from 'ui'
import { useFlag } from './ui/useFlag'
const DeployCheckToast = ({ id }: { id: string | number }) => {
const router = useRouter()

View File

@@ -76,7 +76,6 @@
"common": "workspace:*",
"common-tags": "^1.8.2",
"config": "workspace:*",
"configcat-js": "^9.5.1",
"cron-parser": "^4.9.0",
"cronstrue": "^2.50.0",
"dayjs": "^1.11.10",

View File

@@ -33,7 +33,13 @@ import { NuqsAdapter } from 'nuqs/adapters/next/pages'
import { ErrorInfo } from 'react'
import { ErrorBoundary } from 'react-error-boundary'
import { FeatureFlagProvider, TelemetryTagManager, ThemeProvider, useThemeSandbox } from 'common'
import {
FeatureFlagProvider,
getFlags as getConfigCatFlags,
TelemetryTagManager,
ThemeProvider,
useThemeSandbox,
} from 'common'
import MetaFaviconsPagesRouter from 'common/MetaFavicons/pages-router'
import { RouteValidationWrapper } from 'components/interfaces/App'
import { AppBannerContextProvider } from 'components/interfaces/App/AppBannerWrapperContext'
@@ -45,7 +51,6 @@ import { GlobalErrorBoundaryState } from 'components/ui/GlobalErrorBoundaryState
import { useRootQueryClient } from 'data/query-client'
import { customFont, sourceCodePro } from 'fonts'
import { AuthProvider } from 'lib/auth'
import { getFlags as getConfigCatFlags } from 'lib/configcat'
import { API_URL, BASE_PATH, IS_PLATFORM } from 'lib/constants'
import { ProfileProvider } from 'lib/profile'
import { Telemetry } from 'lib/telemetry'

View File

@@ -11,7 +11,7 @@ import { z } from 'zod'
import { PopoverSeparator } from '@ui/components/shadcn/ui/popover'
import { components } from 'api-types'
import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import { LOCAL_STORAGE_KEYS, useFlag, useParams } from 'common'
import {
FreeProjectLimitWarning,
NotOrganizationOwnerWarning,
@@ -53,7 +53,6 @@ import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { withAuth } from 'hooks/misc/withAuth'
import { useFlag } from 'hooks/ui/useFlag'
import { getCloudProviderArchitecture } from 'lib/cloudprovider-utils'
import {
AWS_REGIONS_DEFAULT,

View File

@@ -1,13 +1,12 @@
import { useRouter } from 'next/router'
import { useContext, useEffect } from 'react'
import { FeatureFlagContext, useParams } from 'common'
import { FeatureFlagContext, useFlag, useParams } from 'common'
import { ReplicationPipelineStatus } from 'components/interfaces/Database/Replication/ReplicationPipelineStatus'
import DatabaseLayout from 'components/layouts/DatabaseLayout/DatabaseLayout'
import DefaultLayout from 'components/layouts/DefaultLayout'
import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold'
import { FormHeader } from 'components/ui/Forms/FormHeader'
import { useFlag } from 'hooks/ui/useFlag'
import { PipelineRequestStatusProvider } from 'state/replication-pipeline-request-status'
import type { NextPageWithLayout } from 'types'

View File

@@ -1,4 +1,4 @@
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import { ReplicationComingSoon } from 'components/interfaces/Database/Replication/ComingSoon'
import { Destinations } from 'components/interfaces/Database/Replication/Destinations'
import DatabaseLayout from 'components/layouts/DatabaseLayout/DatabaseLayout'
@@ -7,7 +7,6 @@ import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold'
import { FormHeader } from 'components/ui/Forms/FormHeader'
import { UnknownInterface } from 'components/ui/UnknownInterface'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { useFlag } from 'hooks/ui/useFlag'
import { PipelineRequestStatusProvider } from 'state/replication-pipeline-request-status'
import type { NextPageWithLayout } from 'types'

View File

@@ -6,7 +6,7 @@ import Link from 'next/link'
import { useEffect, useState } from 'react'
import { toast } from 'sonner'
import { useParams } from 'common'
import { useFlag, useParams } from 'common'
import ReportChart from 'components/interfaces/Reports/ReportChart'
import ReportHeader from 'components/interfaces/Reports/ReportHeader'
import ReportPadding from 'components/interfaces/Reports/ReportPadding'
@@ -27,8 +27,8 @@ import { ReportSettings } from 'components/ui/Charts/ReportSettings'
import GrafanaPromoBanner from 'components/ui/GrafanaPromoBanner'
import Panel from 'components/ui/Panel'
import { analyticsKeys } from 'data/analytics/keys'
import { useProjectDiskResizeMutation } from 'data/config/project-disk-resize-mutation'
import { useDiskAttributesQuery } from 'data/config/disk-attributes-query'
import { useProjectDiskResizeMutation } from 'data/config/project-disk-resize-mutation'
import { useDatabaseSizeQuery } from 'data/database/database-size-query'
import { useMaxConnectionsQuery } from 'data/database/max-connections-query'
import { usePgbouncerConfigQuery } from 'data/database/pgbouncer-config-query'
@@ -38,7 +38,6 @@ import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useReportDateRange } from 'hooks/misc/useReportDateRange'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { useFlag } from 'hooks/ui/useFlag'
import { formatBytes } from 'lib/helpers'
import { useDatabaseSelectorStateSnapshot } from 'state/database-selector'
import type { NextPageWithLayout } from 'types'

View File

@@ -1,6 +1,6 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import JWTSecretKeysTable from 'components/interfaces/JwtSecrets/jwt-secret-keys-table'
import { JWTSecretKeysTable } from 'components/interfaces/JwtSecrets/jwt-secret-keys-table'
import DefaultLayout from 'components/layouts/DefaultLayout'
import JWTKeysLayout from 'components/layouts/JWTKeys/JWTKeysLayout'
import SettingsLayout from 'components/layouts/ProjectSettingsLayout/SettingsLayout'

View File

@@ -1,5 +1,5 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import * as configcat from 'configcat-js'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { getFlags } from './configcat'
vi.mock('data/fetchers', () => ({
@@ -34,7 +34,7 @@ describe('configcat', () => {
const mockValues = { flag1: true, flag2: false }
mockClient.getAllValuesAsync.mockResolvedValue(mockValues)
const { fetchHandler } = await import('data/fetchers')
const { fetchHandler } = await import('./configcat')
const mockFetchHandler = fetchHandler as unknown as ReturnType<typeof vi.fn>
mockFetchHandler.mockResolvedValueOnce(
new Response(JSON.stringify({}), {

View File

@@ -1,10 +1,20 @@
import * as configcat from 'configcat-js'
import { fetchHandler } from 'data/fetchers'
let client: configcat.IConfigCatClient
const endpoint = '/configuration-files/configcat-proxy/frontend-v2/config_v6.json'
export const fetchHandler: typeof fetch = async (input, init) => {
try {
return await fetch(input, init)
} catch (err: any) {
if (err instanceof TypeError && err.message === 'Failed to fetch') {
console.error(err)
throw new Error('Unable to reach the server. Please check your network or try again later.')
}
throw err
}
}
async function getClient() {
if (client) {
return client

View File

@@ -141,3 +141,19 @@ export const FeatureFlagProvider = ({
export const useFeatureFlags = () => {
return useContext(FeatureFlagContext)
}
const isObjectEmpty = (obj: Object) => {
return Object.keys(obj).length === 0
}
export function useFlag<T = boolean>(name: string) {
const flagStore = useFeatureFlags()
const store = flagStore.configcat
if (!isObjectEmpty(store) && store[name] === undefined) {
console.error(`Flag key "${name}" does not exist in ConfigCat flag store`)
return false
}
return store[name] as T
}

View File

@@ -1,4 +1,5 @@
export * from './auth'
export * from './configcat'
export * from './consent-state'
export * from './constants'
export * from './database-types'

View File

@@ -15,6 +15,7 @@
"@usercentrics/cmp-browser-sdk": "^4.42.0",
"api-types": "workspace:*",
"config": "workspace:*",
"configcat-js": "^9.5.1",
"dat.gui": "^0.7.9",
"flags": "^4.0.0",
"lodash": "^4.17.21",
@@ -27,8 +28,11 @@
"@types/lodash": "4.17.5",
"@types/react": "catalog:",
"@types/react-dom": "catalog:",
"@vitest/coverage-v8": "^3.0.9",
"@vitest/ui": "^3.0.0",
"tsconfig": "workspace:*",
"typescript": "~5.5.0"
"typescript": "~5.5.0",
"vitest": "^3.0.5"
},
"peerDependencies": {
"@supabase/auth-js": "catalog:",

1335
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff