Files
PushGo/src/main/errors.ts

168 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { AppErrorPayload, ErrorCode } from "../shared/contracts";
type ErrorDefinition = {
message: string;
actionText?: string;
actionType?: string;
};
const ERROR_MAP: Record<ErrorCode, ErrorDefinition> = {
APP_GIT_NOT_FOUND: {
message: "未检测到 Git请先安装后再继续",
actionText: "去安装 Git",
actionType: "open_git_download"
},
APP_GIT_HELPER_MISSING: {
message: "已安装 Git但未检测到可用凭据助手首次授权窗口可能无法弹出",
actionText: "安装凭据助手",
actionType: "open_gcm_download"
},
APP_GIT_HELPER_UNSUPPORTED: {
message: "当前 Git 凭据助手不支持授权弹窗,请切换到 Git Credential Manager",
actionText: "查看配置说明",
actionType: "open_gcm_download"
},
APP_FOLDER_INVALID: {
message: "请选择有效的项目文件夹"
},
URL_INVALID_FORMAT: {
message: "仓库地址格式不正确,请检查后重试"
},
URL_PLATFORM_MISMATCH: {
message: "仓库地址与当前平台不一致,是否切换平台?"
},
AUTH_CANCELLED: {
message: "你已取消登录授权,可重新发起"
},
AUTH_FAILED: {
message: "登录失败,请稍后重试"
},
GIT_INIT_FAILED: {
message: "初始化仓库失败,请检查文件夹权限"
},
GIT_COMMIT_NO_CHANGES: {
message: "没有检测到新变更,已尝试直接推送"
},
GIT_REMOTE_SET_FAILED: {
message: "设置远端仓库失败,请检查仓库地址"
},
GIT_PUSH_AUTH_FAILED: {
message: "推送失败:账号无权限或授权已失效"
},
GIT_PUSH_REJECTED: {
message: "推送被拒绝,远端可能有更新,请先同步"
},
NETWORK_TIMEOUT: {
message: "网络超时,请检查网络后重试"
},
UNKNOWN: {
message: "发生未知错误,请重试"
}
};
export class AppError extends Error {
readonly payload: AppErrorPayload;
constructor(code: ErrorCode, overrides?: Partial<AppErrorPayload>) {
const base = ERROR_MAP[code];
super(overrides?.message ?? base.message);
this.name = "AppError";
this.payload = {
code,
message: overrides?.message ?? base.message,
actionText: overrides?.actionText ?? base.actionText,
actionType: overrides?.actionType ?? base.actionType
};
}
}
export function createAppError(code: ErrorCode, overrides?: Partial<AppErrorPayload>): AppError {
return new AppError(code, overrides);
}
export function toAppErrorPayload(error: unknown, fallbackCode: ErrorCode = "UNKNOWN"): AppErrorPayload {
if (error instanceof AppError) {
return error.payload;
}
if (isPayload(error)) {
return error;
}
const base = ERROR_MAP[fallbackCode];
return {
code: fallbackCode,
message: base.message,
actionText: base.actionText,
actionType: base.actionType
};
}
function isPayload(error: unknown): error is AppErrorPayload {
return (
typeof error === "object" &&
error !== null &&
"code" in error &&
"message" in error &&
typeof (error as { code: unknown }).code === "string" &&
typeof (error as { message: unknown }).message === "string"
);
}
export function isGitNotFound(output: string): boolean {
const content = output.toLowerCase();
return content.includes("command not found") || content.includes("is not recognized") || content.includes("enoent");
}
export function inferGitPushError(stderr: string): AppError {
const message = stderr.toLowerCase();
if (message.includes("no credential store has been selected") || message.includes("credential.credentialstore")) {
return createAppError("GIT_PUSH_AUTH_FAILED", {
message: "Git Credential Manager 未配置凭据存储。请先配置 credential.credentialStore如 cache 或 secretservice后重试。"
});
}
if (message.includes("can not use the 'cache' credential store on windows")) {
return createAppError("GIT_PUSH_AUTH_FAILED", {
message: "Windows 不支持 cache 凭据存储。请改用 wincredman 后重试。"
});
}
if (message.includes("credential-manager") && message.includes("is not a git command")) {
return createAppError("GIT_PUSH_AUTH_FAILED", {
message: "未找到 Git Credential Manager 可执行程序,请安装并启用后重试。"
});
}
if (
message.includes("user interaction is not allowed") ||
message.includes("cannot prompt because user interactivity has been disabled") ||
message.includes("unable to open browser") ||
message.includes("failed to launch browser")
) {
return createAppError("GIT_PUSH_AUTH_FAILED", {
message: "无法拉起授权窗口。请检查系统默认浏览器与图形会话后重试。"
});
}
if (
message.includes("authentication failed") ||
message.includes("could not read username") ||
message.includes("403") ||
message.includes("access denied")
) {
return createAppError("GIT_PUSH_AUTH_FAILED");
}
if (message.includes("failed to push some refs") || message.includes("non-fast-forward") || message.includes("rejected")) {
return createAppError("GIT_PUSH_REJECTED");
}
if (message.includes("timed out") || message.includes("timeout")) {
return createAppError("NETWORK_TIMEOUT");
}
return createAppError("UNKNOWN");
}