@@ -23,6 +23,8 @@ import {
2323 UpdateMenuBodySchema ,
2424 CreateLabelBodySchema ,
2525 UpdateLabelBodySchema ,
26+ ModulesConfigSchema ,
27+ normalizeModulesConfig ,
2628} from '@menu/schemas' ;
2729import type { AppBindings } from '../types' ;
2830import type { DbInstance } from '../db' ;
@@ -86,6 +88,54 @@ admin.get('/settings', ...base, async (c) => {
8688 } ) ;
8789} ) ;
8890
91+ // ── Modules ──────────────────────────────────────────────────────────
92+
93+ admin . get ( '/modules' , ...base , async ( c ) => {
94+ const [ row ] = await c . get ( 'db' )
95+ . select ( {
96+ modules : schema . settings . modules ,
97+ selectionEnabled : schema . settings . selectionEnabled ,
98+ aiChatEnabled : schema . settings . aiChatEnabled ,
99+ aiVoiceEnabled : schema . settings . aiVoiceEnabled ,
100+ } )
101+ . from ( schema . settings )
102+ . where ( eq ( schema . settings . id , 1 ) ) ;
103+
104+ if ( ! row ) return c . json ( { error : 'Not found' } , 404 ) ;
105+ return c . json ( { modules : normalizeModulesConfig ( row . modules , row ) } ) ;
106+ } ) ;
107+
108+ admin . put ( '/modules' , ...base , async ( c ) => {
109+ const body = await parseBody ( c , ModulesConfigSchema ) ;
110+ if ( body instanceof Response ) return body ;
111+
112+ const [ row ] = await c . get ( 'db' )
113+ . select ( {
114+ modules : schema . settings . modules ,
115+ selectionEnabled : schema . settings . selectionEnabled ,
116+ aiChatEnabled : schema . settings . aiChatEnabled ,
117+ aiVoiceEnabled : schema . settings . aiVoiceEnabled ,
118+ } )
119+ . from ( schema . settings )
120+ . where ( eq ( schema . settings . id , 1 ) ) ;
121+ if ( ! row ) return c . json ( { error : 'Not found' } , 404 ) ;
122+
123+ const modules = normalizeModulesConfig ( { ...normalizeModulesConfig ( row . modules , row ) , ...body } ) ;
124+ await c . get ( 'db' )
125+ . update ( schema . settings )
126+ . set ( {
127+ modules,
128+ selectionEnabled : modules . ordering . enabled ,
129+ aiChatEnabled : modules . ai . enabled ,
130+ aiVoiceEnabled : modules . ai . enabled && modules . ai . voiceEnabled ,
131+ updatedAt : Date . now ( ) ,
132+ } )
133+ . where ( eq ( schema . settings . id , 1 ) ) ;
134+
135+ await refreshPublicCatalog ( c ) ;
136+ return c . json ( { ok : true , modules } ) ;
137+ } ) ;
138+
89139admin . put ( '/settings' , ...base , async ( c ) => {
90140 const body = await parseBody ( c , UpdateSettingsBodySchema ) ;
91141 if ( body instanceof Response ) return body ;
@@ -101,6 +151,20 @@ admin.put('/settings', ...base, async (c) => {
101151 if ( body . aiChatEnabled !== undefined ) updates . aiChatEnabled = body . aiChatEnabled ;
102152 if ( body . aiVoiceEnabled !== undefined ) updates . aiVoiceEnabled = body . aiChatEnabled === false ? false : body . aiVoiceEnabled ;
103153 if ( body . selectionEnabled !== undefined ) updates . selectionEnabled = body . selectionEnabled ;
154+ if ( body . aiChatEnabled !== undefined || body . aiVoiceEnabled !== undefined || body . selectionEnabled !== undefined ) {
155+ const [ row ] = await c . get ( 'db' )
156+ . select ( { modules : schema . settings . modules , selectionEnabled : schema . settings . selectionEnabled , aiChatEnabled : schema . settings . aiChatEnabled , aiVoiceEnabled : schema . settings . aiVoiceEnabled } )
157+ . from ( schema . settings )
158+ . where ( eq ( schema . settings . id , 1 ) ) ;
159+ const modules = normalizeModulesConfig ( row ?. modules , row ) ;
160+ if ( body . selectionEnabled !== undefined ) modules . ordering . enabled = body . selectionEnabled ;
161+ if ( body . aiChatEnabled !== undefined ) {
162+ modules . ai . enabled = body . aiChatEnabled ;
163+ if ( ! body . aiChatEnabled ) modules . ai . voiceEnabled = false ;
164+ }
165+ if ( body . aiVoiceEnabled !== undefined ) modules . ai . voiceEnabled = modules . ai . enabled && body . aiVoiceEnabled ;
166+ updates . modules = modules ;
167+ }
104168 if ( body . primaryLocale !== undefined ) updates . primaryLocale = body . primaryLocale ;
105169 if ( body . enabledLocales !== undefined ) updates . enabledLocales = body . enabledLocales ;
106170 if ( body . disabledLocales !== undefined ) updates . disabledLocales = body . disabledLocales ;
@@ -753,6 +817,15 @@ admin.delete('/locale-flag/:code', ...base, async (c) => {
753817
754818admin . get ( '/analytics' , ...base , async ( c ) => {
755819 const db = c . get ( 'db' ) ;
820+ const [ settingsRow ] = await db
821+ . select ( { modules : schema . settings . modules } )
822+ . from ( schema . settings )
823+ . where ( eq ( schema . settings . id , 1 ) )
824+ . limit ( 1 ) ;
825+ if ( ! normalizeModulesConfig ( settingsRow ?. modules ) . analytics . enabled ) {
826+ return c . json ( { error : 'Not Found' } , 404 ) ;
827+ }
828+
756829
757830 const periodParam = c . req . query ( 'period' ) ?? '7d' ;
758831 const ms = periodToMs ( periodParam ) ;
0 commit comments