mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-11-01 10:22:08 +00:00
142 lines
11 KiB
TypeScript
142 lines
11 KiB
TypeScript
// Legacy HostBackup API messages are an English wire contract shared with CLI callers.
|
|
// Match complete, source-verified messages only; never derive a translation key from input.
|
|
// This presentation-only adapter keeps unknown tool diagnostics and parameter text intact.
|
|
type Translate = (key: string, params?: Record<string, string | number>) => string
|
|
|
|
const fixed = new Map<string, string>([
|
|
["path must be absolute", "backup.apiErrors.absolutePath"],
|
|
["this path is already configured", "backup.apiErrors.pathConfigured"],
|
|
["path is required", "backup.apiErrors.pathRequired"],
|
|
["path query parameter is required", "backup.apiErrors.pathQuery"],
|
|
["path not found", "backup.apiErrors.pathNotFound"],
|
|
["invalid job id", "backup.apiErrors.invalidJobId"],
|
|
["job not found", "backup.apiErrors.jobNotFound"],
|
|
["runner script not installed", "backup.apiErrors.runnerMissing"],
|
|
["no restore state to dismiss", "backup.apiErrors.noRestore"],
|
|
["invalid file name", "backup.apiErrors.invalidFile"],
|
|
["not found", "backup.apiErrors.notFound"],
|
|
["log path outside allowed directory", "backup.apiErrors.logOutside"],
|
|
["targets must be a list", "backup.apiErrors.targetsList"],
|
|
["empty expression", "backup.apiErrors.emptyExpression"],
|
|
["invalid id (use letters, digits, _ or -)", "backup.apiErrors.invalidId"],
|
|
["backend must be pbs, local or borg", "backup.apiErrors.backend"],
|
|
["backend must be pbs or borg", "backup.apiErrors.remoteBackend"],
|
|
["backend must be 'pbs' or 'borg'", "backup.apiErrors.remoteBackendQuoted"],
|
|
["profile_mode must be default or custom", "backup.apiErrors.profileMode"],
|
|
["borg cannot be attached (PVE vzdump only writes to pbs/local storages)", "backup.apiErrors.borgAttached"],
|
|
["borg is not a valid backend for attached jobs (PVE vzdump only writes to pbs/local storages)", "backup.apiErrors.borgAttachedLong"],
|
|
["pve_parent_job_id and pve_storage are required for attached", "backup.apiErrors.parentRequired"],
|
|
["paths must be a list of absolute paths", "backup.apiErrors.absolutePaths"],
|
|
["custom profile needs at least one path", "backup.apiErrors.customPath"],
|
|
["could not resolve default profile paths", "backup.apiErrors.defaultPaths"],
|
|
["retention must be an object", "backup.apiErrors.retentionObject"],
|
|
["pbs_repository is required", "backup.apiErrors.pbsRepository"],
|
|
["pbs_encrypt_mode must be 'none', 'new' or 'existing'", "backup.apiErrors.pbsEncryption"],
|
|
["failed to create PBS encryption keyfile", "backup.apiErrors.pbsKeyFailed"],
|
|
["failed to create PBS encryption keyfile (is proxmox-backup-client installed?)", "backup.apiErrors.pbsClientMissing"],
|
|
["borg_repo is required", "backup.apiErrors.borgRepository"],
|
|
["borg_encrypt_mode must be one of: none, repokey, keyfile, authenticated", "backup.apiErrors.borgEncryption"],
|
|
["encrypt_mode must be one of: none, repokey, keyfile, authenticated", "backup.apiErrors.encryption"],
|
|
["borg_passphrase is required when encryption is enabled (save it on the destination or pass one in the request)", "backup.apiErrors.borgPassphrase"],
|
|
["passphrase is required when encryption is enabled", "backup.apiErrors.passphrase"],
|
|
["password is required", "backup.apiErrors.password"],
|
|
["confirm_device must match device exactly (typo / safety check)", "backup.apiErrors.deviceConfirmation"],
|
|
["invalid device path", "backup.apiErrors.invalidDevice"],
|
|
["absolute mountpoint required", "backup.apiErrors.absoluteMountpoint"],
|
|
["archive layout not recognized — no rootfs/ found", "backup.apiErrors.archiveLayout"],
|
|
["archive not found", "backup.apiErrors.archiveMissing"],
|
|
["archive path is not a regular file", "backup.apiErrors.archiveNotFile"],
|
|
["invalid name", "backup.apiErrors.invalidName"],
|
|
["invalid staging_path", "backup.apiErrors.invalidStaging"],
|
|
["job name cannot be changed (delete + recreate to rename)", "backup.apiErrors.jobRename"],
|
|
["key_path must be absolute", "backup.apiErrors.absoluteKey"],
|
|
["mode must be \"local\" or \"ssh\"", "backup.apiErrors.mode"],
|
|
["name is required (letters, digits, _ or -)", "backup.apiErrors.nameRequired"],
|
|
["no log available for this job yet", "backup.apiErrors.noLog"],
|
|
["no manual PBS configs file", "backup.apiErrors.noPbsConfig"],
|
|
["output file missing", "backup.apiErrors.outputMissing"],
|
|
["parser output was not valid JSON", "backup.apiErrors.parserJson"],
|
|
["run_restore output was not valid JSON", "backup.apiErrors.restoreJson"],
|
|
["repo is required", "backup.apiErrors.repoRequired"],
|
|
["repo_name and snapshot are required", "backup.apiErrors.repoSnapshot"],
|
|
["repo_name and snapshot are required for borg", "backup.apiErrors.borgRepoSnapshot"],
|
|
["repo_name and snapshot are required for pbs", "backup.apiErrors.pbsRepoSnapshot"],
|
|
["repo_name is required", "backup.apiErrors.repoName"],
|
|
["restore tooling not installed on this host", "backup.apiErrors.restoreMissing"],
|
|
["server and datastore are required", "backup.apiErrors.serverDatastore"],
|
|
["snapshot is required", "backup.apiErrors.snapshotRequired"],
|
|
["source must be pbs, borg, or local", "backup.apiErrors.source"],
|
|
["ssh_port must be an integer between 1 and 65535", "backup.apiErrors.sshPort"],
|
|
["ssh_user, ssh_host and ssh_remote_path are required for ssh mode", "backup.apiErrors.sshRequired"],
|
|
["target has no repository path", "backup.apiErrors.repositoryPath"],
|
|
["task not found or expired", "backup.apiErrors.taskExpired"],
|
|
["invalid expression", "backup.apiErrors.invalidExpression"],
|
|
["no report emitted", "backup.apiErrors.noReport"],
|
|
["parse_manifest exited non-zero", "backup.apiErrors.parseManifestFailed"],
|
|
])
|
|
|
|
const parameterized: ReadonlyArray<readonly [RegExp, string]> = [
|
|
[new RegExp("^job already exists: ([\\s\\S]+)$"), "backup.apiErrors.jobExists"],
|
|
[new RegExp("^path does not exist on this host: ([\\s\\S]+)$"), "backup.apiErrors.pathMissing"],
|
|
[new RegExp("^device does not exist: ([\\s\\S]+)$"), "backup.apiErrors.deviceMissing"],
|
|
[new RegExp("^not a mountpoint: ([\\s\\S]+)$"), "backup.apiErrors.mountpoint"],
|
|
[new RegExp("^local archive not found: ([\\s\\S]+)$"), "backup.apiErrors.localArchiveMissing"],
|
|
[new RegExp("^Borg destination '([\\s\\S]+)' not found$"), "backup.apiErrors.borgDestination"],
|
|
[new RegExp("^PBS destination '([\\s\\S]+)' not found$"), "backup.apiErrors.pbsDestination"],
|
|
[new RegExp("^no password available for PBS repo '([\\s\\S]+)'$"), "backup.apiErrors.pbsPassword"],
|
|
[new RegExp("^Borg repo \"([\\s\\S]+)\" not configured$"), "backup.apiErrors.borgRepoMissing"],
|
|
[new RegExp("^PBS repo \"([\\s\\S]+)\" not configured$"), "backup.apiErrors.pbsRepoMissing"],
|
|
[new RegExp("^Borg target not found: ([\\s\\S]+)$"), "backup.apiErrors.borgTargetMissing"],
|
|
[new RegExp("^PBS repo not found: ([\\s\\S]+)$"), "backup.apiErrors.pbsTargetMissing"],
|
|
[new RegExp("^PVE vzdump job not found: ([\\s\\S]+)$"), "backup.apiErrors.pveJobMissing"],
|
|
[new RegExp("^cannot persist state: ([\\s\\S]+)$"), "backup.apiErrors.statePersist"],
|
|
[new RegExp("^cannot prepare ssh dir: ([\\s\\S]+)$"), "backup.apiErrors.sshDirectory"],
|
|
[new RegExp("^cannot read log: ([\\s\\S]+)$"), "backup.apiErrors.logRead"],
|
|
[new RegExp("^could not update \\.env: ([\\s\\S]+)$"), "backup.apiErrors.envUpdate"],
|
|
[new RegExp("^failed to persist PBS config: ([\\s\\S]+)$"), "backup.apiErrors.pbsConfigWrite"],
|
|
[new RegExp("^failed to persist: ([\\s\\S]+)$"), "backup.apiErrors.persist"],
|
|
[new RegExp("^failed to remove archive: ([\\s\\S]+)$"), "backup.apiErrors.archiveRemove"],
|
|
[new RegExp("^failed to start: ([\\s\\S]+)$"), "backup.apiErrors.start"],
|
|
[new RegExp("^failed to update borg-targets\\.txt: ([\\s\\S]+)$"), "backup.apiErrors.borgTargetsUpdate"],
|
|
[new RegExp("^failed to update pbs-manual-configs\\.txt: ([\\s\\S]+)$"), "backup.apiErrors.pbsTargetsUpdate"],
|
|
[new RegExp("^failed to update systemd units: ([\\s\\S]+)$"), "backup.apiErrors.unitsUpdate"],
|
|
[new RegExp("^failed to write borg-targets\\.txt: ([\\s\\S]+)$"), "backup.apiErrors.borgTargetsWrite"],
|
|
[new RegExp("^failed to write job files: ([\\s\\S]+)$"), "backup.apiErrors.jobWrite"],
|
|
[new RegExp("^failed to write local-target\\.conf: ([\\s\\S]+)$"), "backup.apiErrors.localTargetWrite"],
|
|
[new RegExp("^failed to write systemd units: ([\\s\\S]+)$"), "backup.apiErrors.unitsWrite"],
|
|
[new RegExp("^format failed: ([\\s\\S]+)$"), "backup.apiErrors.format"],
|
|
[new RegExp("^invalid on_calendar: ([\\s\\S]+)$"), "backup.apiErrors.calendar"],
|
|
[new RegExp("^mount failed: ([\\s\\S]+)$"), "backup.apiErrors.mount"],
|
|
[new RegExp("^parser invocation failed: ([\\s\\S]+)$"), "backup.apiErrors.parserInvocation"],
|
|
[new RegExp("^preflight invocation failed: ([\\s\\S]+)$"), "backup.apiErrors.preflightInvocation"],
|
|
[new RegExp("^public key not found after generation: ([\\s\\S]+)$"), "backup.apiErrors.publicKeyMissing"],
|
|
[new RegExp("^retention\\.([\\s\\S]+) must be an integer$"), "backup.apiErrors.retentionInteger"],
|
|
[new RegExp("^retention\\.([\\s\\S]+) must be non-negative$"), "backup.apiErrors.retentionNegative"],
|
|
[new RegExp("^ssh-keygen failed: ([\\s\\S]+)$"), "backup.apiErrors.keygen"],
|
|
[new RegExp("^systemctl failed: ([\\s\\S]+)$"), "backup.apiErrors.systemctl"],
|
|
[new RegExp("^umount failed: ([\\s\\S]+)$"), "backup.apiErrors.unmount"],
|
|
[new RegExp("^task is in state \"([\\s\\S]+)\", not completed$"), "backup.apiErrors.taskIncomplete"],
|
|
[new RegExp("^unknown kind: ([\\s\\S]+)$"), "backup.apiErrors.unknownKind"],
|
|
[new RegExp("^unknown mode \"([\\s\\S]+)\"$"), "backup.apiErrors.unknownMode"],
|
|
[new RegExp("^([\\s\\S]+) is the built-in default and cannot be removed$"), "backup.apiErrors.defaultRemove"],
|
|
[new RegExp("^([\\s\\S]+) is the built-in default; no need to add it$"), "backup.apiErrors.defaultAdd"],
|
|
[new RegExp("^pbs_encrypt_mode='existing' but no keyfile is installed at ([\\s\\S]+) — import one first with POST /api/host-backups/pbs-encryption/import$"), "backup.apiErrors.keyImport"],
|
|
[new RegExp("^PVE job storage mismatch \\(job uses ([\\s\\S]+), payload says ([\\s\\S]+)\\)$"), "backup.apiErrors.storageMismatch"],
|
|
]
|
|
|
|
export function hostBackupErrorText(problem: unknown, t: Translate): string {
|
|
const message = typeof problem === "string" ? problem
|
|
: problem && typeof problem === "object" && "message" in problem && typeof problem.message === "string"
|
|
? problem.message : ""
|
|
if (!message) return t("backup.apiErrors.requestFailed")
|
|
const key = fixed.get(message)
|
|
if (key) return t(key)
|
|
// Keep unusually large tool output verbatim, without running pattern matching over it.
|
|
if (message.length > 16384) return message
|
|
for (const [pattern, patternKey] of parameterized) {
|
|
const match = pattern.exec(message)
|
|
if (match) return t(patternKey, { value: match[1], other: match[2] ?? "" })
|
|
}
|
|
return message
|
|
}
|