fix: enhance error handling in feature creation process

- Added error handling for feature creation in BoardView component to log errors and display user-friendly messages.
- Updated persistFeatureCreate function to throw errors on failure, allowing for better state management.
- Introduced removal of features from state if server creation fails, improving user experience during conflicts.

Also added @playwright/test to devDependencies in package-lock.json for improved testing capabilities.
This commit is contained in:
gsxdsm
2026-02-15 10:21:39 -08:00
parent a3a5c9e2cb
commit a935229031
4 changed files with 61 additions and 33 deletions

View File

@@ -882,7 +882,15 @@ export function BoardView() {
// Capture existing feature IDs before adding
const featuresBeforeIds = new Set(useAppStore.getState().features.map((f) => f.id));
await handleAddFeature(featureData);
try {
await handleAddFeature(featureData);
} catch (error) {
logger.error('Failed to create PR comments feature:', error);
toast.error('Failed to create feature', {
description: error instanceof Error ? error.message : 'An error occurred',
});
return;
}
// Find the newly created feature by looking for an ID that wasn't in the original set
const latestFeatures = useAppStore.getState().features;
@@ -913,7 +921,7 @@ export function BoardView() {
// Create the feature
const featureData = {
title: `Resolve Merge Conflicts`,
title: `Resolve Merge Conflicts: ${remoteBranch}${worktree.branch}`,
category: 'Maintenance',
description,
images: [],
@@ -930,7 +938,15 @@ export function BoardView() {
// Capture existing feature IDs before adding
const featuresBeforeIds = new Set(useAppStore.getState().features.map((f) => f.id));
await handleAddFeature(featureData);
try {
await handleAddFeature(featureData);
} catch (error) {
logger.error('Failed to create resolve conflicts feature:', error);
toast.error('Failed to create feature', {
description: error instanceof Error ? error.message : 'An error occurred',
});
return;
}
// Find the newly created feature by looking for an ID that wasn't in the original set
const latestFeatures = useAppStore.getState().features;
@@ -972,7 +988,15 @@ export function BoardView() {
// Capture existing feature IDs before adding
const featuresBeforeIds = new Set(useAppStore.getState().features.map((f) => f.id));
await handleAddFeature(featureData);
try {
await handleAddFeature(featureData);
} catch (error) {
logger.error('Failed to create merge conflict resolution feature:', error);
toast.error('Failed to create feature', {
description: error instanceof Error ? error.message : 'An error occurred',
});
return;
}
// Find the newly created feature by looking for an ID that wasn't in the original set
const latestFeatures = useAppStore.getState().features;
@@ -995,7 +1019,15 @@ export function BoardView() {
async (featureData: Parameters<typeof handleAddFeature>[0]) => {
// Capture existing feature IDs before adding
const featuresBeforeIds = new Set(useAppStore.getState().features.map((f) => f.id));
await handleAddFeature(featureData);
try {
await handleAddFeature(featureData);
} catch (error) {
logger.error('Failed to create feature:', error);
toast.error('Failed to create feature', {
description: error instanceof Error ? error.message : 'An error occurred',
});
return;
}
// Find the newly created feature by looking for an ID that wasn't in the original set
const latestFeatures = useAppStore.getState().features;

View File

@@ -225,7 +225,13 @@ export function useBoardActions({
};
const createdFeature = addFeature(newFeatureData);
// Must await to ensure feature exists on server before user can drag it
await persistFeatureCreate(createdFeature);
try {
await persistFeatureCreate(createdFeature);
} catch (error) {
// Remove the feature from state if server creation failed (e.g., duplicate title)
removeFeature(createdFeature.id);
throw error;
}
saveCategory(featureData.category);
// Handle child dependencies - update other features to depend on this new feature
@@ -276,6 +282,7 @@ export function useBoardActions({
},
[
addFeature,
removeFeature,
persistFeatureCreate,
persistFeatureUpdate,
updateFeature,

View File

@@ -75,27 +75,25 @@ export function useBoardPersistence({ currentProject }: UseBoardPersistenceProps
);
// Persist feature creation to API
// Throws on failure so callers can handle it (e.g., remove the feature from state)
const persistFeatureCreate = useCallback(
async (feature: Feature) => {
if (!currentProject) return;
try {
const api = getElectronAPI();
if (!api.features) {
logger.error('Features API not available');
return;
}
const api = getElectronAPI();
if (!api.features) {
throw new Error('Features API not available');
}
const result = await api.features.create(currentProject.path, feature as ApiFeature);
if (result.success && result.feature) {
updateFeature(result.feature.id, result.feature as Partial<Feature>);
// Invalidate React Query cache to sync UI
queryClient.invalidateQueries({
queryKey: queryKeys.features.all(currentProject.path),
});
}
} catch (error) {
logger.error('Failed to persist feature creation:', error);
const result = await api.features.create(currentProject.path, feature as ApiFeature);
if (result.success && result.feature) {
updateFeature(result.feature.id, result.feature as Partial<Feature>);
// Invalidate React Query cache to sync UI
queryClient.invalidateQueries({
queryKey: queryKeys.features.all(currentProject.path),
});
} else if (!result.success) {
throw new Error(result.error || 'Failed to create feature on server');
}
},
[currentProject, updateFeature, queryClient]

13
package-lock.json generated
View File

@@ -8,6 +8,7 @@
"name": "automaker",
"version": "0.13.0",
"hasInstallScript": true,
"license": "MIT",
"workspaces": [
"apps/*",
"libs/*"
@@ -56,6 +57,7 @@
"yaml": "2.7.0"
},
"devDependencies": {
"@playwright/test": "1.57.0",
"@types/cookie": "0.6.0",
"@types/cookie-parser": "1.4.10",
"@types/cors": "2.8.19",
@@ -11475,7 +11477,6 @@
"os": [
"android"
],
"peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -11497,7 +11498,6 @@
"os": [
"darwin"
],
"peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -11519,7 +11519,6 @@
"os": [
"darwin"
],
"peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -11541,7 +11540,6 @@
"os": [
"freebsd"
],
"peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -11563,7 +11561,6 @@
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -11585,7 +11582,6 @@
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -11607,7 +11603,6 @@
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -11629,7 +11624,6 @@
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -11651,7 +11645,6 @@
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -11673,7 +11666,6 @@
"os": [
"win32"
],
"peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -11695,7 +11687,6 @@
"os": [
"win32"
],
"peer": true,
"engines": {
"node": ">= 12.0.0"
},