# useMutateGeneric

## Description
A configurable React Query mutation hook that abstracts CRUD operations for Okapi endpoints. Provides atomic control over POST/PUT/DELETE operations with deep customization while maintaining FOLIO API conventions.

**Key Features**:
- Auto-generated endpoint URLs
- Built-in error swallowing (silent catch unless overridden)
- Type-safe mutation separation
- Query key hierarchy management
- Full lifecycle event hooks

---

## Basic Usage
```jsx
const { post, put, delete: destroy } = useMutateGeneric({
  endpoint: 'users',
  queryKey: ['user-management']
});

// Create user
const handleCreate = (userData) => post(userData);

// Update user
const handleUpdate = (updatedUser) => put(updatedUser);

// Delete user
const handleDelete = (userId) => destroy(userId);
```

**Note**: By default:
- Errors are caught but not thrown (silent failure)
- POST goes to `/endpoint`
- PUT/DELETE go to `/endpoint/{id}`

---

## Advanced Use Cases

### 1. Custom Endpoint Structure
```jsx
// Custom endpoint for legacy system
useMutateGeneric({
  endpoint: 'v2/inventory',
  endpointMutators: {
    put: (data) => `legacy-inventory/${data.legacyId}?version=1.2`
  }
});
```

### 2. Payload Transformation
```jsx
// Add audit metadata to payload
useMutateGeneric({
  payloadMutators: {
    post: (data) => ({
      json: {
        ...data,
        metadata: {
          createdBy: getCurrentUserId(),
          createdDate: new Date().toISOString()
        }
      }
    })
  }
});
```

### 3. Custom Promise Handling
```jsx
// Directly override HTTP method
useMutateGeneric({
  promiseReturns: {
    post: (data, ky) => ky.custom('PATCH', 'custom-endpoint', { data })
  }
});
```

### 4. Full Mutation Control
```jsx
// Access loading states and errors
const {
  post: postMutation // Returns full mutation object
} = useMutateGeneric({
  returnQueryObject: { post: true }
});

// Usage
postMutation.mutateAsync(data);
console.log('Loading:', postMutation.isLoading);
```

---

## Configuration Options

### Core Parameters
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `endpoint` | string | ✓ | - | Base API path (e.g., `'circulation/loans'`) |
| `queryKey` | array | ✓ | - | React Query root key (e.g., `['loans']`) |

### Operation-Specific Parameters (post/put/delete)
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `endpointMutators.{op}` | `(data) => string` | [See below] | Generates final endpoint URL |
| `payloadMutators.{op}` | `(data) => object` | Returns `{ json: data }` | Shapes request payload |
| `promiseReturns.{op}` | `(data, ky) => Promise` | Standard CRUD | Full control over fetch implementation |
| `queryKeyMutators.{op}` | `() => array` | Appends operation type | Custom query key construction |
| `afterQueryCalls.{op}` | `(response) => void` | - | Success side effects |
| `catchQueryCalls.{op}` | `(error) => void` | Silent catch | Custom error handling |
| `returnQueryObject.{op}` | boolean | `false` | Returns full mutation object |

**Default Endpoint Mutators**:
- POST: `() => endpoint`
- PUT: `(data) => ${endpoint}/${data.id}`
- DELETE: `(id) => ${endpoint}/${id}`

---

## How It Works

### Architecture Flow
1. **Hook Initialization**
    - Receives base configuration
    - Creates three isolated `useMutation` instances (post/put/delete)

2. **Request Execution**
   ```mermaid
   graph TD
   A[User calls post(data)] --> B[Apply payloadMutators]
   B --> C[Build endpoint via endpointMutators]
   C --> D[Execute promiseReturns with ky]
   D --> E[Trigger afterQueryCalls]
   E --> F[Update React Query cache]
   ```

3. **Error Handling**
    - Errors bubble through `catchQueryCalls`
    - Uncaught errors are swallowed unless `catchQueryCalls` re-throws

4. **Cache Management**
    - Automatic query key generation via `queryKeyMutators`
    - No automatic cache invalidation (must use `useQueryClient`)

---

## Critical Implementation Notes

### 1. Error Handling Philosophy
- Default: Fails silently (prevents uncaught promise warnings)
- To surface errors:
  ```js
  useMutateGeneric({
    catchQueryCalls: {
      post: (error) => {
        showErrorToast(error); 
        throw error; // Propagate to UI errorBoundary if necessary
      }
    }
  });
  ```

### 2. Type Safety
- No runtime validation of payload shapes
- Recommend validation in `payloadMutators`:
  ```js
  payloadMutators: {
    post: (data) => {
      const safeData = ItemSchema.parse(data);
      return { json: safeData };
    }
  }
  ```

### 3. Performance Considerations
- Each operation creates isolated mutation instances
- Avoid excessive re-renders by memoizing config objects
- For bulk operations, prefer direct ky usage

---

## When Not to Use
- **Simple GET requests**: Use `useQuery` directly
- **Non-Okapi APIs**: Lacks built-in auth headers
  - However this can be achieved by overriding the fetch method with `promiseReturns`
