iamfebin commited on
Commit
60290e5
·
1 Parent(s): 5b367e1

Implement dynamic runtime configuration to fetch Supabase secrets from backend

Browse files
Dockerfile CHANGED
@@ -2,16 +2,6 @@
2
  FROM node:20-alpine AS frontend-builder
3
  WORKDIR /app/frontend
4
 
5
- # Declare build arguments (Hugging Face passes secrets as build args)
6
- ARG VITE_SUPABASE_URL
7
- ARG VITE_SUPABASE_ANON_KEY
8
- ARG SUPABASE_URL
9
- ARG SUPABASE_KEY
10
-
11
- # Expose them to Vite compilation environment, with fallback to Streamlit secret names
12
- ENV VITE_SUPABASE_URL=${VITE_SUPABASE_URL:-$SUPABASE_URL}
13
- ENV VITE_SUPABASE_ANON_KEY=${VITE_SUPABASE_ANON_KEY:-$SUPABASE_KEY}
14
-
15
 
16
  # Copy package files and install dependencies
17
  COPY algospaced-ui/package*.json ./
 
2
  FROM node:20-alpine AS frontend-builder
3
  WORKDIR /app/frontend
4
 
 
 
 
 
 
 
 
 
 
 
5
 
6
  # Copy package files and install dependencies
7
  COPY algospaced-ui/package*.json ./
algospaced-ui/src/main.tsx CHANGED
@@ -3,8 +3,27 @@ import { createRoot } from 'react-dom/client'
3
  import './index.css'
4
  import App from './App.tsx'
5
 
6
- createRoot(document.getElementById('root')!).render(
7
- <StrictMode>
8
- <App />
9
- </StrictMode>,
10
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  import './index.css'
4
  import App from './App.tsx'
5
 
6
+ import { initializeSupabase } from './supabaseClient'
7
+
8
+ async function init() {
9
+ try {
10
+ const apiBase = import.meta.env.VITE_API_BASE_URL || '';
11
+ const res = await fetch(`${apiBase}/api/config`);
12
+ if (!res.ok) throw new Error("Failed to load runtime configuration");
13
+ const config = await res.json();
14
+ initializeSupabase(config.supabaseUrl, config.supabaseAnonKey);
15
+ } catch (err) {
16
+ console.error("Failed to load config from API, falling back to build environment:", err);
17
+ const url = import.meta.env.VITE_SUPABASE_URL || '';
18
+ const key = import.meta.env.VITE_SUPABASE_ANON_KEY || '';
19
+ initializeSupabase(url, key);
20
+ }
21
+
22
+ createRoot(document.getElementById('root')!).render(
23
+ <StrictMode>
24
+ <App />
25
+ </StrictMode>,
26
+ )
27
+ }
28
+
29
+ init();
algospaced-ui/src/supabaseClient.ts CHANGED
@@ -1,7 +1,27 @@
1
  import { createClient } from '@supabase/supabase-js';
2
 
3
- const supabaseUrl = import.meta.env.VITE_SUPABASE_URL || '';
4
- const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY || '';
5
 
6
- export const supabase = createClient(supabaseUrl, supabaseAnonKey);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
 
1
  import { createClient } from '@supabase/supabase-js';
2
 
3
+ let supabaseInstance: any = null;
 
4
 
5
+ export function initializeSupabase(url: string, key: string) {
6
+ if (url && key) {
7
+ supabaseInstance = createClient(url, key);
8
+ }
9
+ }
10
+
11
+ // Proxy wrapper that delegates all calls to the dynamically initialized instance
12
+ export const supabase = new Proxy({} as any, {
13
+ get(target, prop) {
14
+ if (!supabaseInstance) {
15
+ // Fallback: try loading from build-time environment if not initialized yet
16
+ const url = import.meta.env.VITE_SUPABASE_URL || '';
17
+ const key = import.meta.env.VITE_SUPABASE_ANON_KEY || '';
18
+ if (url && key) {
19
+ supabaseInstance = createClient(url, key);
20
+ } else {
21
+ throw new Error("Supabase client is not initialized. Please call initializeSupabase(url, key) first.");
22
+ }
23
+ }
24
+ return supabaseInstance[prop];
25
+ }
26
+ });
27
 
main.py CHANGED
@@ -119,6 +119,13 @@ def get_supabase_client(authorization: str = Header(None)) -> Client:
119
  except Exception as e:
120
  raise HTTPException(status_code=401, detail=f"Authentication failed: {str(e)}")
121
 
 
 
 
 
 
 
 
122
  @app.get("/api/streak")
123
  def get_streak(client: Client = Depends(get_supabase_client)):
124
  streak_data = db.get_active_streak(client)
 
119
  except Exception as e:
120
  raise HTTPException(status_code=401, detail=f"Authentication failed: {str(e)}")
121
 
122
+ @app.get("/api/config")
123
+ def get_public_config():
124
+ return {
125
+ "supabaseUrl": SUPABASE_URL,
126
+ "supabaseAnonKey": SUPABASE_KEY
127
+ }
128
+
129
  @app.get("/api/streak")
130
  def get_streak(client: Client = Depends(get_supabase_client)):
131
  streak_data = db.get_active_streak(client)