import * as plugins from '../plugins.js'; import * as interfaces from '../../ts_interfaces/index.js'; import { appState } from './shared.js'; import { getActionContext } from './login.js'; // ============================================================================ // ACME Config State (DB-backed singleton, managed via Domains > Certificates) // ============================================================================ export interface IAcmeConfigState { config: interfaces.data.IAcmeConfig | null; isLoading: boolean; error: string | null; lastUpdated: number; } export const acmeConfigStatePart = await appState.getStatePart( 'acmeConfig', { config: null, isLoading: false, error: null, lastUpdated: 0, }, 'soft', ); // ACME Config Actions // ============================================================================ export const fetchAcmeConfigAction = acmeConfigStatePart.createAction( async (statePartArg): Promise => { const context = getActionContext(); const currentState = statePartArg.getState()!; if (!context.identity) return currentState; try { const request = new plugins.domtools.plugins.typedrequest.TypedRequest< interfaces.requests.IReq_GetAcmeConfig >('/typedrequest', 'getAcmeConfig'); const response = await request.fire({ identity: context.identity }); return { config: response.config, isLoading: false, error: null, lastUpdated: Date.now(), }; } catch (error: unknown) { return { ...currentState, isLoading: false, error: error instanceof Error ? error.message : 'Failed to fetch ACME config', }; } }, ); export const updateAcmeConfigAction = acmeConfigStatePart.createAction<{ accountEmail?: string; enabled?: boolean; useProduction?: boolean; autoRenew?: boolean; renewThresholdDays?: number; }>(async (statePartArg, dataArg, actionContext): Promise => { const context = getActionContext(); try { const request = new plugins.domtools.plugins.typedrequest.TypedRequest< interfaces.requests.IReq_UpdateAcmeConfig >('/typedrequest', 'updateAcmeConfig'); const response = await request.fire({ identity: context.identity!, accountEmail: dataArg.accountEmail, enabled: dataArg.enabled, useProduction: dataArg.useProduction, autoRenew: dataArg.autoRenew, renewThresholdDays: dataArg.renewThresholdDays, }); if (!response.success) { return { ...statePartArg.getState()!, error: response.message || 'Failed to update ACME config', }; } return await actionContext!.dispatch(fetchAcmeConfigAction, null); } catch (error: unknown) { return { ...statePartArg.getState()!, error: error instanceof Error ? error.message : 'Failed to update ACME config', }; } }); // ============================================================================