mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-06-20 21:00:41 +00:00
feat: add backup recommendations and update backup strategy UI
- Introduced new backup recommendations feature with interfaces for recommended storage providers. - Updated i18n translations for backup strategy to reflect new terminology and improved descriptions. - Enhanced types with optional private and public keys in user profiles. - Redesigned backup-related styles for better layout and responsiveness. - Updated TypeScript configuration to include shared modules. - Configured Vite to resolve shared modules and allow filesystem access. - Added cron triggers for periodic tasks in Wrangler configuration.
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
export const BACKUP_DEFAULT_TIMEZONE = 'UTC';
|
||||
export const BACKUP_DEFAULT_SCHEDULE_TIME = '03:00';
|
||||
export const BACKUP_DEFAULT_RETENTION_COUNT = 30;
|
||||
export const BACKUP_DEFAULT_E3_REGION = 'auto';
|
||||
export const BACKUP_DEFAULT_REMOTE_PATH = 'nodewarden';
|
||||
|
||||
export type BackupDestinationType = 'e3' | 'webdav' | 'placeholder';
|
||||
export type BackupScheduleFrequency = 'daily' | 'weekly' | 'monthly';
|
||||
|
||||
export interface E3BackupDestination {
|
||||
endpoint: string;
|
||||
bucket: string;
|
||||
region: string;
|
||||
accessKeyId: string;
|
||||
secretAccessKey: string;
|
||||
rootPath: string;
|
||||
}
|
||||
|
||||
export interface WebDavBackupDestination {
|
||||
baseUrl: string;
|
||||
username: string;
|
||||
password: string;
|
||||
remotePath: string;
|
||||
}
|
||||
|
||||
export interface PlaceholderBackupDestination {
|
||||
providerName: string;
|
||||
notes: string;
|
||||
}
|
||||
|
||||
export type BackupDestinationConfig =
|
||||
| E3BackupDestination
|
||||
| WebDavBackupDestination
|
||||
| PlaceholderBackupDestination;
|
||||
|
||||
export interface BackupRuntimeState {
|
||||
lastAttemptAt: string | null;
|
||||
lastAttemptLocalDate: string | null;
|
||||
lastSuccessAt: string | null;
|
||||
lastErrorAt: string | null;
|
||||
lastErrorMessage: string | null;
|
||||
lastUploadedFileName: string | null;
|
||||
lastUploadedSizeBytes: number | null;
|
||||
lastUploadedDestination: string | null;
|
||||
}
|
||||
|
||||
export interface BackupScheduleConfig {
|
||||
enabled: boolean;
|
||||
frequency: BackupScheduleFrequency;
|
||||
scheduleTime: string;
|
||||
timezone: string;
|
||||
dayOfWeek: number;
|
||||
dayOfMonth: number;
|
||||
retentionCount: number | null;
|
||||
}
|
||||
|
||||
export interface BackupDestinationRecord {
|
||||
id: string;
|
||||
name: string;
|
||||
type: BackupDestinationType;
|
||||
destination: BackupDestinationConfig;
|
||||
schedule: BackupScheduleConfig;
|
||||
runtime: BackupRuntimeState;
|
||||
}
|
||||
|
||||
export interface BackupSettings {
|
||||
destinations: BackupDestinationRecord[];
|
||||
}
|
||||
|
||||
export function createBackupRandomId(): string {
|
||||
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
return `backup-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
||||
}
|
||||
|
||||
export function createDefaultBackupRuntimeState(): BackupRuntimeState {
|
||||
return {
|
||||
lastAttemptAt: null,
|
||||
lastAttemptLocalDate: null,
|
||||
lastSuccessAt: null,
|
||||
lastErrorAt: null,
|
||||
lastErrorMessage: null,
|
||||
lastUploadedFileName: null,
|
||||
lastUploadedSizeBytes: null,
|
||||
lastUploadedDestination: null,
|
||||
};
|
||||
}
|
||||
|
||||
export function createDefaultBackupScheduleConfig(timezone: string = BACKUP_DEFAULT_TIMEZONE): BackupScheduleConfig {
|
||||
return {
|
||||
enabled: false,
|
||||
frequency: 'daily',
|
||||
scheduleTime: BACKUP_DEFAULT_SCHEDULE_TIME,
|
||||
timezone,
|
||||
dayOfWeek: 1,
|
||||
dayOfMonth: 1,
|
||||
retentionCount: BACKUP_DEFAULT_RETENTION_COUNT,
|
||||
};
|
||||
}
|
||||
|
||||
export function createDefaultBackupDestinationConfig(type: BackupDestinationType): BackupDestinationConfig {
|
||||
if (type === 'e3') {
|
||||
return {
|
||||
endpoint: '',
|
||||
bucket: '',
|
||||
region: BACKUP_DEFAULT_E3_REGION,
|
||||
accessKeyId: '',
|
||||
secretAccessKey: '',
|
||||
rootPath: BACKUP_DEFAULT_REMOTE_PATH,
|
||||
};
|
||||
}
|
||||
if (type === 'placeholder') {
|
||||
return {
|
||||
providerName: 'Reserved',
|
||||
notes: '',
|
||||
};
|
||||
}
|
||||
return {
|
||||
baseUrl: '',
|
||||
username: '',
|
||||
password: '',
|
||||
remotePath: BACKUP_DEFAULT_REMOTE_PATH,
|
||||
};
|
||||
}
|
||||
|
||||
export function createDefaultBackupDestinationName(type: BackupDestinationType, index: number): string {
|
||||
if (type === 'e3') return `E3 ${index}`;
|
||||
if (type === 'placeholder') return `Reserved ${index}`;
|
||||
return `WebDAV ${index}`;
|
||||
}
|
||||
|
||||
export interface CreateBackupDestinationRecordOptions {
|
||||
id?: string;
|
||||
name?: string;
|
||||
timezone?: string;
|
||||
}
|
||||
|
||||
export function createBackupDestinationRecord(
|
||||
type: BackupDestinationType,
|
||||
index: number,
|
||||
options: CreateBackupDestinationRecordOptions = {}
|
||||
): BackupDestinationRecord {
|
||||
return {
|
||||
id: options.id || createBackupRandomId(),
|
||||
name: options.name || createDefaultBackupDestinationName(type, index),
|
||||
type,
|
||||
destination: createDefaultBackupDestinationConfig(type),
|
||||
schedule: createDefaultBackupScheduleConfig(options.timezone || BACKUP_DEFAULT_TIMEZONE),
|
||||
runtime: createDefaultBackupRuntimeState(),
|
||||
};
|
||||
}
|
||||
|
||||
export function createDefaultBackupSettings(
|
||||
timezone: string = BACKUP_DEFAULT_TIMEZONE,
|
||||
options: { destinationName?: string } = {}
|
||||
): BackupSettings {
|
||||
return {
|
||||
destinations: [
|
||||
createBackupDestinationRecord('webdav', 1, {
|
||||
timezone,
|
||||
name: options.destinationName,
|
||||
}),
|
||||
],
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user