@@ -3,9 +3,12 @@ import { type ClassValue, clsx } from 'clsx';
33import { Room } from 'livekit-client' ;
44import { twMerge } from 'tailwind-merge' ;
55import type { ReceivedChatMessage , TextStreamData } from '@livekit/components-react' ;
6- import { APP_CONFIG } from '@/app-config' ;
6+ import { APP_CONFIG_DEFAULTS } from '@/app-config' ;
77import type { AppConfig , SandboxConfig } from './types' ;
88
9+ export const CONFIG_ENDPOINT = process . env . NEXT_PUBLIC_APP_CONFIG_ENDPOINT ;
10+ export const SANDBOX_ID = process . env . SANDBOX_ID ;
11+
912export const THEME_STORAGE_KEY = 'theme-mode' ;
1013export const THEME_MEDIA_QUERY = '(prefers-color-scheme: dark)' ;
1114
@@ -30,25 +33,44 @@ export function transcriptionToChatMessage(
3033 } ;
3134}
3235
36+ export function getOrigin ( headers : Headers ) : string {
37+ const host = headers . get ( 'host' ) ;
38+ const proto = headers . get ( 'x-forwarded-proto' ) || 'https' ;
39+ return `${ proto } ://${ host } ` ;
40+ }
41+
3342// https://react.dev/reference/react/cache#caveats
3443// > React will invalidate the cache for all memoized functions for each server request.
35- export const getAppConfig = cache ( async ( ) : Promise < AppConfig > => {
36- if ( process . env . NEXT_PUBLIC_APP_CONFIG_ENDPOINT ) {
44+ export const getAppConfig = cache ( async ( origin : string ) : Promise < AppConfig > => {
45+ if ( CONFIG_ENDPOINT ) {
46+ const sandboxId = SANDBOX_ID ?? origin . split ( '.' ) [ 0 ] ;
47+
3748 try {
38- const url = new URL ( process . env . NEXT_PUBLIC_APP_CONFIG_ENDPOINT , window . location . origin ) ;
39- const response = await fetch ( url . toString ( ) , {
49+ const response = await fetch ( CONFIG_ENDPOINT , {
4050 cache : 'no-store' ,
51+ headers : { 'X-Sandbox-ID' : sandboxId } ,
4152 } ) ;
42- const sandboxConfig : SandboxConfig = await response . json ( ) ;
4353
44- return {
45- ...APP_CONFIG ,
46- ...sandboxConfig ,
47- } ;
54+ const remoteConfig : SandboxConfig = await response . json ( ) ;
55+ const config : AppConfig = { ...APP_CONFIG_DEFAULTS } ;
56+
57+ for ( const [ key , entry ] of Object . entries ( remoteConfig ) ) {
58+ if ( entry === null ) continue ;
59+ if (
60+ key in config &&
61+ typeof config [ key as keyof AppConfig ] === entry . type &&
62+ typeof config [ key as keyof AppConfig ] === typeof entry . value
63+ ) {
64+ // @ts -expect-error I'm not sure quite how to appease TypeScript, but we've thoroughly checked types above
65+ config [ key as keyof AppConfig ] = entry . value as AppConfig [ keyof AppConfig ] ;
66+ }
67+ }
68+
69+ return config ;
4870 } catch ( error ) {
4971 console . error ( '!!!' , error ) ;
5072 }
5173 }
5274
53- return APP_CONFIG ;
75+ return APP_CONFIG_DEFAULTS ;
5476} ) ;
0 commit comments