mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-10-22 07:08:53 +02:00
refactor: cleanup
This commit is contained in:
1 parent
598d3bd513
commit
dd42d46753
249 files changed
+67417
-6659
No files matched your search
+313
-10
@@ -11,6 +11,10 @@ export type BackendErrorCode =
|
||||
| "PROFILE_NOT_PROTECTED"
|
||||
| "PROFILE_ALREADY_PROTECTED"
|
||||
| "PROFILE_RUNNING"
|
||||
| "PROFILE_PAIRED_TWICE"
|
||||
| "URL_SCHEME_NOT_ALLOWED"
|
||||
| "TOOL_IS_LOCAL_ONLY"
|
||||
| "TYPING_TOO_LONG"
|
||||
| "PROFILE_EPHEMERAL"
|
||||
| "PROFILE_MISSING_SALT"
|
||||
| "PROFILE_LOCKED"
|
||||
@@ -41,12 +45,17 @@ export type BackendErrorCode =
|
||||
| "EXTENSION_PATH_HAS_COMMA"
|
||||
| "EXTENSION_LINK_REQUIRES_DIRECTORY"
|
||||
| "EXTENSION_LINKED_CANNOT_SYNC"
|
||||
| "EXTENSION_URL_INVALID"
|
||||
| "EXTENSION_DOWNLOAD_FAILED"
|
||||
| "EXTENSION_NOT_AN_EXTENSION"
|
||||
| "EXTENSION_TOO_LARGE"
|
||||
| "CANNOT_MODIFY_CLOUD_MANAGED_PROXY"
|
||||
| "SYNC_LOCKED_BY_PROFILE"
|
||||
| "SYNC_NOT_CONFIGURED"
|
||||
| "FINGERPRINT_REQUIRES_PRO"
|
||||
| "PROXY_NOT_WORKING"
|
||||
| "PROXY_PAYMENT_REQUIRED"
|
||||
| "PROXY_TLS_HANDSHAKE_FAILED"
|
||||
| "VPN_NOT_WORKING"
|
||||
| "CAMOUFOX_IMPORT_DEPRECATED"
|
||||
| "PROXY_SIDECAR_VERSION_MISMATCH"
|
||||
@@ -77,9 +86,19 @@ export type BackendErrorCode =
|
||||
| "MCP_SERVER_NOT_RUNNING"
|
||||
| "MCP_PORT_UNAVAILABLE"
|
||||
| "MCP_CONFIGURATION_UNAVAILABLE"
|
||||
// Local MCP has been removed in favor of remote MCP.
|
||||
| "MCP_LOCAL_REMOVED"
|
||||
| "MCP_AGENT_UNKNOWN"
|
||||
| "MCP_AGENT_INSTALL_FAILED"
|
||||
| "MCP_AGENT_REMOVE_FAILED"
|
||||
| "MCP_REMOTE_REQUIRES_SIGN_IN"
|
||||
| "MCP_REMOTE_UNAUTHORIZED"
|
||||
| "MCP_REMOTE_SLOT_TAKEN"
|
||||
| "MCP_REMOTE_NOT_ENTITLED"
|
||||
| "MCP_REMOTE_UNREACHABLE"
|
||||
| "MCP_REMOTE_KEY_MISSING"
|
||||
| "MCP_REMOTE_KEY_LIMIT"
|
||||
| "MCP_REMOTE_KEY_UNAVAILABLE"
|
||||
| "VLESS_CONFIG_INVALID"
|
||||
| "XRAY_UNAVAILABLE"
|
||||
| "XRAY_UNSUPPORTED_OS"
|
||||
@@ -89,6 +108,27 @@ export type BackendErrorCode =
|
||||
| "CLOUD_REQUEST_FAILED"
|
||||
| "REMOTE_RATE_LIMITED"
|
||||
| "REMOTE_NO_CAPACITY"
|
||||
// The deployment has no fleet credential at all, which is not the same as a
|
||||
// busy fleet — telling the two apart is the whole reason it is coded.
|
||||
| "REMOTE_NOT_CONFIGURED"
|
||||
// The launch was refused for a reason the user cannot wait out (a bad
|
||||
// request, a profile that will not run). `params.detail` carries the
|
||||
// server's own words.
|
||||
| "REMOTE_LAUNCH_REFUSED"
|
||||
// The fleet never answered a launch (timeout or connection failure), even on
|
||||
// the retry that de-duplicates on the idempotency key. Nothing was refused;
|
||||
// the user can only try again.
|
||||
| "REMOTE_FLEET_UNREACHABLE"
|
||||
// Already at the account's concurrent-session ceiling. `params.limit`/`live`.
|
||||
| "REMOTE_CONCURRENCY_LIMIT"
|
||||
// Asked to drive a session that has not reached `live` yet.
|
||||
| "REMOTE_SESSION_NOT_DRIVABLE"
|
||||
// The profile's OS is not one a leased host serves (e.g. an android
|
||||
// fingerprint). `params.platform` names it.
|
||||
| "REMOTE_PLATFORM_UNSUPPORTED"
|
||||
// Sync is on but no upload has ever completed, so a remote host would pull an
|
||||
// empty profile and overwrite the real one. Refused before any lease.
|
||||
| "REMOTE_PROFILE_NOT_SYNCED"
|
||||
| "REMOTE_NOT_ENTITLED"
|
||||
| "REMOTE_INTERACTIVE_NOT_ENTITLED"
|
||||
// The profile's exit only resolves on this computer, so a leased host cannot
|
||||
@@ -96,6 +136,11 @@ export type BackendErrorCode =
|
||||
// name different features, and a user told their "Cookie Bot" needs a public
|
||||
// proxy while they were opening a browser by hand cannot act on that.
|
||||
| "REMOTE_REQUIRES_REMOTE_EXIT_NODE"
|
||||
// The exit's PROTOCOL is the problem, not its address. A VLESS server is as
|
||||
// publicly routable as any other, so the reachability check passes and the
|
||||
// sentence above sends the user to fix the one part of their config that was
|
||||
// already right. `params.kind` names the protocol.
|
||||
| "REMOTE_PROXY_KIND_UNSUPPORTED"
|
||||
| "REMOTE_SESSION_REFUSED"
|
||||
| "REMOTE_SESSION_NOT_FOUND"
|
||||
| "REMOTE_SESSION_CONFLICT"
|
||||
@@ -126,13 +171,34 @@ export type BackendErrorCode =
|
||||
// "attach a proxy" is unactionable advice for someone whose proxy is plainly
|
||||
// attached.
|
||||
| "COOKIE_BOT_REQUIRES_REMOTE_EXIT_NODE"
|
||||
// The server's own names for two refusals it throws from `putSchedule`,
|
||||
// `updateProfileState` and `runNow`. `COOKIE_BOT_REQUIRES_PROXY` is the
|
||||
// ...and its twin for an exit whose PROTOCOL no host can speak. Kept apart
|
||||
// from the address refusal because a VLESS server is publicly routable: the
|
||||
// user is not being asked for a different address, they are being asked for a
|
||||
// different kind of exit. `params.kind` names it.
|
||||
| "COOKIE_BOT_PROXY_KIND_UNSUPPORTED"
|
||||
// The server's own names for two refusals the schedule, profile-state and
|
||||
// run-now routes can return. `COOKIE_BOT_REQUIRES_PROXY` is the
|
||||
// server-side twin of the local `COOKIE_BOT_REQUIRES_EXIT_NODE` precondition;
|
||||
// without a case here the single most important refusal in the feature
|
||||
// rendered as the raw machine identifier.
|
||||
| "COOKIE_BOT_REQUIRES_PROXY"
|
||||
| "COOKIE_BOT_TOUCH_FINGERPRINT_UNSUPPORTED"
|
||||
// Agent runs. The first ten are the server's own refusals; the last two are
|
||||
// how a bodyless status on a recipe route is classified client-side, because
|
||||
// "that run does not exist" is the wrong sentence to show someone editing a
|
||||
// saved goal.
|
||||
| "AGENT_NOT_ENTITLED"
|
||||
| "AGENT_NOT_CONFIGURED"
|
||||
| "AGENT_TARGET_OFFLINE"
|
||||
| "AGENT_BUDGET_EXCEEDED"
|
||||
| "AGENT_RUN_LIMIT_REACHED"
|
||||
| "AGENT_RUN_NOT_FOUND"
|
||||
| "AGENT_RUN_NOT_CANCELLABLE"
|
||||
| "AGENT_GOAL_INVALID"
|
||||
| "AGENT_BUDGET_INVALID"
|
||||
| "AGENT_TOKEN_PROFILE_MISMATCH"
|
||||
| "AGENT_RECIPE_INVALID"
|
||||
| "AGENT_RECIPE_NOT_FOUND"
|
||||
| "FINGERPRINT_EXIT_MISMATCH"
|
||||
// The launch refuses instead of opening a window on an unmanaged device: a
|
||||
// silent fallback would leave the user browsing a random fingerprint while
|
||||
@@ -140,20 +206,56 @@ export type BackendErrorCode =
|
||||
// can have. `detail` carries the underlying browser error for support.
|
||||
| "WAYFERN_FINGERPRINT_APPLY_FAILED"
|
||||
| "WAYFERN_FINGERPRINT_GENERATION_FAILED"
|
||||
// Its own code rather than a generation failure: the browser's quota block is
|
||||
// account-wide and lasts 24 hours, so "try again" is wrong advice, and a user
|
||||
// whose every profile refuses at once has to be told this is one limit and
|
||||
// not a broken install.
|
||||
// Its own code rather than a generation failure: the block applies to the
|
||||
// whole account rather than one profile, so "try again" is wrong advice, and
|
||||
// a user whose every profile refuses at once has to be told this is one
|
||||
// limit and not a broken install.
|
||||
| "WAYFERN_GENERATION_LIMIT_REACHED"
|
||||
// A cross-OS claim needs a signed plan token, so an expired or offline
|
||||
// session cannot apply one. Distinct from the generic apply failure because
|
||||
// A cross-OS claim needs an active signed-in session, so an expired or
|
||||
// offline one cannot apply it. Distinct from the generic apply failure because
|
||||
// signing in again is the fix; `detail` names the claimed OS.
|
||||
| "WAYFERN_CROSS_OS_REQUIRES_PLAN"
|
||||
| "WAYFERN_IDENTITY_REFUSED"
|
||||
| "PROFILE_EXPORT_FAILED"
|
||||
| "PROFILE_EXPORT_TOO_LARGE"
|
||||
| "PROFILE_IMPORT_FAILED"
|
||||
| "PROFILE_IMPORT_TOO_NEW"
|
||||
| "PROFILE_IMPORT_UNSAFE_ARCHIVE"
|
||||
| "RECORDING_ALREADY_RUNNING"
|
||||
| "PROFILE_NOT_RUNNING"
|
||||
| "WAYFERN_152_REQUIRED"
|
||||
| "RECORDING_FAILED"
|
||||
| "LAUNCH_CONSENT_EXPIRED"
|
||||
| "VPN_WORKER_START_FAILED"
|
||||
| "EXIT_PROBE_FAILED"
|
||||
| "CAMOUFOX_REMOVED"
|
||||
| "NO_E2E_PASSWORD_SET"
|
||||
| "TRASH_ENTRY_NOT_FOUND"
|
||||
| "TRASH_RESTORE_CONFLICT"
|
||||
// Moving the data directory. Every refusal is its own code because every one
|
||||
// of them has a different fix: close the browsers, wait for the sync, pick
|
||||
// somewhere else, free some space.
|
||||
| "DATA_ROOT_SAME_AS_CURRENT"
|
||||
| "DATA_ROOT_DESTINATION_INSIDE_SOURCE"
|
||||
| "DATA_ROOT_BROWSER_RUNNING"
|
||||
| "DATA_ROOT_SYNC_IN_PROGRESS"
|
||||
// `params.required` / `params.available`, both in bytes as strings.
|
||||
| "DATA_ROOT_INSUFFICIENT_SPACE"
|
||||
| "DATA_ROOT_DESTINATION_NOT_WRITABLE"
|
||||
| "DATA_ROOT_DESTINATION_NOT_EMPTY"
|
||||
| "DATA_ROOT_MOVE_IN_PROGRESS"
|
||||
| "DATA_ROOT_COPY_FAILED"
|
||||
// The copy did not match the source, so nothing was deleted. Its own code
|
||||
// rather than a copy failure: the user's data is still where it was, and
|
||||
// saying so is the whole point of verifying before deleting.
|
||||
| "DATA_ROOT_VERIFY_FAILED"
|
||||
// Synchronised windows.
|
||||
| "SYNC_SESSION_NOT_FOUND"
|
||||
| "SYNC_FOLLOWER_NOT_FOUND"
|
||||
| "SYNC_SESSION_UNAVAILABLE"
|
||||
| "SYNC_DISPLAY_UNAVAILABLE"
|
||||
| "SYNC_DISPLAY_TOO_SMALL"
|
||||
| "SYNC_ARRANGE_FAILED"
|
||||
| "INTERNAL_ERROR";
|
||||
|
||||
export interface BackendError {
|
||||
@@ -188,6 +290,25 @@ export function parseBackendError(err: unknown): BackendError | null {
|
||||
* Translate a backend error to a localized string. Falls back to the raw
|
||||
* message if the error isn't a structured backend error.
|
||||
*/
|
||||
/**
|
||||
* A leased-host operating system as a person reads it.
|
||||
*
|
||||
* macOS / Windows / Linux are proper nouns, the same in every locale, so they
|
||||
* are not translated — only mapped from the wire value the fleet uses.
|
||||
*/
|
||||
function remoteOsLabel(platform: string): string {
|
||||
switch (platform) {
|
||||
case "macos":
|
||||
return "macOS";
|
||||
case "windows":
|
||||
return "Windows";
|
||||
case "linux":
|
||||
return "Linux";
|
||||
default:
|
||||
return platform;
|
||||
}
|
||||
}
|
||||
|
||||
export function translateBackendError(t: TFunction, err: unknown): string {
|
||||
const parsed = parseBackendError(err);
|
||||
if (!parsed) {
|
||||
@@ -208,8 +329,19 @@ export function translateBackendError(t: TFunction, err: unknown): string {
|
||||
return t("backendErrors.profileNotProtected");
|
||||
case "PROFILE_ALREADY_PROTECTED":
|
||||
return t("backendErrors.profileAlreadyProtected");
|
||||
case "TOOL_IS_LOCAL_ONLY":
|
||||
return t("backendErrors.toolIsLocalOnly");
|
||||
case "TYPING_TOO_LONG":
|
||||
return t("backendErrors.typingTooLong", {
|
||||
seconds: parsed.params?.seconds ?? "",
|
||||
limit: parsed.params?.limit ?? "",
|
||||
});
|
||||
case "URL_SCHEME_NOT_ALLOWED":
|
||||
return t("backendErrors.urlSchemeNotAllowed");
|
||||
case "PROFILE_RUNNING":
|
||||
return t("backendErrors.profileRunning");
|
||||
case "PROFILE_PAIRED_TWICE":
|
||||
return t("backendErrors.profilePairedTwice");
|
||||
case "PROFILE_EPHEMERAL":
|
||||
return t("backendErrors.profileEphemeral");
|
||||
case "PROFILE_MISSING_SALT":
|
||||
@@ -275,6 +407,14 @@ export function translateBackendError(t: TFunction, err: unknown): string {
|
||||
return t("backendErrors.extensionLinkRequiresDirectory");
|
||||
case "EXTENSION_LINKED_CANNOT_SYNC":
|
||||
return t("backendErrors.extensionLinkedCannotSync");
|
||||
case "EXTENSION_URL_INVALID":
|
||||
return t("backendErrors.extensionUrlInvalid");
|
||||
case "EXTENSION_DOWNLOAD_FAILED":
|
||||
return t("backendErrors.extensionDownloadFailed");
|
||||
case "EXTENSION_NOT_AN_EXTENSION":
|
||||
return t("backendErrors.extensionNotAnExtension");
|
||||
case "EXTENSION_TOO_LARGE":
|
||||
return t("backendErrors.extensionTooLarge");
|
||||
case "CANNOT_MODIFY_CLOUD_MANAGED_PROXY":
|
||||
return t("backendErrors.cannotModifyCloudManagedProxy");
|
||||
case "SYNC_LOCKED_BY_PROFILE":
|
||||
@@ -287,6 +427,10 @@ export function translateBackendError(t: TFunction, err: unknown): string {
|
||||
return t("backendErrors.proxyNotWorking");
|
||||
case "PROXY_PAYMENT_REQUIRED":
|
||||
return t("backendErrors.proxyPaymentRequired");
|
||||
case "PROXY_TLS_HANDSHAKE_FAILED":
|
||||
return t("backendErrors.proxyTlsHandshakeFailed", {
|
||||
proxy: parsed.params?.proxy ?? "",
|
||||
});
|
||||
case "VPN_NOT_WORKING":
|
||||
return t("backendErrors.vpnNotWorking");
|
||||
case "CAMOUFOX_IMPORT_DEPRECATED":
|
||||
@@ -369,6 +513,24 @@ export function translateBackendError(t: TFunction, err: unknown): string {
|
||||
return t("backendErrors.mcpPortUnavailable");
|
||||
case "MCP_CONFIGURATION_UNAVAILABLE":
|
||||
return t("backendErrors.mcpConfigurationUnavailable");
|
||||
case "MCP_REMOTE_REQUIRES_SIGN_IN":
|
||||
return t("backendErrors.mcpRemoteRequiresSignIn");
|
||||
case "MCP_REMOTE_UNAUTHORIZED":
|
||||
return t("backendErrors.mcpRemoteUnauthorized");
|
||||
case "MCP_REMOTE_SLOT_TAKEN":
|
||||
return t("backendErrors.mcpRemoteSlotTaken");
|
||||
case "MCP_REMOTE_NOT_ENTITLED":
|
||||
return t("backendErrors.mcpRemoteNotEntitled");
|
||||
case "MCP_REMOTE_UNREACHABLE":
|
||||
return t("backendErrors.mcpRemoteUnreachable");
|
||||
case "MCP_REMOTE_KEY_MISSING":
|
||||
return t("backendErrors.mcpRemoteKeyMissing");
|
||||
case "MCP_REMOTE_KEY_LIMIT":
|
||||
return t("backendErrors.mcpRemoteKeyLimit");
|
||||
case "MCP_REMOTE_KEY_UNAVAILABLE":
|
||||
return t("backendErrors.mcpRemoteKeyUnavailable");
|
||||
case "MCP_LOCAL_REMOVED":
|
||||
return t("backendErrors.mcpLocalRemoved");
|
||||
case "MCP_AGENT_UNKNOWN":
|
||||
return t("backendErrors.mcpAgentUnknown");
|
||||
case "MCP_AGENT_INSTALL_FAILED":
|
||||
@@ -418,8 +580,41 @@ export function translateBackendError(t: TFunction, err: unknown): string {
|
||||
return t("backendErrors.cloudRequestFailed");
|
||||
case "REMOTE_RATE_LIMITED":
|
||||
return t("backendErrors.remoteRateLimited");
|
||||
case "REMOTE_NO_CAPACITY":
|
||||
return t("backendErrors.remoteNoCapacity");
|
||||
case "REMOTE_NO_CAPACITY": {
|
||||
// Newer backends name the platform; older ones (and a bare 503 mapped by
|
||||
// status alone) do not, so fall back to the platform-free line.
|
||||
const platform = parsed.params?.platform;
|
||||
return platform
|
||||
? t("backendErrors.remoteNoCapacityPlatform", {
|
||||
platform: remoteOsLabel(platform),
|
||||
})
|
||||
: t("backendErrors.remoteNoCapacity");
|
||||
}
|
||||
case "REMOTE_NOT_CONFIGURED":
|
||||
return t("backendErrors.remoteNotConfigured");
|
||||
case "REMOTE_LAUNCH_REFUSED": {
|
||||
// The server's own words, when it gave any. Kept as a diagnostic; the
|
||||
// generic line stands alone when it did not.
|
||||
const detail = parsed.params?.detail?.trim();
|
||||
return detail
|
||||
? t("backendErrors.remoteLaunchRefusedDetail", { detail })
|
||||
: t("backendErrors.remoteLaunchRefused");
|
||||
}
|
||||
case "REMOTE_FLEET_UNREACHABLE":
|
||||
return t("backendErrors.remoteFleetUnreachable");
|
||||
case "REMOTE_CONCURRENCY_LIMIT":
|
||||
return t("backendErrors.remoteConcurrencyLimit", {
|
||||
live: parsed.params?.live ?? "",
|
||||
limit: parsed.params?.limit ?? "",
|
||||
});
|
||||
case "REMOTE_SESSION_NOT_DRIVABLE":
|
||||
return t("backendErrors.remoteSessionNotDrivable");
|
||||
case "REMOTE_PLATFORM_UNSUPPORTED":
|
||||
return t("backendErrors.remotePlatformUnsupported", {
|
||||
platform: remoteOsLabel(parsed.params?.platform ?? ""),
|
||||
});
|
||||
case "REMOTE_PROFILE_NOT_SYNCED":
|
||||
return t("backendErrors.remoteProfileNotSynced");
|
||||
case "REMOTE_NOT_ENTITLED":
|
||||
return t("backendErrors.remoteNotEntitled");
|
||||
// Distinct from the above: the plan HAS remote hours, it just may not spend
|
||||
@@ -430,6 +625,10 @@ export function translateBackendError(t: TFunction, err: unknown): string {
|
||||
return t("backendErrors.remoteInteractiveNotEntitled");
|
||||
case "REMOTE_REQUIRES_REMOTE_EXIT_NODE":
|
||||
return t("backendErrors.remoteRequiresRemoteExitNode");
|
||||
case "REMOTE_PROXY_KIND_UNSUPPORTED":
|
||||
return t("backendErrors.remoteProxyKindUnsupported", {
|
||||
kind: parsed.params?.kind ?? "",
|
||||
});
|
||||
case "REMOTE_SESSION_REFUSED":
|
||||
return t("backendErrors.remoteSessionRefused");
|
||||
case "REMOTE_SESSION_NOT_FOUND":
|
||||
@@ -504,8 +703,38 @@ export function translateBackendError(t: TFunction, err: unknown): string {
|
||||
return t("backendErrors.cookieBotRequiresExitNode");
|
||||
case "COOKIE_BOT_REQUIRES_REMOTE_EXIT_NODE":
|
||||
return t("backendErrors.cookieBotRequiresRemoteExitNode");
|
||||
case "COOKIE_BOT_PROXY_KIND_UNSUPPORTED":
|
||||
return t("backendErrors.cookieBotProxyKindUnsupported", {
|
||||
kind: parsed.params?.kind ?? "",
|
||||
});
|
||||
case "COOKIE_BOT_TOUCH_FINGERPRINT_UNSUPPORTED":
|
||||
return t("backendErrors.cookieBotTouchFingerprintUnsupported");
|
||||
case "AGENT_NOT_ENTITLED":
|
||||
return t("backendErrors.agentNotEntitled");
|
||||
case "AGENT_NOT_CONFIGURED":
|
||||
return t("backendErrors.agentNotConfigured");
|
||||
case "AGENT_TARGET_OFFLINE":
|
||||
return t("backendErrors.agentTargetOffline");
|
||||
case "AGENT_BUDGET_EXCEEDED":
|
||||
return t("backendErrors.agentBudgetExceeded");
|
||||
case "AGENT_RUN_LIMIT_REACHED":
|
||||
return t("backendErrors.agentRunLimitReached");
|
||||
case "AGENT_RUN_NOT_FOUND":
|
||||
return t("backendErrors.agentRunNotFound");
|
||||
case "AGENT_RUN_NOT_CANCELLABLE":
|
||||
return t("backendErrors.agentRunNotCancellable");
|
||||
case "AGENT_GOAL_INVALID":
|
||||
return t("backendErrors.agentGoalInvalid");
|
||||
case "AGENT_BUDGET_INVALID":
|
||||
return t("backendErrors.agentBudgetInvalid");
|
||||
// The run was started against a profile the issued token does not cover.
|
||||
// Its own code because signing in again is the fix, not editing the goal.
|
||||
case "AGENT_TOKEN_PROFILE_MISMATCH":
|
||||
return t("backendErrors.agentTokenProfileMismatch");
|
||||
case "AGENT_RECIPE_INVALID":
|
||||
return t("backendErrors.agentRecipeInvalid");
|
||||
case "AGENT_RECIPE_NOT_FOUND":
|
||||
return t("backendErrors.agentRecipeNotFound");
|
||||
// The launch gate's block. The dialog renders the mismatch detail from
|
||||
// `params` itself; this string is the fallback for anywhere that only has
|
||||
// room for one sentence.
|
||||
@@ -525,6 +754,34 @@ export function translateBackendError(t: TFunction, err: unknown): string {
|
||||
return t("backendErrors.wayfernCrossOsRequiresPlan", {
|
||||
detail: parsed.params?.detail ?? "",
|
||||
});
|
||||
case "WAYFERN_IDENTITY_REFUSED":
|
||||
return t("backendErrors.wayfernIdentityRefused", {
|
||||
detail: parsed.params?.detail ?? "",
|
||||
});
|
||||
case "PROFILE_EXPORT_FAILED":
|
||||
return t("backendErrors.profileExportFailed", {
|
||||
detail: parsed.params?.detail ?? "",
|
||||
});
|
||||
case "PROFILE_EXPORT_TOO_LARGE":
|
||||
return t("backendErrors.profileExportTooLarge");
|
||||
case "PROFILE_IMPORT_FAILED":
|
||||
return t("backendErrors.profileImportFailed", {
|
||||
detail: parsed.params?.detail ?? "",
|
||||
});
|
||||
case "PROFILE_IMPORT_TOO_NEW":
|
||||
return t("backendErrors.profileImportTooNew");
|
||||
case "PROFILE_IMPORT_UNSAFE_ARCHIVE":
|
||||
return t("backendErrors.profileImportUnsafeArchive");
|
||||
case "RECORDING_ALREADY_RUNNING":
|
||||
return t("backendErrors.recordingAlreadyRunning");
|
||||
case "PROFILE_NOT_RUNNING":
|
||||
return t("backendErrors.profileNotRunning");
|
||||
case "WAYFERN_152_REQUIRED":
|
||||
return t("backendErrors.wayfern152Required");
|
||||
case "RECORDING_FAILED":
|
||||
return t("backendErrors.recordingFailed", {
|
||||
detail: parsed.params?.detail ?? "",
|
||||
});
|
||||
case "LAUNCH_CONSENT_EXPIRED":
|
||||
return t("backendErrors.launchConsentExpired");
|
||||
case "VPN_WORKER_START_FAILED":
|
||||
@@ -537,6 +794,52 @@ export function translateBackendError(t: TFunction, err: unknown): string {
|
||||
return t("backendErrors.camoufoxRemoved");
|
||||
case "NO_E2E_PASSWORD_SET":
|
||||
return t("backendErrors.noE2ePasswordSet");
|
||||
case "TRASH_ENTRY_NOT_FOUND":
|
||||
return t("backendErrors.trashEntryNotFound");
|
||||
case "TRASH_RESTORE_CONFLICT":
|
||||
return t("backendErrors.trashRestoreConflict");
|
||||
case "DATA_ROOT_SAME_AS_CURRENT":
|
||||
return t("backendErrors.dataRootSameAsCurrent");
|
||||
case "DATA_ROOT_DESTINATION_INSIDE_SOURCE":
|
||||
return t("backendErrors.dataRootDestinationInsideSource");
|
||||
case "DATA_ROOT_BROWSER_RUNNING":
|
||||
return t("backendErrors.dataRootBrowserRunning");
|
||||
case "DATA_ROOT_SYNC_IN_PROGRESS":
|
||||
return t("backendErrors.dataRootSyncInProgress");
|
||||
// The figures arrive already written out. This module is imported by a
|
||||
// plain `node --test` run, so it stays free of project imports, and the
|
||||
// one place that knows the byte counts formats them.
|
||||
case "DATA_ROOT_INSUFFICIENT_SPACE":
|
||||
return t("backendErrors.dataRootInsufficientSpace", {
|
||||
required: parsed.params?.required ?? "",
|
||||
available: parsed.params?.available ?? "",
|
||||
});
|
||||
case "DATA_ROOT_DESTINATION_NOT_WRITABLE":
|
||||
return t("backendErrors.dataRootDestinationNotWritable");
|
||||
case "DATA_ROOT_DESTINATION_NOT_EMPTY":
|
||||
return t("backendErrors.dataRootDestinationNotEmpty");
|
||||
case "DATA_ROOT_MOVE_IN_PROGRESS":
|
||||
return t("backendErrors.dataRootMoveInProgress");
|
||||
case "DATA_ROOT_COPY_FAILED":
|
||||
return t("backendErrors.dataRootCopyFailed", {
|
||||
detail: parsed.params?.detail ?? "",
|
||||
});
|
||||
case "DATA_ROOT_VERIFY_FAILED":
|
||||
return t("backendErrors.dataRootVerifyFailed");
|
||||
case "SYNC_SESSION_NOT_FOUND":
|
||||
return t("backendErrors.syncSessionNotFound");
|
||||
case "SYNC_FOLLOWER_NOT_FOUND":
|
||||
return t("backendErrors.syncFollowerNotFound");
|
||||
case "SYNC_SESSION_UNAVAILABLE":
|
||||
return t("backendErrors.syncSessionUnavailable");
|
||||
case "SYNC_DISPLAY_UNAVAILABLE":
|
||||
return t("backendErrors.syncDisplayUnavailable");
|
||||
case "SYNC_DISPLAY_TOO_SMALL":
|
||||
return t("backendErrors.syncDisplayTooSmall", {
|
||||
windows: Number(parsed.params?.count ?? 0),
|
||||
});
|
||||
case "SYNC_ARRANGE_FAILED":
|
||||
return t("backendErrors.syncArrangeFailed");
|
||||
case "INTERNAL_ERROR":
|
||||
return t("backendErrors.internal", {
|
||||
detail: parsed.params?.detail ?? "",
|
||||
|
||||
Reference in new issue
Block a user