| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- 'use client'
- import { IS_PLATFORM } from 'common'
- import { Auth, EdgeFunctions, Storage } from 'icons'
- import { Database } from 'lucide-react'
- import { useMemo } from 'react'
- import type { ICommand } from 'ui-patterns/CommandMenu'
- import {
- CommandHeader,
- CommandMenuInput,
- CommandWrapper,
- PageType,
- useQuery,
- useRegisterCommands,
- useRegisterPage,
- useSetPage,
- } from 'ui-patterns/CommandMenu'
- import { COMMAND_MENU_SECTIONS } from './CommandMenu.utils'
- import { ContextSearchResults } from './ContextSearchResults'
- import { orderCommandSectionsByPriority } from './ordering'
- import type { SearchContextValue } from './SearchContext.types'
- import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
- import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
- interface SearchContextOption {
- value: SearchContextValue
- label: string
- pageName: string
- placeholder: string
- icon: React.ComponentType<React.SVGProps<SVGSVGElement>>
- }
- const SEARCH_CONTEXT_OPTIONS: SearchContextOption[] = [
- {
- value: 'database-tables',
- label: 'Database Tables',
- pageName: 'Search Database Tables',
- placeholder: 'Search database tables...',
- icon: Database,
- },
- {
- value: 'auth-policies',
- label: 'RLS Policies',
- pageName: 'Search RLS Policies',
- placeholder: 'Search rls policies...',
- icon: Auth,
- },
- {
- value: 'edge-functions',
- label: 'Edge Functions',
- pageName: 'Search Edge Functions',
- placeholder: 'Search edge functions...',
- icon: EdgeFunctions,
- },
- {
- value: 'storage',
- label: 'Storage',
- pageName: 'Search Storage',
- placeholder: 'Search buckets...',
- icon: Storage,
- },
- ]
- function ContextSearchPage({
- context,
- placeholder,
- }: {
- context: SearchContextValue
- placeholder: string
- }) {
- const query = useQuery()
- return (
- <CommandWrapper>
- <CommandHeader>
- <CommandMenuInput placeholder={placeholder} />
- </CommandHeader>
- <ContextSearchResults context={context} query={query} />
- </CommandWrapper>
- )
- }
- export function useContextSearchCommands() {
- const { data: project } = useSelectedProjectQuery()
- const setPage = useSetPage()
- const {
- projectAuthAll: authEnabled,
- projectEdgeFunctionAll: edgeFunctionsEnabled,
- projectStorageAll: storageEnabled,
- } = useIsFeatureEnabled(['project_auth:all', 'project_edge_function:all', 'project_storage:all'])
- const pageDefinitions = [
- { title: 'Search Database Tables', context: 'database-tables' as const },
- { title: 'Search RLS Policies', context: 'auth-policies' as const },
- { title: 'Search Edge Functions', context: 'edge-functions' as const },
- { title: 'Search Storage', context: 'storage' as const },
- ]
- // Register pages - pageDefinitions is constant, so hooks are called in consistent order
- for (const { title, context } of pageDefinitions) {
- const placeholder =
- SEARCH_CONTEXT_OPTIONS.find((opt) => opt.value === context)?.placeholder ?? ''
- // eslint-disable-next-line react-hooks/rules-of-hooks
- useRegisterPage(title, {
- type: PageType.Component,
- component: () => <ContextSearchPage context={context} placeholder={placeholder} />,
- })
- }
- const contextCommands = useMemo(() => {
- return SEARCH_CONTEXT_OPTIONS.filter((option) => {
- let isFeatureEnabled = false
- switch (option.value) {
- case 'database-tables':
- isFeatureEnabled = true
- break
- case 'auth-policies':
- isFeatureEnabled = authEnabled
- break
- case 'edge-functions':
- isFeatureEnabled = edgeFunctionsEnabled
- break
- case 'storage':
- isFeatureEnabled = storageEnabled
- break
- }
- if (!isFeatureEnabled) return false
- // If self-hosted, show if feature is enabled
- if (!IS_PLATFORM) {
- return true
- }
- // only show when inside a project if not self-hosted
- return !!project
- }).map((option) => ({
- id: `search-${option.value}`,
- name: `Search ${option.label}...`,
- action: () => setPage(option.pageName),
- icon: () => <option.icon className="h-4 w-4" strokeWidth={1.5} />,
- })) as ICommand[]
- }, [setPage, authEnabled, edgeFunctionsEnabled, storageEnabled, project])
- useRegisterCommands(COMMAND_MENU_SECTIONS.QUERY, contextCommands, {
- orderSection: orderCommandSectionsByPriority,
- sectionMeta: { priority: 3 },
- enabled: !IS_PLATFORM || !!project,
- })
- }
|