Skip to content

Commit 7ed4436

Browse files
committed
fix middleware auth
1 parent f965da5 commit 7ed4436

File tree

3 files changed

+74
-87
lines changed

3 files changed

+74
-87
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use client';
2+
3+
import { ReactNode } from 'react';
4+
import { useTinybirdToken } from '@/providers/TinybirdProvider';
5+
import { useModal } from '../context/ModalContext';
6+
import { useKeyboardShortcut } from '@/hooks/useKeyboardShortcut';
7+
import CostPredictionModal from './CostPredictionModal';
8+
9+
interface RootLayoutContentProps {
10+
children: ReactNode;
11+
initialToken: string;
12+
initialOrgName: string;
13+
}
14+
15+
export function RootLayoutContent({ children, initialToken, initialOrgName }: RootLayoutContentProps) {
16+
const { setToken, setOrgName } = useTinybirdToken();
17+
18+
// Set the initial values from the server
19+
setToken(initialToken);
20+
setOrgName(initialOrgName);
21+
22+
return (
23+
<>
24+
{children}
25+
<ModalController filters={{}} />
26+
</>
27+
);
28+
}
29+
30+
function ModalController({ filters }: { filters: Record<string, string> }) {
31+
const { isCostPredictionOpen, openCostPrediction, closeCostPrediction } = useModal();
32+
33+
useKeyboardShortcut('k', () => {
34+
if (!isCostPredictionOpen) {
35+
openCostPrediction();
36+
}
37+
}, true);
38+
39+
return (
40+
<CostPredictionModal
41+
isOpen={isCostPredictionOpen}
42+
onClose={closeCostPrediction}
43+
currentFilters={filters}
44+
/>
45+
);
46+
}
Lines changed: 14 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,31 @@
1-
'use client'
2-
import { useEffect, useState } from 'react'
3-
import { Inter } from "next/font/google"
4-
import "./globals.css"
5-
import { TinybirdProvider } from '@/providers/TinybirdProvider'
6-
import { ClerkProvider } from '@clerk/nextjs'
7-
import { useTinybirdToken } from '@/providers/TinybirdProvider'
8-
import { ModalProvider } from './context/ModalContext'
9-
import CostPredictionModal from './components/CostPredictionModal'
10-
import { useModal } from './context/ModalContext'
11-
import { useKeyboardShortcut } from '@/hooks/useKeyboardShortcut'
1+
import { headers } from 'next/headers';
2+
import { Inter } from "next/font/google";
3+
import "./globals.css";
4+
import { TinybirdProvider } from '@/providers/TinybirdProvider';
5+
import { ClerkProvider } from '@clerk/nextjs';
6+
import { ModalProvider } from './context/ModalContext';
7+
import { RootLayoutContent } from './components/RootLayoutContent';
128

13-
const inter = Inter({ subsets: ["latin"] })
9+
const inter = Inter({ subsets: ["latin"] });
1410

15-
function RootLayoutContent({ children }: { children: React.ReactNode }) {
16-
const { setToken, setOrgName } = useTinybirdToken()
17-
const [isReady, setIsReady] = useState(false)
11+
export default async function RootLayout({ children }: { children: React.ReactNode }) {
12+
const headersList = await headers();
13+
const token = headersList.get('x-tinybird-token') || '';
14+
const orgName = headersList.get('x-org-name') || '';
1815

19-
useEffect(() => {
20-
let isMounted = true
21-
22-
const fetchToken = async () => {
23-
try {
24-
const response = await fetch(window.location.pathname)
25-
if (!isMounted) return
26-
27-
const token = response.headers.get('x-tinybird-token')
28-
const orgName = response.headers.get('x-org-name')
29-
30-
if (token) {
31-
setToken(token)
32-
setOrgName(orgName || '')
33-
}
34-
35-
setIsReady(true)
36-
} catch (error) {
37-
console.error('Error fetching token:', error)
38-
if (isMounted) setIsReady(true)
39-
}
40-
}
41-
42-
fetchToken()
43-
44-
return () => {
45-
isMounted = false
46-
}
47-
}, []) // Empty dependency array to run only once
48-
49-
if (!isReady) return <div>Loading...</div>
50-
51-
return (
52-
<>
53-
{children}
54-
</>
55-
)
56-
}
57-
58-
function ModalController({ filters }: { filters: Record<string, string> }) {
59-
const { isCostPredictionOpen, openCostPrediction, closeCostPrediction } = useModal()
60-
61-
// Use 'k' with modifier key (Cmd/Ctrl)
62-
useKeyboardShortcut('k', () => {
63-
if (!isCostPredictionOpen) {
64-
openCostPrediction();
65-
}
66-
}, true)
67-
68-
return (
69-
<CostPredictionModal
70-
isOpen={isCostPredictionOpen}
71-
onClose={closeCostPrediction}
72-
currentFilters={filters}
73-
/>
74-
)
75-
}
76-
77-
export default function RootLayout({ children }: { children: React.ReactNode }) {
7816
return (
7917
<html lang="en" className="dark">
8018
<body className={inter.className}>
8119
<ClerkProvider>
8220
<TinybirdProvider>
8321
<ModalProvider>
84-
<RootLayoutContent>
22+
<RootLayoutContent initialToken={token} initialOrgName={orgName}>
8523
{children}
86-
<ModalController filters={{}} />
8724
</RootLayoutContent>
8825
</ModalProvider>
8926
</TinybirdProvider>
9027
</ClerkProvider>
9128
</body>
9229
</html>
93-
)
30+
);
9431
}

dashboard/ai-analytics/src/providers/TinybirdProvider.tsx

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ interface TinybirdContextType {
1111
}
1212

1313
const TinybirdContext = createContext<TinybirdContextType | null>(null);
14-
1514
const queryClient = new QueryClient();
1615

17-
export function TinybirdProvider({ children }: { children: ReactNode }) {
16+
export function TinybirdProvider({
17+
children,
18+
}: {
19+
children: ReactNode;
20+
}) {
1821
const [token, setTokenState] = useState<string | null>(null);
1922
const [orgName, setOrgNameState] = useState<string | null>(null);
2023

21-
// Memoize these functions so they don't change on every render
2224
const setToken = useCallback((newToken: string) => {
2325
setTokenState(newToken);
2426
}, []);
@@ -27,10 +29,12 @@ export function TinybirdProvider({ children }: { children: ReactNode }) {
2729
setOrgNameState(newOrgName);
2830
}, []);
2931

30-
// Create a stable context value
31-
const contextValue = useMemo(() => {
32-
return { token, orgName, setToken, setOrgName };
33-
}, [token, orgName, setToken, setOrgName]);
32+
const contextValue = useMemo(() => ({
33+
token,
34+
orgName,
35+
setToken,
36+
setOrgName
37+
}), [token, orgName, setToken, setOrgName]);
3438

3539
return (
3640
<TinybirdContext.Provider value={contextValue}>
@@ -39,12 +43,12 @@ export function TinybirdProvider({ children }: { children: ReactNode }) {
3943
</QueryClientProvider>
4044
</TinybirdContext.Provider>
4145
);
42-
}
46+
}
4347

4448
export function useTinybirdToken() {
4549
const context = useContext(TinybirdContext);
4650
if (!context) {
47-
throw new Error('useTinybirdToken must be used within TinybirdProvider');
51+
throw new Error('useTinybirdToken must be used within a TinybirdProvider');
4852
}
4953
return context;
50-
}
54+
}

0 commit comments

Comments
 (0)