SecondLevelNav.tsx119 lines · main
1import { useParams } from 'common'
2import { type ReactNode } from 'react'
3
4import { API_DOCS_CATEGORIES } from './ProjectAPIDocs.constants'
5import { SecondLevelNavLayout, type MenuItemFilter } from './SecondLevelNav.Layout'
6import { ResourcePickerList } from './SecondLevelNav.ResourcePicker'
7import { StorageResourceList } from './SecondLevelNav.StoragePicker'
8import { useEdgeFunctionsQuery } from '@/data/edge-functions/edge-functions-query'
9import { useOpenAPISpecQuery } from '@/data/open-api/api-spec-query'
10import { useBucketInfoQueryPreferCached } from '@/data/storage/buckets-query'
11import { DOCS_URL } from '@/lib/constants'
12import { useAppStateSnapshot } from '@/state/app-state'
13
14const OPEN_API_SPEC_STALE_TIME = 1000 * 60 * 10
15
16const EntitiesSecondLevelNav = () => {
17 const { ref } = useParams()
18
19 const { data } = useOpenAPISpecQuery({ projectRef: ref }, { staleTime: OPEN_API_SPEC_STALE_TIME })
20 const tables = data?.tables ?? []
21
22 return (
23 <SecondLevelNavLayout
24 category={API_DOCS_CATEGORIES.ENTITIES}
25 title="Tables & Views"
26 docsUrl={`${DOCS_URL}/reference/javascript/select`}
27 renderResourceList={(props) => (
28 <ResourcePickerList {...props} items={tables} emptyMessage="No tables available" />
29 )}
30 />
31 )
32}
33
34const StoredProceduresSecondLevelNav = () => {
35 const { ref } = useParams()
36
37 const { data } = useOpenAPISpecQuery({ projectRef: ref }, { staleTime: OPEN_API_SPEC_STALE_TIME })
38 const functions = data?.functions ?? []
39
40 return (
41 <SecondLevelNavLayout
42 category={API_DOCS_CATEGORIES.STORED_PROCEDURES}
43 title="Database Functions"
44 docsUrl={`${DOCS_URL}/reference/javascript/rpc`}
45 renderResourceList={(props) => (
46 <ResourcePickerList
47 {...props}
48 items={functions}
49 emptyMessage="No database functions available"
50 />
51 )}
52 />
53 )
54}
55
56const EdgeFunctionsSecondLevelNav = () => {
57 const { ref } = useParams()
58
59 const { data: edgeFunctions } = useEdgeFunctionsQuery({ projectRef: ref })
60
61 return (
62 <SecondLevelNavLayout
63 category={API_DOCS_CATEGORIES.EDGE_FUNCTIONS}
64 title="Edge Functions"
65 docsUrl={`${DOCS_URL}/reference/javascript/functions-invoke`}
66 renderResourceList={(props) => (
67 <ResourcePickerList
68 {...props}
69 items={edgeFunctions ?? []}
70 emptyMessage="No edge functions available"
71 />
72 )}
73 />
74 )
75}
76
77const StorageSecondLevelNav = () => {
78 const { ref } = useParams()
79
80 const snap = useAppStateSnapshot()
81 const [, resource] = snap.activeDocsSection
82
83 const selectedBucket = useBucketInfoQueryPreferCached(resource, ref)
84
85 const menuItemFilter: MenuItemFilter | undefined = selectedBucket
86 ? (item) => {
87 if (!selectedBucket.public && item.key === 'retrieve-public-url') return false
88 if (selectedBucket.public && item.key === 'create-signed-url') return false
89 return true
90 }
91 : undefined
92
93 return (
94 <SecondLevelNavLayout
95 category={API_DOCS_CATEGORIES.STORAGE}
96 title="Storage"
97 docsUrl={`${DOCS_URL}/reference/javascript/storage-createbucket`}
98 menuItemFilter={menuItemFilter}
99 renderResourceList={(props) => <StorageResourceList {...props} projectRef={ref} />}
100 />
101 )
102}
103
104const SECTION_COMPONENTS: Record<string, () => ReactNode> = {
105 [API_DOCS_CATEGORIES.ENTITIES]: EntitiesSecondLevelNav,
106 [API_DOCS_CATEGORIES.STORED_PROCEDURES]: StoredProceduresSecondLevelNav,
107 [API_DOCS_CATEGORIES.STORAGE]: StorageSecondLevelNav,
108 [API_DOCS_CATEGORIES.EDGE_FUNCTIONS]: EdgeFunctionsSecondLevelNav,
109}
110
111export const SecondLevelNav = () => {
112 const snap = useAppStateSnapshot()
113 const [section] = snap.activeDocsSection
114
115 const SectionComponent = SECTION_COMPONENTS[section]
116 if (!SectionComponent) return null
117
118 return <SectionComponent key={section} />
119}