'use client'
import { useCallback, useRef, useState } from 'react'
import type {
PackageInfo,
PackageActionsState,
PackageActionHandlers,
UsePackageActionsReturn,
PackageError,
} from '@/lib/types/package-admin-types'
import { PackageErrorCode } from '@/lib/types/package-admin-types'
/**
* usePackageActions Hook
*
* Manages individual package operations (install, uninstall, enable, disable).
* Tracks operation loading states and prevents duplicate operations.
*
* @param options - Configuration options
* @returns Package action handlers and state
*
* @example
* ```tsx
* const { handlers, state, isOperationInProgress } = usePackageActions({
* onSuccess: (package) => {
* showToast(`${package.name} installed successfully`)
* refetchList()
* },
* })
*
* return (
*
* )
* ```
*/
interface UsePackageActionsOptions {
/**
* Base URL prefix for API calls (e.g. '/workflowui')
*/
baseUrl?: string
/**
* Callback when operation completes successfully
*/
onSuccess?: (
pkg: PackageInfo,
operation: 'install' | 'uninstall' | 'enable' | 'disable'
) => void
/**
* Callback when operation fails
*/
onError?: (error: PackageError, packageId: string) => void
}
/**
* Create a structured PackageError from API response
*/
function createPackageError(
statusCode: number,
response: Record
): PackageError {
const message = (response.message as string) || 'Unknown error'
const code = (response.code as PackageErrorCode) || PackageErrorCode.UNKNOWN_ERROR
const details = (response.details as Record) || {}
const error = new Error(message) as PackageError
error.code = code
error.statusCode = statusCode
error.details = details
error.name = 'PackageError'
return error
}
/**
* Parse API error response
*/
async function parseApiError(response: Response): Promise {
try {
const data = (await response.json()) as Record
return createPackageError(response.status, data)
} catch {
const error = new Error(
`HTTP ${response.status}: ${response.statusText}`
) as PackageError
error.code = PackageErrorCode.NETWORK_ERROR
error.statusCode = response.status
error.name = 'PackageError'
return error
}
}
export function usePackageActions(
options: UsePackageActionsOptions = {}
): UsePackageActionsReturn {
const { baseUrl = '', onSuccess, onError } = options
// State
const [state, setState] = useState({
isLoading: false,
operationInProgress: new Set(),
error: null,
})
// Track abort controllers per operation
const abortControllersRef = useRef