mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-03 19:09:36 +00:00
Two PostgreSQL gaps on the panel:
1. x-ui setting and other CLI subcommands read XUI_DB_TYPE/XUI_DB_DSN from
the process environment, which systemd injects via EnvironmentFile but a
plain shell invocation does not. On a PostgreSQL install the CLI silently
fell back to SQLite, so changes made from the management menu never
reached the panel's database. Load the systemd EnvironmentFile
(/etc/default/x-ui and distro equivalents) at startup; godotenv.Load does
not override existing vars, so it stays a no-op for the managed service.
2. DB backup/restore (panel endpoints and the Telegram bot) only handled the
SQLite file, so on PostgreSQL Back Up returned a stale/absent x-ui.db and
Restore silently did nothing. Add pg_dump/pg_restore based backup/restore:
- GetDb/ImportDB run pg_dump (custom format) / pg_restore, passing
credentials via the PG* environment instead of argv.
- getDb downloads x-ui.dump on Postgres, x-ui.db on SQLite.
- Telegram backup sends the matching file via GetDb.
- BackupModal shows a Postgres note and accepts .dump; the dist page
injects window.X_UI_DB_TYPE; new strings translated for all locales.
- install.sh installs postgresql-client for the external-DSN path and
points the user to in-panel Backup & Restore.
Closes #4658
90 lines
2.7 KiB
TypeScript
90 lines
2.7 KiB
TypeScript
/// <reference types="vite/client" />
|
|
|
|
interface SubPageData {
|
|
sId?: string;
|
|
enabled?: boolean;
|
|
download?: string;
|
|
upload?: string;
|
|
total?: string;
|
|
used?: string;
|
|
remained?: string;
|
|
totalByte?: string | number;
|
|
expire?: string | number;
|
|
lastOnline?: string | number;
|
|
subUrl?: string;
|
|
subJsonUrl?: string;
|
|
subClashUrl?: string;
|
|
subTitle?: string;
|
|
links?: string[];
|
|
emails?: string[];
|
|
datepicker?: 'gregorian' | 'jalalian';
|
|
downloadByte?: string | number;
|
|
uploadByte?: string | number;
|
|
usedByte?: string | number;
|
|
}
|
|
|
|
interface Window {
|
|
X_UI_BASE_PATH?: string;
|
|
X_UI_CUR_VER?: string;
|
|
X_UI_DB_TYPE?: string;
|
|
__SUB_PAGE_DATA__?: SubPageData;
|
|
}
|
|
|
|
declare module 'qs' {
|
|
interface StringifyOptions {
|
|
arrayFormat?: 'indices' | 'brackets' | 'repeat' | 'comma';
|
|
encode?: boolean;
|
|
encoder?: (str: unknown, defaultEncoder: (s: unknown) => string, charset: string, type: 'key' | 'value') => string;
|
|
allowDots?: boolean;
|
|
skipNulls?: boolean;
|
|
addQueryPrefix?: boolean;
|
|
}
|
|
interface ParseOptions {
|
|
depth?: number;
|
|
arrayLimit?: number;
|
|
allowDots?: boolean;
|
|
parseArrays?: boolean;
|
|
ignoreQueryPrefix?: boolean;
|
|
}
|
|
export function stringify(obj: unknown, options?: StringifyOptions): string;
|
|
export function parse(str: string, options?: ParseOptions): Record<string, unknown>;
|
|
const qs: { stringify: typeof stringify; parse: typeof parse };
|
|
export default qs;
|
|
}
|
|
|
|
declare module 'persian-calendar-suite' {
|
|
import type { ComponentType, ReactNode } from 'react';
|
|
|
|
type DateInput = string | number | null;
|
|
type OutputFormat = 'iso' | 'shamsi' | 'gregorian' | 'hijri' | 'timestamp';
|
|
|
|
interface PersianDateTimePickerProps {
|
|
value?: DateInput;
|
|
onChange?: (value: number | string | null) => void;
|
|
defaultValue?: string | number | 'now' | null;
|
|
showTime?: boolean;
|
|
minuteStep?: number;
|
|
outputFormat?: OutputFormat;
|
|
showFooter?: boolean;
|
|
theme?: Record<string, unknown>;
|
|
disabledHours?: number[];
|
|
minDate?: string | Date | null;
|
|
maxDate?: string | Date | null;
|
|
enabledDates?: string[] | null;
|
|
disabledDates?: string[] | null;
|
|
disabledWeekDays?: number[];
|
|
persianNumbers?: boolean;
|
|
rtlCalendar?: boolean;
|
|
placeholder?: string;
|
|
disabled?: boolean;
|
|
className?: string;
|
|
children?: ReactNode;
|
|
}
|
|
|
|
export const PersianDateTimePicker: ComponentType<PersianDateTimePickerProps>;
|
|
export const PersianCalendar: ComponentType<Record<string, unknown>>;
|
|
export const PersianDateRangePicker: ComponentType<Record<string, unknown>>;
|
|
export const PersianTimePicker: ComponentType<Record<string, unknown>>;
|
|
export const PersianTimeline: ComponentType<Record<string, unknown>>;
|
|
}
|