920 lines
32 KiB
TypeScript
920 lines
32 KiB
TypeScript
import * as plugins from './plugins.js';
|
|
import * as interfaces from '../ts_interfaces/index.js';
|
|
|
|
// ============================================================================
|
|
// Smartstate instance
|
|
// ============================================================================
|
|
export const appState = new plugins.domtools.plugins.smartstate.Smartstate();
|
|
|
|
// ============================================================================
|
|
// State Part Interfaces
|
|
// ============================================================================
|
|
|
|
export interface ILoginState {
|
|
identity: interfaces.data.IIdentity | null;
|
|
isLoggedIn: boolean;
|
|
}
|
|
|
|
export interface ISystemState {
|
|
status: interfaces.data.ISystemStatus | null;
|
|
}
|
|
|
|
export interface IServicesState {
|
|
services: interfaces.data.IService[];
|
|
currentService: interfaces.data.IService | null;
|
|
currentServiceLogs: interfaces.data.ILogEntry[];
|
|
currentServiceStats: interfaces.data.IContainerStats | null;
|
|
platformServices: interfaces.data.IPlatformService[];
|
|
currentPlatformService: interfaces.data.IPlatformService | null;
|
|
}
|
|
|
|
export interface INetworkState {
|
|
targets: interfaces.data.INetworkTarget[];
|
|
stats: interfaces.data.INetworkStats | null;
|
|
trafficStats: interfaces.data.ITrafficStats | null;
|
|
dnsRecords: interfaces.data.IDnsRecord[];
|
|
domains: interfaces.data.IDomainDetail[];
|
|
certificates: interfaces.data.ICertificate[];
|
|
}
|
|
|
|
export interface IRegistriesState {
|
|
tokens: interfaces.data.IRegistryToken[];
|
|
registryStatus: { running: boolean; port: number } | null;
|
|
}
|
|
|
|
export interface IBackupsState {
|
|
backups: interfaces.data.IBackup[];
|
|
schedules: interfaces.data.IBackupSchedule[];
|
|
}
|
|
|
|
export interface ISettingsState {
|
|
settings: interfaces.data.ISettings | null;
|
|
backupPasswordConfigured: boolean;
|
|
}
|
|
|
|
export interface IUiState {
|
|
activeView: string;
|
|
autoRefresh: boolean;
|
|
refreshInterval: number;
|
|
}
|
|
|
|
// ============================================================================
|
|
// State Parts
|
|
// ============================================================================
|
|
|
|
export const loginStatePart = await appState.getStatePart<ILoginState>(
|
|
'login',
|
|
{
|
|
identity: null,
|
|
isLoggedIn: false,
|
|
},
|
|
'persistent',
|
|
);
|
|
|
|
export const systemStatePart = await appState.getStatePart<ISystemState>(
|
|
'system',
|
|
{
|
|
status: null,
|
|
},
|
|
'soft',
|
|
);
|
|
|
|
export const servicesStatePart = await appState.getStatePart<IServicesState>(
|
|
'services',
|
|
{
|
|
services: [],
|
|
currentService: null,
|
|
currentServiceLogs: [],
|
|
currentServiceStats: null,
|
|
platformServices: [],
|
|
currentPlatformService: null,
|
|
},
|
|
'soft',
|
|
);
|
|
|
|
export const networkStatePart = await appState.getStatePart<INetworkState>(
|
|
'network',
|
|
{
|
|
targets: [],
|
|
stats: null,
|
|
trafficStats: null,
|
|
dnsRecords: [],
|
|
domains: [],
|
|
certificates: [],
|
|
},
|
|
'soft',
|
|
);
|
|
|
|
export const registriesStatePart = await appState.getStatePart<IRegistriesState>(
|
|
'registries',
|
|
{
|
|
tokens: [],
|
|
registryStatus: null,
|
|
},
|
|
'soft',
|
|
);
|
|
|
|
export const backupsStatePart = await appState.getStatePart<IBackupsState>(
|
|
'backups',
|
|
{
|
|
backups: [],
|
|
schedules: [],
|
|
},
|
|
'soft',
|
|
);
|
|
|
|
export const settingsStatePart = await appState.getStatePart<ISettingsState>(
|
|
'settings',
|
|
{
|
|
settings: null,
|
|
backupPasswordConfigured: false,
|
|
},
|
|
'soft',
|
|
);
|
|
|
|
export const uiStatePart = await appState.getStatePart<IUiState>(
|
|
'ui',
|
|
{
|
|
activeView: 'dashboard',
|
|
autoRefresh: true,
|
|
refreshInterval: 30000,
|
|
},
|
|
);
|
|
|
|
// ============================================================================
|
|
// Helpers
|
|
// ============================================================================
|
|
|
|
interface IActionContext {
|
|
identity: interfaces.data.IIdentity | null;
|
|
}
|
|
|
|
const getActionContext = (): IActionContext => {
|
|
return { identity: loginStatePart.getState().identity };
|
|
};
|
|
|
|
// ============================================================================
|
|
// Login Actions
|
|
// ============================================================================
|
|
|
|
export const loginAction = loginStatePart.createAction<{
|
|
username: string;
|
|
password: string;
|
|
}>(async (statePartArg, dataArg) => {
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_AdminLoginWithUsernameAndPassword
|
|
>('/typedrequest', 'adminLoginWithUsernameAndPassword');
|
|
|
|
const response = await typedRequest.fire({
|
|
username: dataArg.username,
|
|
password: dataArg.password,
|
|
});
|
|
|
|
return {
|
|
identity: response.identity,
|
|
isLoggedIn: true,
|
|
};
|
|
} catch (err) {
|
|
console.error('Login failed:', err);
|
|
return { identity: null, isLoggedIn: false };
|
|
}
|
|
});
|
|
|
|
export const logoutAction = loginStatePart.createAction(async (statePartArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
if (context.identity) {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_AdminLogout
|
|
>('/typedrequest', 'adminLogout');
|
|
await typedRequest.fire({ identity: context.identity });
|
|
}
|
|
} catch (err) {
|
|
console.error('Logout error:', err);
|
|
}
|
|
return { identity: null, isLoggedIn: false };
|
|
});
|
|
|
|
// ============================================================================
|
|
// System Status Actions
|
|
// ============================================================================
|
|
|
|
export const fetchSystemStatusAction = systemStatePart.createAction(async (statePartArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetSystemStatus
|
|
>('/typedrequest', 'getSystemStatus');
|
|
const response = await typedRequest.fire({ identity: context.identity! });
|
|
return { status: response.status };
|
|
} catch (err) {
|
|
console.error('Failed to fetch system status:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
// ============================================================================
|
|
// Services Actions
|
|
// ============================================================================
|
|
|
|
export const fetchServicesAction = servicesStatePart.createAction(async (statePartArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetServices
|
|
>('/typedrequest', 'getServices');
|
|
const response = await typedRequest.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), services: response.services };
|
|
} catch (err) {
|
|
console.error('Failed to fetch services:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const fetchServiceAction = servicesStatePart.createAction<{ name: string }>(
|
|
async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetService
|
|
>('/typedrequest', 'getService');
|
|
const response = await typedRequest.fire({
|
|
identity: context.identity!,
|
|
serviceName: dataArg.name,
|
|
});
|
|
return { ...statePartArg.getState(), currentService: response.service };
|
|
} catch (err) {
|
|
console.error('Failed to fetch service:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
},
|
|
);
|
|
|
|
export const createServiceAction = servicesStatePart.createAction<{
|
|
config: interfaces.data.IServiceCreate;
|
|
}>(async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_CreateService
|
|
>('/typedrequest', 'createService');
|
|
await typedRequest.fire({
|
|
identity: context.identity!,
|
|
serviceConfig: dataArg.config,
|
|
});
|
|
// Re-fetch services list
|
|
const listReq = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetServices
|
|
>('/typedrequest', 'getServices');
|
|
const listResp = await listReq.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), services: listResp.services };
|
|
} catch (err) {
|
|
console.error('Failed to create service:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const deleteServiceAction = servicesStatePart.createAction<{ name: string }>(
|
|
async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_DeleteService
|
|
>('/typedrequest', 'deleteService');
|
|
await typedRequest.fire({
|
|
identity: context.identity!,
|
|
serviceName: dataArg.name,
|
|
});
|
|
const state = statePartArg.getState();
|
|
return {
|
|
...state,
|
|
services: state.services.filter((s) => s.name !== dataArg.name),
|
|
currentService: null,
|
|
};
|
|
} catch (err) {
|
|
console.error('Failed to delete service:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
},
|
|
);
|
|
|
|
export const startServiceAction = servicesStatePart.createAction<{ name: string }>(
|
|
async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_StartService
|
|
>('/typedrequest', 'startService');
|
|
await typedRequest.fire({
|
|
identity: context.identity!,
|
|
serviceName: dataArg.name,
|
|
});
|
|
// Re-fetch services
|
|
const listReq = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetServices
|
|
>('/typedrequest', 'getServices');
|
|
const listResp = await listReq.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), services: listResp.services };
|
|
} catch (err) {
|
|
console.error('Failed to start service:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
},
|
|
);
|
|
|
|
export const stopServiceAction = servicesStatePart.createAction<{ name: string }>(
|
|
async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_StopService
|
|
>('/typedrequest', 'stopService');
|
|
await typedRequest.fire({
|
|
identity: context.identity!,
|
|
serviceName: dataArg.name,
|
|
});
|
|
const listReq = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetServices
|
|
>('/typedrequest', 'getServices');
|
|
const listResp = await listReq.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), services: listResp.services };
|
|
} catch (err) {
|
|
console.error('Failed to stop service:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
},
|
|
);
|
|
|
|
export const restartServiceAction = servicesStatePart.createAction<{ name: string }>(
|
|
async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_RestartService
|
|
>('/typedrequest', 'restartService');
|
|
await typedRequest.fire({
|
|
identity: context.identity!,
|
|
serviceName: dataArg.name,
|
|
});
|
|
const listReq = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetServices
|
|
>('/typedrequest', 'getServices');
|
|
const listResp = await listReq.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), services: listResp.services };
|
|
} catch (err) {
|
|
console.error('Failed to restart service:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
},
|
|
);
|
|
|
|
export const fetchServiceLogsAction = servicesStatePart.createAction<{
|
|
name: string;
|
|
lines?: number;
|
|
}>(async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetServiceLogs
|
|
>('/typedrequest', 'getServiceLogs');
|
|
const response = await typedRequest.fire({
|
|
identity: context.identity!,
|
|
serviceName: dataArg.name,
|
|
tail: dataArg.lines || 200,
|
|
});
|
|
return { ...statePartArg.getState(), currentServiceLogs: response.logs };
|
|
} catch (err) {
|
|
console.error('Failed to fetch service logs:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const fetchServiceStatsAction = servicesStatePart.createAction<{ name: string }>(
|
|
async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetServiceStats
|
|
>('/typedrequest', 'getServiceStats');
|
|
const response = await typedRequest.fire({
|
|
identity: context.identity!,
|
|
serviceName: dataArg.name,
|
|
});
|
|
return { ...statePartArg.getState(), currentServiceStats: response.stats };
|
|
} catch (err) {
|
|
console.error('Failed to fetch service stats:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
},
|
|
);
|
|
|
|
// ============================================================================
|
|
// Platform Services Actions
|
|
// ============================================================================
|
|
|
|
export const fetchPlatformServicesAction = servicesStatePart.createAction(
|
|
async (statePartArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetPlatformServices
|
|
>('/typedrequest', 'getPlatformServices');
|
|
const response = await typedRequest.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), platformServices: response.platformServices };
|
|
} catch (err) {
|
|
console.error('Failed to fetch platform services:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
},
|
|
);
|
|
|
|
export const startPlatformServiceAction = servicesStatePart.createAction<{
|
|
serviceType: interfaces.data.TPlatformServiceType;
|
|
}>(async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_StartPlatformService
|
|
>('/typedrequest', 'startPlatformService');
|
|
await typedRequest.fire({
|
|
identity: context.identity!,
|
|
serviceType: dataArg.serviceType,
|
|
});
|
|
// Re-fetch platform services
|
|
const listReq = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetPlatformServices
|
|
>('/typedrequest', 'getPlatformServices');
|
|
const listResp = await listReq.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), platformServices: listResp.platformServices };
|
|
} catch (err) {
|
|
console.error('Failed to start platform service:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const stopPlatformServiceAction = servicesStatePart.createAction<{
|
|
serviceType: interfaces.data.TPlatformServiceType;
|
|
}>(async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_StopPlatformService
|
|
>('/typedrequest', 'stopPlatformService');
|
|
await typedRequest.fire({
|
|
identity: context.identity!,
|
|
serviceType: dataArg.serviceType,
|
|
});
|
|
const listReq = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetPlatformServices
|
|
>('/typedrequest', 'getPlatformServices');
|
|
const listResp = await listReq.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), platformServices: listResp.platformServices };
|
|
} catch (err) {
|
|
console.error('Failed to stop platform service:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
// ============================================================================
|
|
// Network Actions
|
|
// ============================================================================
|
|
|
|
export const fetchNetworkTargetsAction = networkStatePart.createAction(async (statePartArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetNetworkTargets
|
|
>('/typedrequest', 'getNetworkTargets');
|
|
const response = await typedRequest.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), targets: response.targets };
|
|
} catch (err) {
|
|
console.error('Failed to fetch network targets:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const fetchNetworkStatsAction = networkStatePart.createAction(async (statePartArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetNetworkStats
|
|
>('/typedrequest', 'getNetworkStats');
|
|
const response = await typedRequest.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), stats: response.stats };
|
|
} catch (err) {
|
|
console.error('Failed to fetch network stats:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const fetchTrafficStatsAction = networkStatePart.createAction(async (statePartArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetTrafficStats
|
|
>('/typedrequest', 'getTrafficStats');
|
|
const response = await typedRequest.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), trafficStats: response.stats };
|
|
} catch (err) {
|
|
console.error('Failed to fetch traffic stats:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const fetchDnsRecordsAction = networkStatePart.createAction(async (statePartArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetDnsRecords
|
|
>('/typedrequest', 'getDnsRecords');
|
|
const response = await typedRequest.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), dnsRecords: response.records };
|
|
} catch (err) {
|
|
console.error('Failed to fetch DNS records:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const syncDnsAction = networkStatePart.createAction(async (statePartArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_SyncDns
|
|
>('/typedrequest', 'syncDns');
|
|
await typedRequest.fire({ identity: context.identity! });
|
|
// Re-fetch DNS records
|
|
const listReq = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetDnsRecords
|
|
>('/typedrequest', 'getDnsRecords');
|
|
const listResp = await listReq.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), dnsRecords: listResp.records };
|
|
} catch (err) {
|
|
console.error('Failed to sync DNS:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const fetchDomainsAction = networkStatePart.createAction(async (statePartArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetDomains
|
|
>('/typedrequest', 'getDomains');
|
|
const response = await typedRequest.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), domains: response.domains };
|
|
} catch (err) {
|
|
console.error('Failed to fetch domains:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const fetchCertificatesAction = networkStatePart.createAction(async (statePartArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_ListCertificates
|
|
>('/typedrequest', 'listCertificates');
|
|
const response = await typedRequest.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), certificates: response.certificates };
|
|
} catch (err) {
|
|
console.error('Failed to fetch certificates:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const renewCertificateAction = networkStatePart.createAction<{ domain: string }>(
|
|
async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_RenewCertificate
|
|
>('/typedrequest', 'renewCertificate');
|
|
await typedRequest.fire({
|
|
identity: context.identity!,
|
|
domain: dataArg.domain,
|
|
});
|
|
// Re-fetch certificates
|
|
const listReq = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_ListCertificates
|
|
>('/typedrequest', 'listCertificates');
|
|
const listResp = await listReq.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), certificates: listResp.certificates };
|
|
} catch (err) {
|
|
console.error('Failed to renew certificate:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
},
|
|
);
|
|
|
|
// ============================================================================
|
|
// Registry Actions
|
|
// ============================================================================
|
|
|
|
export const fetchRegistryTokensAction = registriesStatePart.createAction(
|
|
async (statePartArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetRegistryTokens
|
|
>('/typedrequest', 'getRegistryTokens');
|
|
const response = await typedRequest.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), tokens: response.tokens };
|
|
} catch (err) {
|
|
console.error('Failed to fetch registry tokens:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
},
|
|
);
|
|
|
|
export const createRegistryTokenAction = registriesStatePart.createAction<{
|
|
token: interfaces.data.ICreateTokenRequest;
|
|
}>(async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_CreateRegistryToken
|
|
>('/typedrequest', 'createRegistryToken');
|
|
await typedRequest.fire({
|
|
identity: context.identity!,
|
|
token: dataArg.token,
|
|
});
|
|
// Re-fetch tokens
|
|
const listReq = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetRegistryTokens
|
|
>('/typedrequest', 'getRegistryTokens');
|
|
const listResp = await listReq.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), tokens: listResp.tokens };
|
|
} catch (err) {
|
|
console.error('Failed to create registry token:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const deleteRegistryTokenAction = registriesStatePart.createAction<{
|
|
tokenId: string;
|
|
}>(async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_DeleteRegistryToken
|
|
>('/typedrequest', 'deleteRegistryToken');
|
|
await typedRequest.fire({
|
|
identity: context.identity!,
|
|
tokenId: dataArg.tokenId,
|
|
});
|
|
const state = statePartArg.getState();
|
|
return {
|
|
...state,
|
|
tokens: state.tokens.filter((t) => t.id !== dataArg.tokenId),
|
|
};
|
|
} catch (err) {
|
|
console.error('Failed to delete registry token:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
// ============================================================================
|
|
// Backups Actions
|
|
// ============================================================================
|
|
|
|
export const fetchBackupsAction = backupsStatePart.createAction(async (statePartArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetBackups
|
|
>('/typedrequest', 'getBackups');
|
|
const response = await typedRequest.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), backups: response.backups };
|
|
} catch (err) {
|
|
console.error('Failed to fetch backups:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const deleteBackupAction = backupsStatePart.createAction<{ backupId: number }>(
|
|
async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_DeleteBackup
|
|
>('/typedrequest', 'deleteBackup');
|
|
await typedRequest.fire({
|
|
identity: context.identity!,
|
|
backupId: dataArg.backupId,
|
|
});
|
|
const state = statePartArg.getState();
|
|
return {
|
|
...state,
|
|
backups: state.backups.filter((b) => b.id !== dataArg.backupId),
|
|
};
|
|
} catch (err) {
|
|
console.error('Failed to delete backup:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
},
|
|
);
|
|
|
|
export const fetchSchedulesAction = backupsStatePart.createAction(async (statePartArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetBackupSchedules
|
|
>('/typedrequest', 'getBackupSchedules');
|
|
const response = await typedRequest.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), schedules: response.schedules };
|
|
} catch (err) {
|
|
console.error('Failed to fetch schedules:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const createScheduleAction = backupsStatePart.createAction<{
|
|
config: interfaces.data.IBackupScheduleCreate;
|
|
}>(async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_CreateBackupSchedule
|
|
>('/typedrequest', 'createBackupSchedule');
|
|
await typedRequest.fire({
|
|
identity: context.identity!,
|
|
scheduleConfig: dataArg.config,
|
|
});
|
|
// Re-fetch schedules
|
|
const listReq = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetBackupSchedules
|
|
>('/typedrequest', 'getBackupSchedules');
|
|
const listResp = await listReq.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), schedules: listResp.schedules };
|
|
} catch (err) {
|
|
console.error('Failed to create schedule:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const deleteScheduleAction = backupsStatePart.createAction<{ scheduleId: number }>(
|
|
async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_DeleteBackupSchedule
|
|
>('/typedrequest', 'deleteBackupSchedule');
|
|
await typedRequest.fire({
|
|
identity: context.identity!,
|
|
scheduleId: dataArg.scheduleId,
|
|
});
|
|
const state = statePartArg.getState();
|
|
return {
|
|
...state,
|
|
schedules: state.schedules.filter((s) => s.id !== dataArg.scheduleId),
|
|
};
|
|
} catch (err) {
|
|
console.error('Failed to delete schedule:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
},
|
|
);
|
|
|
|
export const triggerScheduleAction = backupsStatePart.createAction<{ scheduleId: number }>(
|
|
async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_TriggerBackupSchedule
|
|
>('/typedrequest', 'triggerBackupSchedule');
|
|
await typedRequest.fire({
|
|
identity: context.identity!,
|
|
scheduleId: dataArg.scheduleId,
|
|
});
|
|
// Re-fetch backups
|
|
const backupsReq = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetBackups
|
|
>('/typedrequest', 'getBackups');
|
|
const backupsResp = await backupsReq.fire({ identity: context.identity! });
|
|
return { ...statePartArg.getState(), backups: backupsResp.backups };
|
|
} catch (err) {
|
|
console.error('Failed to trigger schedule:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
},
|
|
);
|
|
|
|
// ============================================================================
|
|
// Settings Actions
|
|
// ============================================================================
|
|
|
|
export const fetchSettingsAction = settingsStatePart.createAction(async (statePartArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const [settingsResp, passwordResp] = await Promise.all([
|
|
new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetSettings
|
|
>('/typedrequest', 'getSettings').fire({ identity: context.identity! }),
|
|
new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_GetBackupPasswordStatus
|
|
>('/typedrequest', 'getBackupPasswordStatus').fire({ identity: context.identity! }),
|
|
]);
|
|
return {
|
|
settings: settingsResp.settings,
|
|
backupPasswordConfigured: passwordResp.status.isConfigured,
|
|
};
|
|
} catch (err) {
|
|
console.error('Failed to fetch settings:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const updateSettingsAction = settingsStatePart.createAction<{
|
|
settings: Partial<interfaces.data.ISettings>;
|
|
}>(async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_UpdateSettings
|
|
>('/typedrequest', 'updateSettings');
|
|
const response = await typedRequest.fire({
|
|
identity: context.identity!,
|
|
settings: dataArg.settings,
|
|
});
|
|
return { ...statePartArg.getState(), settings: response.settings };
|
|
} catch (err) {
|
|
console.error('Failed to update settings:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
});
|
|
|
|
export const setBackupPasswordAction = settingsStatePart.createAction<{ password: string }>(
|
|
async (statePartArg, dataArg) => {
|
|
const context = getActionContext();
|
|
try {
|
|
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
interfaces.requests.IReq_SetBackupPassword
|
|
>('/typedrequest', 'setBackupPassword');
|
|
await typedRequest.fire({
|
|
identity: context.identity!,
|
|
password: dataArg.password,
|
|
});
|
|
return { ...statePartArg.getState(), backupPasswordConfigured: true };
|
|
} catch (err) {
|
|
console.error('Failed to set backup password:', err);
|
|
return statePartArg.getState();
|
|
}
|
|
},
|
|
);
|
|
|
|
// ============================================================================
|
|
// UI Actions
|
|
// ============================================================================
|
|
|
|
export const setActiveViewAction = uiStatePart.createAction<{ view: string }>(
|
|
async (statePartArg, dataArg) => {
|
|
return { ...statePartArg.getState(), activeView: dataArg.view };
|
|
},
|
|
);
|
|
|
|
export const toggleAutoRefreshAction = uiStatePart.createAction(async (statePartArg) => {
|
|
const state = statePartArg.getState();
|
|
return { ...state, autoRefresh: !state.autoRefresh };
|
|
});
|
|
|
|
// ============================================================================
|
|
// Auto-refresh system
|
|
// ============================================================================
|
|
|
|
let refreshIntervalHandle: ReturnType<typeof setInterval> | null = null;
|
|
|
|
const dispatchCombinedRefreshAction = async () => {
|
|
const loginState = loginStatePart.getState();
|
|
if (!loginState.isLoggedIn) return;
|
|
|
|
try {
|
|
await systemStatePart.dispatchAction(fetchSystemStatusAction, null);
|
|
} catch (err) {
|
|
// Silently fail on auto-refresh
|
|
}
|
|
};
|
|
|
|
const startAutoRefresh = () => {
|
|
const uiState = uiStatePart.getState();
|
|
const loginState = loginStatePart.getState();
|
|
|
|
if (uiState.autoRefresh && loginState.isLoggedIn) {
|
|
if (refreshIntervalHandle) {
|
|
clearInterval(refreshIntervalHandle);
|
|
}
|
|
refreshIntervalHandle = setInterval(() => {
|
|
dispatchCombinedRefreshAction();
|
|
}, uiState.refreshInterval);
|
|
} else {
|
|
if (refreshIntervalHandle) {
|
|
clearInterval(refreshIntervalHandle);
|
|
refreshIntervalHandle = null;
|
|
}
|
|
}
|
|
};
|
|
|
|
uiStatePart.select((s) => s).subscribe(() => startAutoRefresh());
|
|
loginStatePart.select((s) => s).subscribe(() => startAutoRefresh());
|
|
startAutoRefresh();
|