NavigationBar.utils.tsx228 lines · main
1import { Auth, Database, EdgeFunctions, Realtime, SqlEditor, Storage, TableEditor } from 'icons'
2import { Blocks, Lightbulb, List, Settings, Telescope } from 'lucide-react'
3
4import { ICON_SIZE, ICON_STROKE_WIDTH } from '@/components/interfaces/Sidebar'
5import type { Route } from '@/components/ui/ui.types'
6import { EditorIndexPageLink } from '@/data/prefetchers/project.$ref.editor'
7import type { Project } from '@/data/projects/project-detail-query'
8import { IS_PLATFORM, PROJECT_STATUS } from '@/lib/constants'
9import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
10
11interface RouteContext {
12 ref?: string
13 isProjectActive: boolean
14 isProjectBuilding: boolean
15 buildingUrl: string
16}
17
18interface ProductFeatures {
19 auth?: boolean
20 edgeFunctions?: boolean
21 storage?: boolean
22 realtime?: boolean
23 authOverviewPage?: boolean
24}
25
26interface OtherFeatures {
27 isPlatform?: boolean
28 unifiedLogs?: boolean
29 showReports?: boolean
30 showLogs?: boolean
31}
32
33interface SettingsFeatures {
34 isPlatform?: boolean
35}
36
37function getRouteContext(ref?: string, project?: Project): RouteContext {
38 return {
39 ref,
40 isProjectActive: project?.status === PROJECT_STATUS.ACTIVE_HEALTHY,
41 isProjectBuilding: project?.status === PROJECT_STATUS.COMING_UP,
42 buildingUrl: `/project/${ref}`,
43 }
44}
45
46export const generateToolRoutes = (ref?: string, project?: Project): Route[] => {
47 const { isProjectActive, isProjectBuilding, buildingUrl } = getRouteContext(ref, project)
48
49 return [
50 {
51 key: 'editor',
52 label: 'Table Editor',
53 disabled: !isProjectActive,
54 icon: <TableEditor size={ICON_SIZE} strokeWidth={ICON_STROKE_WIDTH} />,
55 link: ref && (isProjectBuilding ? buildingUrl : `/project/${ref}/editor`),
56 linkElement: <EditorIndexPageLink projectRef={ref} />,
57 shortcutId: SHORTCUT_IDS.NAV_TABLE_EDITOR,
58 },
59 {
60 key: 'sql',
61 label: 'SQL Editor',
62 disabled: !isProjectActive,
63 icon: <SqlEditor size={ICON_SIZE} strokeWidth={ICON_STROKE_WIDTH} />,
64 link: ref && (isProjectBuilding ? buildingUrl : `/project/${ref}/sql`),
65 shortcutId: SHORTCUT_IDS.NAV_SQL_EDITOR,
66 },
67 ]
68}
69
70export const generateProductRoutes = (
71 ref?: string,
72 project?: Project,
73 features?: ProductFeatures
74): Route[] => {
75 const { isProjectActive, isProjectBuilding, buildingUrl } = getRouteContext(ref, project)
76
77 const authEnabled = features?.auth ?? true
78 const edgeFunctionsEnabled = features?.edgeFunctions ?? true
79 const storageEnabled = features?.storage ?? true
80 const realtimeEnabled = features?.realtime ?? true
81 const authOverviewPageEnabled = features?.authOverviewPage ?? false
82
83 return [
84 {
85 key: 'database',
86 label: 'Database',
87 disabled: !isProjectActive,
88 icon: <Database size={ICON_SIZE} strokeWidth={ICON_STROKE_WIDTH} />,
89 link:
90 ref &&
91 (isProjectBuilding
92 ? buildingUrl
93 : isProjectActive
94 ? `/project/${ref}/database/schemas`
95 : `/project/${ref}/database/backups/scheduled`),
96 shortcutId: SHORTCUT_IDS.NAV_DATABASE,
97 },
98 ...(authEnabled
99 ? [
100 {
101 key: 'auth',
102 label: 'Authentication',
103 disabled: !isProjectActive,
104 icon: <Auth size={ICON_SIZE} strokeWidth={ICON_STROKE_WIDTH} />,
105 link:
106 ref &&
107 (isProjectBuilding
108 ? buildingUrl
109 : authOverviewPageEnabled
110 ? `/project/${ref}/auth/overview`
111 : `/project/${ref}/auth/users`),
112 shortcutId: SHORTCUT_IDS.NAV_AUTH,
113 },
114 ]
115 : []),
116 ...(storageEnabled
117 ? [
118 {
119 key: 'storage',
120 label: 'Storage',
121 disabled: !isProjectActive,
122 icon: <Storage size={ICON_SIZE} strokeWidth={ICON_STROKE_WIDTH} />,
123 link: ref && (isProjectBuilding ? buildingUrl : `/project/${ref}/storage/files`),
124 shortcutId: SHORTCUT_IDS.NAV_STORAGE,
125 },
126 ]
127 : []),
128 ...(edgeFunctionsEnabled
129 ? [
130 {
131 key: 'functions',
132 label: 'Edge Functions',
133 disabled: false,
134 icon: <EdgeFunctions size={ICON_SIZE} strokeWidth={ICON_STROKE_WIDTH} />,
135 link: ref && `/project/${ref}/functions`,
136 shortcutId: SHORTCUT_IDS.NAV_FUNCTIONS,
137 },
138 ]
139 : []),
140 ...(realtimeEnabled
141 ? [
142 {
143 key: 'realtime',
144 label: 'Realtime',
145 disabled: !isProjectActive,
146 icon: <Realtime size={ICON_SIZE} strokeWidth={ICON_STROKE_WIDTH} />,
147 link: ref && (isProjectBuilding ? buildingUrl : `/project/${ref}/realtime/inspector`),
148 shortcutId: SHORTCUT_IDS.NAV_REALTIME,
149 },
150 ]
151 : []),
152 ]
153}
154
155export const generateOtherRoutes = (
156 ref?: string,
157 project?: Project,
158 features?: OtherFeatures
159): Route[] => {
160 const { isProjectActive, isProjectBuilding, buildingUrl } = getRouteContext(ref, project)
161
162 const isPlatform = features?.isPlatform ?? IS_PLATFORM
163 const unifiedLogsEnabled = features?.unifiedLogs ?? false
164 const reportsEnabled = features?.showReports ?? true
165 const logsEnabled = features?.showLogs ?? true
166 return [
167 {
168 key: 'advisors',
169 label: 'Advisors',
170 disabled: !isProjectActive,
171 icon: <Lightbulb size={ICON_SIZE} strokeWidth={ICON_STROKE_WIDTH} />,
172 link: ref && (isProjectBuilding ? buildingUrl : `/project/${ref}/advisors/security`),
173 shortcutId: SHORTCUT_IDS.NAV_ADVISORS,
174 },
175 // Observability is only available on the platform, not for self-hosted/CLI
176 ...(isPlatform && reportsEnabled
177 ? [
178 {
179 key: 'observability',
180 label: 'Observability',
181 disabled: !isProjectActive,
182 icon: <Telescope size={ICON_SIZE} strokeWidth={ICON_STROKE_WIDTH} />,
183 link: ref && (isProjectBuilding ? buildingUrl : `/project/${ref}/observability`),
184 shortcutId: SHORTCUT_IDS.NAV_OBSERVABILITY,
185 },
186 ]
187 : []),
188 ...(logsEnabled
189 ? [
190 {
191 key: 'logs',
192 label: 'Logs',
193 disabled: false,
194 icon: <List size={ICON_SIZE} strokeWidth={ICON_STROKE_WIDTH} />,
195 link:
196 ref &&
197 (unifiedLogsEnabled ? `/project/${ref}/logs` : `/project/${ref}/logs/explorer`),
198 shortcutId: SHORTCUT_IDS.NAV_LOGS,
199 },
200 ]
201 : []),
202 {
203 key: 'integrations',
204 label: 'Integrations',
205 disabled: !isProjectActive,
206 icon: <Blocks size={ICON_SIZE} strokeWidth={ICON_STROKE_WIDTH} />,
207 link: ref && (isProjectBuilding ? buildingUrl : `/project/${ref}/integrations`),
208 shortcutId: SHORTCUT_IDS.NAV_INTEGRATIONS,
209 },
210 ]
211}
212
213export const generateSettingsRoutes = (ref?: string, features?: SettingsFeatures): Route[] => {
214 const isPlatform = features?.isPlatform ?? IS_PLATFORM
215
216 return [
217 {
218 key: 'settings',
219 label: 'Project Settings',
220 icon: <Settings size={ICON_SIZE} strokeWidth={ICON_STROKE_WIDTH} />,
221 link:
222 ref &&
223 (isPlatform ? `/project/${ref}/settings/general` : `/project/${ref}/settings/log-drains`),
224 disabled: false,
225 shortcutId: SHORTCUT_IDS.NAV_SETTINGS,
226 },
227 ]
228}