diff --git a/packages/plugin-runtime-types/src/plugins/Context.ts b/packages/plugin-runtime-types/src/plugins/Context.ts index 6d298b9d..59ff080d 100644 --- a/packages/plugin-runtime-types/src/plugins/Context.ts +++ b/packages/plugin-runtime-types/src/plugins/Context.ts @@ -1,27 +1,27 @@ import type { - FindHttpResponsesRequest, - FindHttpResponsesResponse, - GetCookieValueRequest, - GetCookieValueResponse, - GetHttpRequestByIdRequest, - GetHttpRequestByIdResponse, - ListCookieNamesResponse, - ListFoldersRequest, - ListFoldersResponse, - ListHttpRequestsRequest, - ListHttpRequestsResponse, - OpenWindowRequest, - PromptTextRequest, - PromptTextResponse, - RenderGrpcRequestRequest, - RenderGrpcRequestResponse, - RenderHttpRequestRequest, - RenderHttpRequestResponse, - SendHttpRequestRequest, - SendHttpRequestResponse, - ShowToastRequest, - TemplateRenderRequest, - WorkspaceInfo, + FindHttpResponsesRequest, + FindHttpResponsesResponse, + GetCookieValueRequest, + GetCookieValueResponse, + GetHttpRequestByIdRequest, + GetHttpRequestByIdResponse, + ListCookieNamesResponse, + ListFoldersRequest, + ListFoldersResponse, + ListHttpRequestsRequest, + ListHttpRequestsResponse, + OpenWindowRequest, + PromptTextRequest, + PromptTextResponse, + RenderGrpcRequestRequest, + RenderGrpcRequestResponse, + RenderHttpRequestRequest, + RenderHttpRequestResponse, + SendHttpRequestRequest, + SendHttpRequestResponse, + ShowToastRequest, + TemplateRenderRequest, + WorkspaceInfo, } from '../bindings/gen_events.ts'; import type { HttpRequest } from '../bindings/gen_models.ts'; import type { JsonValue } from '../bindings/serde_json/JsonValue'; diff --git a/packages/plugin-runtime-types/src/plugins/WebsocketRequestActionPlugin.ts b/packages/plugin-runtime-types/src/plugins/WebsocketRequestActionPlugin.ts index 22dc2791..da566744 100644 --- a/packages/plugin-runtime-types/src/plugins/WebsocketRequestActionPlugin.ts +++ b/packages/plugin-runtime-types/src/plugins/WebsocketRequestActionPlugin.ts @@ -1,4 +1,7 @@ -import type { CallWebsocketRequestActionArgs, WebsocketRequestAction } from '../bindings/gen_events'; +import type { + CallWebsocketRequestActionArgs, + WebsocketRequestAction, +} from '../bindings/gen_events'; import type { Context } from './Context'; export type WebsocketRequestActionPlugin = WebsocketRequestAction & { diff --git a/packages/plugin-runtime-types/tsconfig.json b/packages/plugin-runtime-types/tsconfig.json index 8cd44efd..9e49c5e4 100644 --- a/packages/plugin-runtime-types/tsconfig.json +++ b/packages/plugin-runtime-types/tsconfig.json @@ -2,19 +2,12 @@ "compilerOptions": { "module": "node16", "target": "es6", - "lib": [ - "es2021", - "dom" - ], + "lib": ["es2021", "dom"], "declaration": true, "declarationDir": "./lib", "outDir": "./lib", "strict": true, - "types": [ - "node" - ] + "types": ["node"] }, - "files": [ - "src/index.ts" - ] + "files": ["src/index.ts"] } diff --git a/packages/plugin-runtime/tsconfig.json b/packages/plugin-runtime/tsconfig.json index 88d9a9c0..845d46fa 100644 --- a/packages/plugin-runtime/tsconfig.json +++ b/packages/plugin-runtime/tsconfig.json @@ -13,13 +13,8 @@ "outDir": "build", "baseUrl": ".", "paths": { - "*": [ - "node_modules/*", - "src/types/*" - ] + "*": ["node_modules/*", "src/types/*"] } }, - "include": [ - "src" - ] + "include": ["src"] } diff --git a/src-tauri/yaak-git/src/push.rs b/src-tauri/yaak-git/src/push.rs index 1a9f4fcd..622c9c6b 100644 --- a/src-tauri/yaak-git/src/push.rs +++ b/src-tauri/yaak-git/src/push.rs @@ -33,26 +33,48 @@ pub(crate) fn git_push(dir: &Path) -> Result { let stdout = String::from_utf8_lossy(&out.stdout); let stderr = String::from_utf8_lossy(&out.stderr); let combined = stdout + stderr; + let combined_lower = combined.to_lowercase(); info!("Pushed to repo status={} {combined}", out.status); - if combined.to_lowercase().contains("could not read") { - return Ok(PushResult::NeedsCredentials { url: remote_url.to_string(), error: None }); - } - - if combined.to_lowercase().contains("unable to access") { - return Ok(PushResult::NeedsCredentials { - url: remote_url.to_string(), - error: Some(combined.to_string()), - }); - } - - if combined.to_lowercase().contains("up-to-date") { - return Ok(PushResult::UpToDate); + // Helper to check if this is a credentials error + let is_credentials_error = || { + combined_lower.contains("could not read") + || combined_lower.contains("unable to access") + || combined_lower.contains("authentication failed") + }; + + // Check for explicit rejection indicators first (e.g., protected branch rejections) + // These can occur even if some git servers don't properly set exit codes + if combined_lower.contains("rejected") || combined_lower.contains("failed to push") { + if is_credentials_error() { + return Ok(PushResult::NeedsCredentials { + url: remote_url.to_string(), + error: Some(combined.to_string()), + }); + } + return Err(GenericError(format!("Failed to push: {combined}"))); } + // Check exit status for any other failures if !out.status.success() { - return Err(GenericError(format!("Failed to push {combined}"))); + if combined_lower.contains("could not read") { + return Ok(PushResult::NeedsCredentials { url: remote_url.to_string(), error: None }); + } + if combined_lower.contains("unable to access") + || combined_lower.contains("authentication failed") + { + return Ok(PushResult::NeedsCredentials { + url: remote_url.to_string(), + error: Some(combined.to_string()), + }); + } + return Err(GenericError(format!("Failed to push: {combined}"))); + } + + // Success cases (exit code 0 and no rejection indicators) + if combined_lower.contains("up-to-date") { + return Ok(PushResult::UpToDate); } Ok(PushResult::Success { message: format!("Pushed to {}/{}", remote_name, branch_name) }) diff --git a/src-web/components/CreateWorkspaceDialog.tsx b/src-web/components/CreateWorkspaceDialog.tsx index 54c1de34..0076412d 100644 --- a/src-web/components/CreateWorkspaceDialog.tsx +++ b/src-web/components/CreateWorkspaceDialog.tsx @@ -51,7 +51,11 @@ export function CreateWorkspaceDialog({ hide }: Props) { gitMutations(syncConfig.filePath, gitCallbacks(syncConfig.filePath)) .init.mutateAsync() .catch((err) => { - showErrorToast('git-init-error', String(err)); + showErrorToast({ + id: 'git-init-error', + title: 'Error initializing Git', + message: String(err), + }); }); } diff --git a/src-web/components/core/Toast.tsx b/src-web/components/core/Toast.tsx index 9076e853..acd750ab 100644 --- a/src-web/components/core/Toast.tsx +++ b/src-web/components/core/Toast.tsx @@ -58,12 +58,11 @@ export function Toast({ children, open, onClose, timeout, action, icon, color }: 'pointer-events-auto overflow-hidden', 'relative pointer-events-auto bg-surface text-text rounded-lg', 'border border-border shadow-lg w-[25rem]', - 'grid grid-cols-[1fr_auto]', )} > -
- {toastIcon && } - +
+ {toastIcon && } +
{children}
{action?.({ hide: onClose })}
@@ -72,7 +71,7 @@ export function Toast({ children, open, onClose, timeout, action, icon, color }: { - showErrorToast('git-branch-error', String(err)); + showErrorToast({ + id: 'git-branch-error', + title: 'Error creating branch', + message: String(err), + }); }, }, ); @@ -163,6 +173,7 @@ function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) { await mergeBranch.mutateAsync( { branch, force: false }, { + disableToastError: true, onSettled: hide, onSuccess() { showToast({ @@ -177,7 +188,11 @@ function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) { sync({ force: true }); }, onError(err) { - showErrorToast('git-merged-branch-error', String(err)); + showErrorToast({ + id: 'git-merged-branch-error', + title: 'Error merging branch', + message: String(err), + }); }, }, ); @@ -208,8 +223,13 @@ function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) { await deleteBranch.mutateAsync( { branch: currentBranch }, { + disableToastError: true, onError(err) { - showErrorToast('git-delete-branch-error', String(err)); + showErrorToast({ + id: 'git-delete-branch-error', + title: 'Error deleting branch', + message: String(err), + }); }, async onSuccess() { await sync({ force: true }); @@ -226,9 +246,14 @@ function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) { waitForOnSelect: true, async onSelect() { await push.mutateAsync(undefined, { + disableToastError: true, onSuccess: handlePullResult, onError(err) { - showErrorToast('git-pull-error', String(err)); + showErrorToast({ + id: 'git-push-error', + title: 'Error pushing changes', + message: String(err), + }); }, }); }, @@ -240,9 +265,14 @@ function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) { waitForOnSelect: true, async onSelect() { await pull.mutateAsync(undefined, { + disableToastError: true, onSuccess: handlePullResult, onError(err) { - showErrorToast('git-pull-error', String(err)); + showErrorToast({ + id: 'git-pull-error', + title: 'Error pulling changes', + message: String(err), + }); }, }); }, diff --git a/src-web/hooks/useHttpAuthentication.ts b/src-web/hooks/useHttpAuthentication.ts index 7f6e10ef..0a4e5dd6 100644 --- a/src-web/hooks/useHttpAuthentication.ts +++ b/src-web/hooks/useHttpAuthentication.ts @@ -38,7 +38,11 @@ export function useSubscribeHttpAuthentication() { jotaiStore.set(httpAuthenticationSummariesAtom, result); return result; } catch (err) { - showErrorToast('http-authentication-error', err); + showErrorToast({ + id: 'http-authentication-error', + title: 'HTTP Authentication Error', + message: err, + }); } }, }); diff --git a/src-web/lib/toast.ts b/src-web/lib/toast.tsx similarity index 79% rename from src-web/lib/toast.ts rename to src-web/lib/toast.tsx index 2ed5d046..26061f10 100644 --- a/src-web/lib/toast.ts +++ b/src-web/lib/toast.tsx @@ -45,11 +45,24 @@ export function hideToast(toHide: ToastInstance) { }); } -export function showErrorToast(id: string, message: T) { +export function showErrorToast({ + id, + title, + message, +}: { + id: string; + title: string; + message: T; +}) { return showToast({ id, - message: String(message), - timeout: 8000, color: 'danger', + timeout: null, + message: ( +
+

{title}

+
{String(message)}
+
+ ), }); }