mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-07-03 05:38:26 +00:00
Compare commits
2 Commits
version-bu
...
matt/be-22
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8126713177 | ||
|
|
6b61a560f7 |
104
src/composables/useApiRequest.test.ts
Normal file
104
src/composables/useApiRequest.test.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import type { AxiosInstance, AxiosResponse } from 'axios'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { useApiRequest } from '@/composables/useApiRequest'
|
||||
|
||||
const mockIsAbortError = vi.hoisted(() => vi.fn())
|
||||
|
||||
vi.mock('@/utils/typeGuardUtil', () => ({
|
||||
isAbortError: mockIsAbortError
|
||||
}))
|
||||
|
||||
const client = { id: 'test-client' } as unknown as AxiosInstance
|
||||
|
||||
function response<T>(data: T): AxiosResponse<T> {
|
||||
return { data } as AxiosResponse<T>
|
||||
}
|
||||
|
||||
describe('useApiRequest', () => {
|
||||
beforeEach(() => {
|
||||
mockIsAbortError.mockReset()
|
||||
mockIsAbortError.mockReturnValue(false)
|
||||
})
|
||||
|
||||
it('returns response data and toggles loading state', async () => {
|
||||
const { isLoading, error, executeRequest } = useApiRequest({
|
||||
client,
|
||||
mapError: vi.fn()
|
||||
})
|
||||
expect(isLoading.value).toBe(false)
|
||||
|
||||
const pending = executeRequest(async () => response('ok'), {
|
||||
errorContext: 'ctx'
|
||||
})
|
||||
expect(isLoading.value).toBe(true)
|
||||
|
||||
await expect(pending).resolves.toBe('ok')
|
||||
expect(isLoading.value).toBe(false)
|
||||
expect(error.value).toBeNull()
|
||||
})
|
||||
|
||||
it('passes the injected client to the api call', async () => {
|
||||
const apiCall = vi.fn(async () => response(1))
|
||||
const { executeRequest } = useApiRequest({ client, mapError: vi.fn() })
|
||||
|
||||
await executeRequest(apiCall, { errorContext: 'ctx' })
|
||||
|
||||
expect(apiCall).toHaveBeenCalledWith(client)
|
||||
})
|
||||
|
||||
it('maps errors through the injected mapper and stores the message', async () => {
|
||||
const mapError = vi.fn(() => 'mapped message')
|
||||
const routeSpecificErrors = { 404: 'nope' }
|
||||
const boom = new Error('boom')
|
||||
const { error, executeRequest } = useApiRequest({ client, mapError })
|
||||
|
||||
const result = await executeRequest(
|
||||
() => {
|
||||
throw boom
|
||||
},
|
||||
{ errorContext: 'ctx', routeSpecificErrors }
|
||||
)
|
||||
|
||||
expect(result).toBeNull()
|
||||
expect(mapError).toHaveBeenCalledWith(boom, 'ctx', routeSpecificErrors)
|
||||
expect(error.value).toBe('mapped message')
|
||||
})
|
||||
|
||||
it('swallows cancellations without mapping an error', async () => {
|
||||
mockIsAbortError.mockReturnValue(true)
|
||||
const mapError = vi.fn(() => 'should not run')
|
||||
const { error, executeRequest } = useApiRequest({ client, mapError })
|
||||
|
||||
const result = await executeRequest(
|
||||
() => {
|
||||
throw new Error('aborted')
|
||||
},
|
||||
{ errorContext: 'ctx' }
|
||||
)
|
||||
|
||||
expect(result).toBeNull()
|
||||
expect(mapError).not.toHaveBeenCalled()
|
||||
expect(error.value).toBeNull()
|
||||
})
|
||||
|
||||
it('runs onSuccess only after a successful response', async () => {
|
||||
const onSuccess = vi.fn()
|
||||
const { executeRequest } = useApiRequest({ client, mapError: vi.fn() })
|
||||
|
||||
await executeRequest(async () => response('ok'), {
|
||||
errorContext: 'ctx',
|
||||
onSuccess
|
||||
})
|
||||
expect(onSuccess).toHaveBeenCalledTimes(1)
|
||||
|
||||
onSuccess.mockClear()
|
||||
await executeRequest(
|
||||
() => {
|
||||
throw new Error('boom')
|
||||
},
|
||||
{ errorContext: 'ctx', onSuccess }
|
||||
)
|
||||
expect(onSuccess).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
63
src/composables/useApiRequest.ts
Normal file
63
src/composables/useApiRequest.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import type { AxiosInstance, AxiosResponse } from 'axios'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import { isAbortError } from '@/utils/typeGuardUtil'
|
||||
|
||||
/**
|
||||
* Maps a caught request error to a user-facing message string.
|
||||
* Each service injects its own mapper so it keeps control of the exact
|
||||
* status-to-message copy it presents.
|
||||
*/
|
||||
export type ApiErrorMapper = (
|
||||
err: unknown,
|
||||
errorContext: string,
|
||||
routeSpecificErrors?: Record<number, string>
|
||||
) => string
|
||||
|
||||
export interface ExecuteRequestOptions {
|
||||
errorContext: string
|
||||
routeSpecificErrors?: Record<number, string>
|
||||
/** Side effect run after a successful response, before the data is returned. */
|
||||
onSuccess?: () => unknown
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared axios request wrapper: owns the `isLoading`/`error` state and the
|
||||
* try/catch/finally plumbing, while the caller injects the axios instance and
|
||||
* an error mapper. Cancellations are swallowed (no error set, `null` returned).
|
||||
*/
|
||||
export function useApiRequest({
|
||||
client,
|
||||
mapError
|
||||
}: {
|
||||
client: AxiosInstance
|
||||
mapError: ApiErrorMapper
|
||||
}) {
|
||||
const isLoading = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
|
||||
async function executeRequest<T>(
|
||||
apiCall: (client: AxiosInstance) => Promise<AxiosResponse<T>>,
|
||||
options: ExecuteRequestOptions
|
||||
): Promise<T | null> {
|
||||
const { errorContext, routeSpecificErrors, onSuccess } = options
|
||||
|
||||
isLoading.value = true
|
||||
error.value = null
|
||||
|
||||
try {
|
||||
const response = await apiCall(client)
|
||||
await onSuccess?.()
|
||||
return response.data
|
||||
} catch (err) {
|
||||
if (isAbortError(err)) return null
|
||||
|
||||
error.value = mapError(err, errorContext, routeSpecificErrors)
|
||||
return null
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
return { isLoading, error, executeRequest }
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { AxiosError, AxiosResponse } from 'axios'
|
||||
import type { AxiosError } from 'axios'
|
||||
import axios from 'axios'
|
||||
import { ref, watch } from 'vue'
|
||||
import { watch } from 'vue'
|
||||
|
||||
import { useApiRequest } from '@/composables/useApiRequest'
|
||||
import { getComfyApiBaseUrl } from '@/config/comfyApi'
|
||||
import type { components, operations } from '@/types/comfyRegistryTypes'
|
||||
import { isAbortError } from '@/utils/typeGuardUtil'
|
||||
|
||||
// Use generated types from OpenAPI spec
|
||||
export type ReleaseNote = components['schemas']['ReleaseNote']
|
||||
@@ -22,9 +22,6 @@ const releaseApiClient = axios.create({
|
||||
|
||||
// Release service for fetching release notes
|
||||
export const useReleaseService = () => {
|
||||
const isLoading = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
|
||||
watch(
|
||||
() => getComfyApiBaseUrl(),
|
||||
(url) => {
|
||||
@@ -32,10 +29,7 @@ export const useReleaseService = () => {
|
||||
}
|
||||
)
|
||||
|
||||
// No transformation needed - API response matches the generated type
|
||||
|
||||
// Handle API errors with context
|
||||
const handleApiError = (
|
||||
const mapError = (
|
||||
err: unknown,
|
||||
context: string,
|
||||
routeSpecificErrors?: Record<number, string>
|
||||
@@ -72,28 +66,10 @@ export const useReleaseService = () => {
|
||||
return `${context}: ${axiosError.message}`
|
||||
}
|
||||
|
||||
// Execute API request with error handling
|
||||
const executeApiRequest = async <T>(
|
||||
apiCall: () => Promise<AxiosResponse<T>>,
|
||||
errorContext: string,
|
||||
routeSpecificErrors?: Record<number, string>
|
||||
): Promise<T | null> => {
|
||||
isLoading.value = true
|
||||
error.value = null
|
||||
|
||||
try {
|
||||
const response = await apiCall()
|
||||
return response.data
|
||||
} catch (err) {
|
||||
// Don't treat cancellations as errors
|
||||
if (isAbortError(err)) return null
|
||||
|
||||
error.value = handleApiError(err, errorContext, routeSpecificErrors)
|
||||
return null
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
const { isLoading, error, executeRequest } = useApiRequest({
|
||||
client: releaseApiClient,
|
||||
mapError
|
||||
})
|
||||
|
||||
// Fetch release notes from API
|
||||
const getReleases = async (
|
||||
@@ -107,17 +83,16 @@ export const useReleaseService = () => {
|
||||
400: 'Invalid project or version parameter'
|
||||
}
|
||||
|
||||
const apiResponse = await executeApiRequest(
|
||||
() =>
|
||||
releaseApiClient.get<ReleaseNote[]>(endpoint, {
|
||||
const apiResponse = await executeRequest(
|
||||
(client) =>
|
||||
client.get<ReleaseNote[]>(endpoint, {
|
||||
params,
|
||||
signal,
|
||||
headers: deployEnvironment
|
||||
? { 'Comfy-Env': deployEnvironment }
|
||||
: undefined
|
||||
}),
|
||||
errorContext,
|
||||
routeSpecificErrors
|
||||
{ errorContext, routeSpecificErrors }
|
||||
)
|
||||
|
||||
return apiResponse
|
||||
|
||||
198
src/services/comfyRegistryService.test.ts
Normal file
198
src/services/comfyRegistryService.test.ts
Normal file
@@ -0,0 +1,198 @@
|
||||
import axios from 'axios'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { useComfyRegistryService } from '@/services/comfyRegistryService'
|
||||
|
||||
const mockAxiosInstance = vi.hoisted(() => ({
|
||||
get: vi.fn(),
|
||||
post: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('axios', () => ({
|
||||
default: {
|
||||
create: vi.fn(() => mockAxiosInstance),
|
||||
isAxiosError: vi.fn()
|
||||
}
|
||||
}))
|
||||
|
||||
describe('useComfyRegistryService', () => {
|
||||
let service: ReturnType<typeof useComfyRegistryService>
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
mockAxiosInstance.get.mockResolvedValue({ data: {} })
|
||||
mockAxiosInstance.post.mockResolvedValue({ data: {} })
|
||||
service = useComfyRegistryService()
|
||||
})
|
||||
|
||||
it('initializes with idle state', () => {
|
||||
expect(service.isLoading.value).toBe(false)
|
||||
expect(service.error.value).toBeNull()
|
||||
})
|
||||
|
||||
describe('request routing', () => {
|
||||
it('getNodeDefs hits the comfy-nodes endpoint', async () => {
|
||||
await service.getNodeDefs({ packId: 'pack', version: '1.0.0' })
|
||||
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith(
|
||||
'/nodes/pack/versions/1.0.0/comfy-nodes',
|
||||
expect.objectContaining({ params: {} })
|
||||
)
|
||||
})
|
||||
|
||||
it('getNodeDefs returns null without a packId or version', async () => {
|
||||
const result = await service.getNodeDefs({ packId: '', version: '' })
|
||||
|
||||
expect(result).toBeNull()
|
||||
expect(mockAxiosInstance.get).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('search hits the search endpoint', async () => {
|
||||
await service.search({ search: 'sampler' })
|
||||
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith(
|
||||
'/nodes/search',
|
||||
expect.objectContaining({ params: { search: 'sampler' } })
|
||||
)
|
||||
})
|
||||
|
||||
it('getPublisherById hits the publisher endpoint', async () => {
|
||||
await service.getPublisherById('pub-1')
|
||||
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith(
|
||||
'/publishers/pub-1',
|
||||
expect.any(Object)
|
||||
)
|
||||
})
|
||||
|
||||
it('listPacksForPublisher forwards include_banned', async () => {
|
||||
await service.listPacksForPublisher('pub-1', true)
|
||||
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith(
|
||||
'/publishers/pub-1/nodes',
|
||||
expect.objectContaining({ params: { include_banned: true } })
|
||||
)
|
||||
})
|
||||
|
||||
it('postPackReview posts the star rating', async () => {
|
||||
await service.postPackReview('pack', 5)
|
||||
|
||||
expect(mockAxiosInstance.post).toHaveBeenCalledWith(
|
||||
'/nodes/pack/reviews',
|
||||
null,
|
||||
expect.objectContaining({ params: { star: 5 } })
|
||||
)
|
||||
})
|
||||
|
||||
it('listAllPacks hits the nodes endpoint', async () => {
|
||||
await service.listAllPacks({ page: 1 })
|
||||
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith(
|
||||
'/nodes',
|
||||
expect.objectContaining({ params: { page: 1 } })
|
||||
)
|
||||
})
|
||||
|
||||
it('getPackVersions hits the versions endpoint', async () => {
|
||||
await service.getPackVersions('pack')
|
||||
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith(
|
||||
'/nodes/pack/versions',
|
||||
expect.any(Object)
|
||||
)
|
||||
})
|
||||
|
||||
it('getPackByVersion hits the specific version endpoint', async () => {
|
||||
await service.getPackByVersion('pack', 'v-1')
|
||||
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith(
|
||||
'/nodes/pack/versions/v-1',
|
||||
expect.any(Object)
|
||||
)
|
||||
})
|
||||
|
||||
it('getPackById hits the node endpoint', async () => {
|
||||
await service.getPackById('pack')
|
||||
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith(
|
||||
'/nodes/pack',
|
||||
expect.any(Object)
|
||||
)
|
||||
})
|
||||
|
||||
it('inferPackFromNodeName hits the comfy-nodes lookup endpoint', async () => {
|
||||
await service.inferPackFromNodeName('KSampler')
|
||||
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith(
|
||||
'/comfy-nodes/KSampler/node',
|
||||
expect.any(Object)
|
||||
)
|
||||
})
|
||||
|
||||
it('getBulkNodeVersions posts the identifiers', async () => {
|
||||
const nodeVersions = [{ node_id: 'pack', version: '1.0.0' }]
|
||||
await service.getBulkNodeVersions(nodeVersions)
|
||||
|
||||
expect(mockAxiosInstance.post).toHaveBeenCalledWith(
|
||||
'/bulk/nodes/versions',
|
||||
{ node_versions: nodeVersions },
|
||||
expect.any(Object)
|
||||
)
|
||||
})
|
||||
|
||||
it('returns the response data on success', async () => {
|
||||
mockAxiosInstance.get.mockResolvedValue({ data: { id: 'pack' } })
|
||||
|
||||
const result = await service.getPackById('pack')
|
||||
|
||||
expect(result).toEqual({ id: 'pack' })
|
||||
})
|
||||
})
|
||||
|
||||
describe('error mapping', () => {
|
||||
it('prefers a route-specific message for a matching status', async () => {
|
||||
mockAxiosInstance.get.mockRejectedValue({
|
||||
response: { status: 404, data: {} }
|
||||
})
|
||||
vi.mocked(axios.isAxiosError).mockReturnValue(true)
|
||||
|
||||
const result = await service.getPackById('missing')
|
||||
|
||||
expect(result).toBeNull()
|
||||
expect(service.error.value).toBe(
|
||||
'Pack not found: The pack with ID missing does not exist'
|
||||
)
|
||||
})
|
||||
|
||||
it('maps generic status codes to friendly messages', async () => {
|
||||
mockAxiosInstance.get.mockRejectedValue({
|
||||
response: { status: 401, data: {} }
|
||||
})
|
||||
vi.mocked(axios.isAxiosError).mockReturnValue(true)
|
||||
|
||||
await service.search()
|
||||
|
||||
expect(service.error.value).toBe('Unauthorized: Authentication required')
|
||||
})
|
||||
|
||||
it('falls back to the axios message when there is no response', async () => {
|
||||
mockAxiosInstance.get.mockRejectedValue({ message: 'Network Error' })
|
||||
vi.mocked(axios.isAxiosError).mockReturnValue(true)
|
||||
|
||||
await service.search()
|
||||
|
||||
expect(service.error.value).toBe(
|
||||
'Failed to perform search: Network Error'
|
||||
)
|
||||
})
|
||||
|
||||
it('handles non-axios errors', async () => {
|
||||
mockAxiosInstance.get.mockRejectedValue(new Error('boom'))
|
||||
vi.mocked(axios.isAxiosError).mockReturnValue(false)
|
||||
|
||||
await service.search()
|
||||
|
||||
expect(service.error.value).toBe('Failed to perform search: boom')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,9 +1,8 @@
|
||||
import type { AxiosError, AxiosResponse } from 'axios'
|
||||
import type { AxiosError } from 'axios'
|
||||
import axios from 'axios'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import { useApiRequest } from '@/composables/useApiRequest'
|
||||
import type { components, operations } from '@/types/comfyRegistryTypes'
|
||||
import { isAbortError } from '@/utils/typeGuardUtil'
|
||||
|
||||
const API_BASE_URL = 'https://api.comfy.org'
|
||||
|
||||
@@ -22,10 +21,7 @@ const registryApiClient = axios.create({
|
||||
* Service for interacting with the Comfy Registry API
|
||||
*/
|
||||
export const useComfyRegistryService = () => {
|
||||
const isLoading = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
|
||||
const handleApiError = (
|
||||
const mapError = (
|
||||
err: unknown,
|
||||
context: string,
|
||||
routeSpecificErrors?: Record<number, string>
|
||||
@@ -64,34 +60,10 @@ export const useComfyRegistryService = () => {
|
||||
return `${context}: ${axiosError.message}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an API request with error and loading state handling
|
||||
* @param apiCall - Function that returns a promise with the API call
|
||||
* @param errorContext - Context description for error messages
|
||||
* @param routeSpecificErrors - Optional map of status codes to custom error messages
|
||||
* @returns Promise with the API response data or null if the request failed
|
||||
*/
|
||||
const executeApiRequest = async <T>(
|
||||
apiCall: () => Promise<AxiosResponse<T>>,
|
||||
errorContext: string,
|
||||
routeSpecificErrors?: Record<number, string>
|
||||
): Promise<T | null> => {
|
||||
isLoading.value = true
|
||||
error.value = null
|
||||
|
||||
try {
|
||||
const response = await apiCall()
|
||||
return response.data
|
||||
} catch (err) {
|
||||
// Don't treat cancellations as errors
|
||||
if (isAbortError(err)) return null
|
||||
|
||||
error.value = handleApiError(err, errorContext, routeSpecificErrors)
|
||||
return null
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
const { isLoading, error, executeRequest } = useApiRequest({
|
||||
client: registryApiClient,
|
||||
mapError
|
||||
})
|
||||
|
||||
/**
|
||||
* Get the Comfy Node definitions in a specific version of a node pack
|
||||
@@ -116,16 +88,15 @@ export const useComfyRegistryService = () => {
|
||||
404: 'The requested node, version, or comfy node does not exist'
|
||||
}
|
||||
|
||||
return executeApiRequest(
|
||||
() =>
|
||||
registryApiClient.get<
|
||||
return executeRequest(
|
||||
(client) =>
|
||||
client.get<
|
||||
operations['ListComfyNodes']['responses'][200]['content']['application/json']
|
||||
>(endpoint, {
|
||||
params: queryParams,
|
||||
signal
|
||||
}),
|
||||
errorContext,
|
||||
routeSpecificErrors
|
||||
{ errorContext, routeSpecificErrors }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -140,12 +111,12 @@ export const useComfyRegistryService = () => {
|
||||
const endpoint = '/nodes/search'
|
||||
const errorContext = 'Failed to perform search'
|
||||
|
||||
return executeApiRequest(
|
||||
() =>
|
||||
registryApiClient.get<
|
||||
return executeRequest(
|
||||
(client) =>
|
||||
client.get<
|
||||
operations['searchNodes']['responses'][200]['content']['application/json']
|
||||
>(endpoint, { params, signal }),
|
||||
errorContext
|
||||
{ errorContext }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -162,13 +133,12 @@ export const useComfyRegistryService = () => {
|
||||
404: `Publisher not found: The publisher with ID ${publisherId} does not exist`
|
||||
}
|
||||
|
||||
return executeApiRequest(
|
||||
() =>
|
||||
registryApiClient.get<components['schemas']['Publisher']>(endpoint, {
|
||||
return executeRequest(
|
||||
(client) =>
|
||||
client.get<components['schemas']['Publisher']>(endpoint, {
|
||||
signal
|
||||
}),
|
||||
errorContext,
|
||||
routeSpecificErrors
|
||||
{ errorContext, routeSpecificErrors }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -188,14 +158,13 @@ export const useComfyRegistryService = () => {
|
||||
404: `Publisher not found: The publisher with ID ${publisherId} does not exist`
|
||||
}
|
||||
|
||||
return executeApiRequest(
|
||||
() =>
|
||||
registryApiClient.get<components['schemas']['Node'][]>(endpoint, {
|
||||
return executeRequest(
|
||||
(client) =>
|
||||
client.get<components['schemas']['Node'][]>(endpoint, {
|
||||
params,
|
||||
signal
|
||||
}),
|
||||
errorContext,
|
||||
routeSpecificErrors
|
||||
{ errorContext, routeSpecificErrors }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -215,14 +184,13 @@ export const useComfyRegistryService = () => {
|
||||
404: `Pack not found: Pack with ID ${packId} does not exist`
|
||||
}
|
||||
|
||||
return executeApiRequest(
|
||||
() =>
|
||||
registryApiClient.post<components['schemas']['Node']>(endpoint, null, {
|
||||
return executeRequest(
|
||||
(client) =>
|
||||
client.post<components['schemas']['Node']>(endpoint, null, {
|
||||
params,
|
||||
signal
|
||||
}),
|
||||
errorContext,
|
||||
routeSpecificErrors
|
||||
{ errorContext, routeSpecificErrors }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -236,12 +204,12 @@ export const useComfyRegistryService = () => {
|
||||
const endpoint = '/nodes'
|
||||
const errorContext = 'Failed to list packs'
|
||||
|
||||
return executeApiRequest(
|
||||
() =>
|
||||
registryApiClient.get<
|
||||
return executeRequest(
|
||||
(client) =>
|
||||
client.get<
|
||||
operations['listAllNodes']['responses'][200]['content']['application/json']
|
||||
>(endpoint, { params, signal }),
|
||||
errorContext
|
||||
{ errorContext }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -260,14 +228,13 @@ export const useComfyRegistryService = () => {
|
||||
404: `Pack not found: Pack with ID ${packId} does not exist`
|
||||
}
|
||||
|
||||
return executeApiRequest(
|
||||
() =>
|
||||
registryApiClient.get<components['schemas']['NodeVersion'][]>(
|
||||
endpoint,
|
||||
{ params, signal }
|
||||
),
|
||||
errorContext,
|
||||
routeSpecificErrors
|
||||
return executeRequest(
|
||||
(client) =>
|
||||
client.get<components['schemas']['NodeVersion'][]>(endpoint, {
|
||||
params,
|
||||
signal
|
||||
}),
|
||||
{ errorContext, routeSpecificErrors }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -286,13 +253,12 @@ export const useComfyRegistryService = () => {
|
||||
404: `Pack not found: Pack with ID ${packId} does not exist`
|
||||
}
|
||||
|
||||
return executeApiRequest(
|
||||
() =>
|
||||
registryApiClient.get<components['schemas']['NodeVersion']>(endpoint, {
|
||||
return executeRequest(
|
||||
(client) =>
|
||||
client.get<components['schemas']['NodeVersion']>(endpoint, {
|
||||
signal
|
||||
}),
|
||||
errorContext,
|
||||
routeSpecificErrors
|
||||
{ errorContext, routeSpecificErrors }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -309,13 +275,12 @@ export const useComfyRegistryService = () => {
|
||||
404: `Pack not found: The pack with ID ${packId} does not exist`
|
||||
}
|
||||
|
||||
return executeApiRequest(
|
||||
() =>
|
||||
registryApiClient.get<components['schemas']['Node']>(endpoint, {
|
||||
return executeRequest(
|
||||
(client) =>
|
||||
client.get<components['schemas']['Node']>(endpoint, {
|
||||
signal
|
||||
}),
|
||||
errorContext,
|
||||
routeSpecificErrors
|
||||
{ errorContext, routeSpecificErrors }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -350,13 +315,12 @@ export const useComfyRegistryService = () => {
|
||||
404: `Comfy node not found: The node with name ${nodeName} does not exist in the registry`
|
||||
}
|
||||
|
||||
return executeApiRequest(
|
||||
() =>
|
||||
registryApiClient.get<components['schemas']['Node']>(endpoint, {
|
||||
return executeRequest(
|
||||
(client) =>
|
||||
client.get<components['schemas']['Node']>(endpoint, {
|
||||
signal
|
||||
}),
|
||||
errorContext,
|
||||
routeSpecificErrors
|
||||
{ errorContext, routeSpecificErrors }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -397,15 +361,16 @@ export const useComfyRegistryService = () => {
|
||||
node_versions: nodeVersions
|
||||
}
|
||||
|
||||
return executeApiRequest(
|
||||
() =>
|
||||
registryApiClient.post<
|
||||
components['schemas']['BulkNodeVersionsResponse']
|
||||
>(endpoint, requestBody, {
|
||||
signal
|
||||
}),
|
||||
errorContext,
|
||||
routeSpecificErrors
|
||||
return executeRequest(
|
||||
(client) =>
|
||||
client.post<components['schemas']['BulkNodeVersionsResponse']>(
|
||||
endpoint,
|
||||
requestBody,
|
||||
{
|
||||
signal
|
||||
}
|
||||
),
|
||||
{ errorContext, routeSpecificErrors }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import type { AxiosError, AxiosResponse } from 'axios'
|
||||
import type { AxiosError } from 'axios'
|
||||
import axios from 'axios'
|
||||
import { ref, watch } from 'vue'
|
||||
import { watch } from 'vue'
|
||||
|
||||
import { useApiRequest } from '@/composables/useApiRequest'
|
||||
import { attachUnifiedRemintInterceptor } from '@/platform/auth/unified/remintRetry'
|
||||
import { getComfyApiBaseUrl } from '@/config/comfyApi'
|
||||
import { d, t } from '@/i18n'
|
||||
import { useAuthStore } from '@/stores/authStore'
|
||||
import type { components, operations } from '@/types/comfyRegistryTypes'
|
||||
import { isAbortError } from '@/utils/typeGuardUtil'
|
||||
|
||||
export enum EventType {
|
||||
CREDIT_ADDED = 'credit_added',
|
||||
@@ -34,9 +34,6 @@ const customerApiClient = axios.create({
|
||||
attachUnifiedRemintInterceptor(customerApiClient)
|
||||
|
||||
export const useCustomerEventsService = () => {
|
||||
const isLoading = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
|
||||
watch(
|
||||
() => getComfyApiBaseUrl(),
|
||||
(url) => {
|
||||
@@ -44,54 +41,31 @@ export const useCustomerEventsService = () => {
|
||||
}
|
||||
)
|
||||
|
||||
const handleRequestError = (
|
||||
const mapError = (
|
||||
err: unknown,
|
||||
context: string,
|
||||
routeSpecificErrors?: Record<number, string>
|
||||
) => {
|
||||
// Don't treat cancellation as an error
|
||||
if (isAbortError(err)) return
|
||||
|
||||
let message: string
|
||||
): string => {
|
||||
if (!axios.isAxiosError(err)) {
|
||||
message = `${context} failed: ${err instanceof Error ? err.message : String(err)}`
|
||||
} else {
|
||||
const axiosError = err as AxiosError<{ message: string }>
|
||||
const status = axiosError.response?.status
|
||||
if (status && routeSpecificErrors?.[status]) {
|
||||
message = routeSpecificErrors[status]
|
||||
} else {
|
||||
message =
|
||||
axiosError.response?.data?.message ??
|
||||
`${context} failed with status ${status}`
|
||||
}
|
||||
return `${context} failed: ${err instanceof Error ? err.message : String(err)}`
|
||||
}
|
||||
|
||||
error.value = message
|
||||
const axiosError = err as AxiosError<{ message: string }>
|
||||
const status = axiosError.response?.status
|
||||
if (status && routeSpecificErrors?.[status]) {
|
||||
return routeSpecificErrors[status]
|
||||
}
|
||||
|
||||
return (
|
||||
axiosError.response?.data?.message ??
|
||||
`${context} failed with status ${status}`
|
||||
)
|
||||
}
|
||||
|
||||
const executeRequest = async <T>(
|
||||
requestCall: () => Promise<AxiosResponse<T>>,
|
||||
options: {
|
||||
errorContext: string
|
||||
routeSpecificErrors?: Record<number, string>
|
||||
}
|
||||
): Promise<T | null> => {
|
||||
const { errorContext, routeSpecificErrors } = options
|
||||
|
||||
isLoading.value = true
|
||||
error.value = null
|
||||
|
||||
try {
|
||||
const response = await requestCall()
|
||||
return response.data
|
||||
} catch (err) {
|
||||
handleRequestError(err, errorContext, routeSpecificErrors)
|
||||
return null
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
const { isLoading, error, executeRequest } = useApiRequest({
|
||||
client: customerApiClient,
|
||||
mapError
|
||||
})
|
||||
|
||||
function formatEventType(eventType: string) {
|
||||
switch (eventType) {
|
||||
@@ -198,8 +172,8 @@ export const useCustomerEventsService = () => {
|
||||
}
|
||||
|
||||
const result = await executeRequest<CustomerEventsResponse>(
|
||||
() =>
|
||||
customerApiClient.get('/customers/events', {
|
||||
(client) =>
|
||||
client.get('/customers/events', {
|
||||
params: { page, limit },
|
||||
headers: authHeaders
|
||||
}),
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
import axios from 'axios'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { useComfyManagerService } from '@/workbench/extensions/manager/services/comfyManagerService'
|
||||
|
||||
const mockAxiosInstance = vi.hoisted(() => ({
|
||||
get: vi.fn(),
|
||||
post: vi.fn()
|
||||
}))
|
||||
|
||||
const managerState = vi.hoisted(() => ({ isNewManagerUI: true }))
|
||||
|
||||
vi.mock('axios', () => ({
|
||||
default: {
|
||||
create: vi.fn(() => mockAxiosInstance),
|
||||
isAxiosError: vi.fn()
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('@/scripts/api', () => ({
|
||||
api: {
|
||||
apiURL: (path: string) => path,
|
||||
clientId: 'client-1',
|
||||
initialClientId: null
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('@/workbench/extensions/manager/composables/useManagerState', () => ({
|
||||
useManagerState: () => ({
|
||||
isNewManagerUI: { value: managerState.isNewManagerUI }
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('uuid', () => ({ v4: () => 'generated-uuid' }))
|
||||
|
||||
describe('useComfyManagerService', () => {
|
||||
let service: ReturnType<typeof useComfyManagerService>
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
managerState.isNewManagerUI = true
|
||||
mockAxiosInstance.get.mockResolvedValue({ data: {} })
|
||||
mockAxiosInstance.post.mockResolvedValue({ data: null })
|
||||
service = useComfyManagerService()
|
||||
})
|
||||
|
||||
it('initializes with idle state', () => {
|
||||
expect(service.isLoading.value).toBe(false)
|
||||
expect(service.error.value).toBeNull()
|
||||
})
|
||||
|
||||
describe('availability gate', () => {
|
||||
it('short-circuits requests when Manager is not in NEW_UI mode', async () => {
|
||||
managerState.isNewManagerUI = false
|
||||
|
||||
const result = await service.listInstalledPacks()
|
||||
|
||||
expect(result).toBeNull()
|
||||
expect(mockAxiosInstance.get).not.toHaveBeenCalled()
|
||||
expect(service.error.value).toBe(
|
||||
'Manager service is not available in current mode'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('read requests', () => {
|
||||
it('getQueueStatus forwards the client_id param', async () => {
|
||||
await service.getQueueStatus('abc')
|
||||
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith(
|
||||
'manager/queue/status',
|
||||
expect.objectContaining({ params: { client_id: 'abc' } })
|
||||
)
|
||||
})
|
||||
|
||||
it('listInstalledPacks hits the installed endpoint', async () => {
|
||||
await service.listInstalledPacks()
|
||||
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith(
|
||||
'customnode/installed',
|
||||
expect.any(Object)
|
||||
)
|
||||
})
|
||||
|
||||
it('getImportFailInfo hits the import-fail endpoint', async () => {
|
||||
await service.getImportFailInfo()
|
||||
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith(
|
||||
'customnode/import_fail_info',
|
||||
expect.any(Object)
|
||||
)
|
||||
})
|
||||
|
||||
it('getImportFailInfoBulk returns empty without identifiers', async () => {
|
||||
const result = await service.getImportFailInfoBulk({})
|
||||
|
||||
expect(result).toEqual({})
|
||||
expect(mockAxiosInstance.post).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('getImportFailInfoBulk posts when identifiers are present', async () => {
|
||||
await service.getImportFailInfoBulk({ cnr_ids: ['a'] })
|
||||
|
||||
expect(mockAxiosInstance.post).toHaveBeenCalledWith(
|
||||
'customnode/import_fail_info_bulk',
|
||||
{ cnr_ids: ['a'] },
|
||||
expect.any(Object)
|
||||
)
|
||||
})
|
||||
|
||||
it('isLegacyManagerUI hits the legacy-ui endpoint', async () => {
|
||||
await service.isLegacyManagerUI()
|
||||
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith(
|
||||
'manager/is_legacy_manager_ui',
|
||||
expect.any(Object)
|
||||
)
|
||||
})
|
||||
|
||||
it('getTaskHistory forwards options as params', async () => {
|
||||
await service.getTaskHistory({ max_items: 5 })
|
||||
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith(
|
||||
'manager/queue/history',
|
||||
expect.objectContaining({ params: { max_items: 5 } })
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('queue operations', () => {
|
||||
it('installPack queues an install task then starts the queue', async () => {
|
||||
await service.installPack({
|
||||
id: 'pack',
|
||||
version: '1.0.0',
|
||||
selected_version: '1.0.0',
|
||||
mode: 'remote',
|
||||
channel: 'default'
|
||||
})
|
||||
|
||||
expect(mockAxiosInstance.post).toHaveBeenCalledWith(
|
||||
'manager/queue/task',
|
||||
expect.objectContaining({ kind: 'install' }),
|
||||
expect.any(Object)
|
||||
)
|
||||
expect(mockAxiosInstance.post).toHaveBeenCalledWith(
|
||||
'manager/queue/start',
|
||||
null,
|
||||
expect.any(Object)
|
||||
)
|
||||
})
|
||||
|
||||
it('uninstallPack queues an uninstall task', async () => {
|
||||
await service.uninstallPack({ node_name: 'pack', is_unknown: false })
|
||||
|
||||
expect(mockAxiosInstance.post).toHaveBeenCalledWith(
|
||||
'manager/queue/task',
|
||||
expect.objectContaining({ kind: 'uninstall' }),
|
||||
expect.any(Object)
|
||||
)
|
||||
})
|
||||
|
||||
it('updateAllPacks posts to the update_all endpoint', async () => {
|
||||
await service.updateAllPacks({ mode: 'remote' })
|
||||
|
||||
expect(mockAxiosInstance.post).toHaveBeenCalledWith(
|
||||
'manager/queue/update_all',
|
||||
null,
|
||||
expect.objectContaining({
|
||||
params: expect.objectContaining({ mode: 'remote' })
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('updateComfyUI posts to the update_comfyui endpoint', async () => {
|
||||
await service.updateComfyUI({ is_stable: true })
|
||||
|
||||
expect(mockAxiosInstance.post).toHaveBeenCalledWith(
|
||||
'manager/queue/update_comfyui',
|
||||
null,
|
||||
expect.objectContaining({
|
||||
params: expect.objectContaining({ is_stable: true })
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('rebootComfyUI posts to the reboot endpoint', async () => {
|
||||
await service.rebootComfyUI()
|
||||
|
||||
expect(mockAxiosInstance.post).toHaveBeenCalledWith(
|
||||
'manager/reboot',
|
||||
null,
|
||||
expect.any(Object)
|
||||
)
|
||||
})
|
||||
|
||||
it('startQueue posts to the start endpoint', async () => {
|
||||
await service.startQueue()
|
||||
|
||||
expect(mockAxiosInstance.post).toHaveBeenCalledWith(
|
||||
'manager/queue/start',
|
||||
null,
|
||||
expect.any(Object)
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('error mapping', () => {
|
||||
it('prefers a route-specific message for a matching status', async () => {
|
||||
mockAxiosInstance.post.mockRejectedValue({
|
||||
response: { status: 403, data: {} }
|
||||
})
|
||||
vi.mocked(axios.isAxiosError).mockReturnValue(true)
|
||||
|
||||
await service.rebootComfyUI()
|
||||
|
||||
expect(service.error.value).toBe(
|
||||
'Forbidden: Rebooting ComfyUI requires security_level of middle or below'
|
||||
)
|
||||
})
|
||||
|
||||
it('maps 404 to a connection message', async () => {
|
||||
mockAxiosInstance.get.mockRejectedValue({
|
||||
response: { status: 404, data: {} }
|
||||
})
|
||||
vi.mocked(axios.isAxiosError).mockReturnValue(true)
|
||||
|
||||
await service.listInstalledPacks()
|
||||
|
||||
expect(service.error.value).toBe('Could not connect to ComfyUI-Manager')
|
||||
})
|
||||
|
||||
it('falls back to the response message for other statuses', async () => {
|
||||
mockAxiosInstance.get.mockRejectedValue({
|
||||
response: { status: 500, data: { message: 'server exploded' } }
|
||||
})
|
||||
vi.mocked(axios.isAxiosError).mockReturnValue(true)
|
||||
|
||||
await service.listInstalledPacks()
|
||||
|
||||
expect(service.error.value).toBe('server exploded')
|
||||
})
|
||||
|
||||
it('handles non-axios errors', async () => {
|
||||
mockAxiosInstance.get.mockRejectedValue(new Error('boom'))
|
||||
vi.mocked(axios.isAxiosError).mockReturnValue(false)
|
||||
|
||||
await service.listInstalledPacks()
|
||||
|
||||
expect(service.error.value).toBe('Fetching installed packs failed: boom')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,10 +1,9 @@
|
||||
import type { AxiosError, AxiosResponse } from 'axios'
|
||||
import type { AxiosError, AxiosInstance, AxiosResponse } from 'axios'
|
||||
import axios from 'axios'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import { useApiRequest } from '@/composables/useApiRequest'
|
||||
import { api } from '@/scripts/api'
|
||||
import { isAbortError } from '@/utils/typeGuardUtil'
|
||||
import { useManagerState } from '@/workbench/extensions/manager/composables/useManagerState'
|
||||
import type { components } from '@/workbench/extensions/manager/types/generatedManagerTypes'
|
||||
|
||||
@@ -51,72 +50,64 @@ const managerApiClient = axios.create({
|
||||
* Note: This service should only be used when Manager state is NEW_UI
|
||||
*/
|
||||
export const useComfyManagerService = () => {
|
||||
const isLoading = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
|
||||
// Check if manager service should be available
|
||||
const isManagerServiceAvailable = () => {
|
||||
const managerState = useManagerState()
|
||||
return managerState.isNewManagerUI.value
|
||||
}
|
||||
|
||||
const handleRequestError = (
|
||||
const mapError = (
|
||||
err: unknown,
|
||||
context: string,
|
||||
routeSpecificErrors?: Record<number, string>
|
||||
) => {
|
||||
// Don't treat cancellation as an error
|
||||
if (isAbortError(err)) return
|
||||
|
||||
let message: string
|
||||
): string => {
|
||||
if (!axios.isAxiosError(err)) {
|
||||
message = `${context} failed: ${err instanceof Error ? err.message : String(err)}`
|
||||
} else {
|
||||
const axiosError = err as AxiosError<{ message: string }>
|
||||
const status = axiosError.response?.status
|
||||
if (status && routeSpecificErrors?.[status]) {
|
||||
message = routeSpecificErrors[status]
|
||||
} else if (status === 404) {
|
||||
message = 'Could not connect to ComfyUI-Manager'
|
||||
} else {
|
||||
message =
|
||||
axiosError.response?.data?.message ??
|
||||
`${context} failed with status ${status}`
|
||||
}
|
||||
return `${context} failed: ${err instanceof Error ? err.message : String(err)}`
|
||||
}
|
||||
|
||||
error.value = message
|
||||
const axiosError = err as AxiosError<{ message: string }>
|
||||
const status = axiosError.response?.status
|
||||
if (status && routeSpecificErrors?.[status]) {
|
||||
return routeSpecificErrors[status]
|
||||
}
|
||||
if (status === 404) {
|
||||
return 'Could not connect to ComfyUI-Manager'
|
||||
}
|
||||
|
||||
return (
|
||||
axiosError.response?.data?.message ??
|
||||
`${context} failed with status ${status}`
|
||||
)
|
||||
}
|
||||
|
||||
const executeRequest = async <T>(
|
||||
requestCall: () => Promise<AxiosResponse<T>>,
|
||||
const {
|
||||
isLoading,
|
||||
error,
|
||||
executeRequest: sendRequest
|
||||
} = useApiRequest({
|
||||
client: managerApiClient,
|
||||
mapError
|
||||
})
|
||||
|
||||
const executeRequest = <T>(
|
||||
apiCall: (client: AxiosInstance) => Promise<AxiosResponse<T>>,
|
||||
options: {
|
||||
errorContext: string
|
||||
routeSpecificErrors?: Record<number, string>
|
||||
isQueueOperation?: boolean
|
||||
}
|
||||
): Promise<T | null> => {
|
||||
const { errorContext, routeSpecificErrors, isQueueOperation } = options
|
||||
|
||||
// Block service calls if not in NEW_UI state
|
||||
if (!isManagerServiceAvailable()) {
|
||||
error.value = 'Manager service is not available in current mode'
|
||||
return null
|
||||
return Promise.resolve(null)
|
||||
}
|
||||
|
||||
isLoading.value = true
|
||||
error.value = null
|
||||
|
||||
try {
|
||||
const response = await requestCall()
|
||||
if (isQueueOperation) await startQueue()
|
||||
return response.data
|
||||
} catch (err) {
|
||||
handleRequestError(err, errorContext, routeSpecificErrors)
|
||||
return null
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
const { isQueueOperation, ...requestOptions } = options
|
||||
return sendRequest(apiCall, {
|
||||
...requestOptions,
|
||||
onSuccess: isQueueOperation ? startQueue : undefined
|
||||
})
|
||||
}
|
||||
|
||||
const startQueue = async (signal?: AbortSignal) => {
|
||||
@@ -126,7 +117,7 @@ export const useComfyManagerService = () => {
|
||||
}
|
||||
|
||||
return executeRequest<null>(
|
||||
() => managerApiClient.post(ManagerRoute.START_QUEUE, null, { signal }),
|
||||
(client) => client.post(ManagerRoute.START_QUEUE, null, { signal }),
|
||||
{ errorContext, routeSpecificErrors }
|
||||
)
|
||||
}
|
||||
@@ -135,8 +126,8 @@ export const useComfyManagerService = () => {
|
||||
const errorContext = 'Getting ComfyUI-Manager queue status'
|
||||
|
||||
return executeRequest<ManagerQueueStatus>(
|
||||
() =>
|
||||
managerApiClient.get(ManagerRoute.QUEUE_STATUS, {
|
||||
(client) =>
|
||||
client.get(ManagerRoute.QUEUE_STATUS, {
|
||||
params: client_id ? { client_id } : undefined,
|
||||
signal
|
||||
}),
|
||||
@@ -148,7 +139,7 @@ export const useComfyManagerService = () => {
|
||||
const errorContext = 'Fetching installed packs'
|
||||
|
||||
return executeRequest<InstalledPacksResponse>(
|
||||
() => managerApiClient.get(ManagerRoute.LIST_INSTALLED, { signal }),
|
||||
(client) => client.get(ManagerRoute.LIST_INSTALLED, { signal }),
|
||||
{ errorContext }
|
||||
)
|
||||
}
|
||||
@@ -157,7 +148,7 @@ export const useComfyManagerService = () => {
|
||||
const errorContext = 'Fetching import failure information'
|
||||
|
||||
return executeRequest<Record<string, unknown>>(
|
||||
() => managerApiClient.get(ManagerRoute.IMPORT_FAIL_INFO, { signal }),
|
||||
(client) => client.get(ManagerRoute.IMPORT_FAIL_INFO, { signal }),
|
||||
{ errorContext }
|
||||
)
|
||||
}
|
||||
@@ -173,8 +164,8 @@ export const useComfyManagerService = () => {
|
||||
}
|
||||
|
||||
return executeRequest<components['schemas']['ImportFailInfoBulkResponse']>(
|
||||
() =>
|
||||
managerApiClient.post(ManagerRoute.IMPORT_FAIL_INFO_BULK, params, {
|
||||
(client) =>
|
||||
client.post(ManagerRoute.IMPORT_FAIL_INFO_BULK, params, {
|
||||
signal
|
||||
}),
|
||||
{ errorContext }
|
||||
@@ -201,7 +192,7 @@ export const useComfyManagerService = () => {
|
||||
}
|
||||
|
||||
return executeRequest<null>(
|
||||
() => managerApiClient.post(ManagerRoute.QUEUE_TASK, task, { signal }),
|
||||
(client) => client.post(ManagerRoute.QUEUE_TASK, task, { signal }),
|
||||
{ errorContext, routeSpecificErrors, isQueueOperation: true }
|
||||
)
|
||||
}
|
||||
@@ -264,8 +255,8 @@ export const useComfyManagerService = () => {
|
||||
}
|
||||
|
||||
return executeRequest<null>(
|
||||
() =>
|
||||
managerApiClient.post(ManagerRoute.UPDATE_ALL, null, {
|
||||
(client) =>
|
||||
client.post(ManagerRoute.UPDATE_ALL, null, {
|
||||
params: queryParams,
|
||||
signal
|
||||
}),
|
||||
@@ -291,8 +282,8 @@ export const useComfyManagerService = () => {
|
||||
}
|
||||
|
||||
return executeRequest<null>(
|
||||
() =>
|
||||
managerApiClient.post(ManagerRoute.UPDATE_COMFYUI, null, {
|
||||
(client) =>
|
||||
client.post(ManagerRoute.UPDATE_COMFYUI, null, {
|
||||
params: queryParams,
|
||||
signal
|
||||
}),
|
||||
@@ -307,7 +298,7 @@ export const useComfyManagerService = () => {
|
||||
}
|
||||
|
||||
return executeRequest<null>(
|
||||
() => managerApiClient.post(ManagerRoute.REBOOT, null, { signal }),
|
||||
(client) => client.post(ManagerRoute.REBOOT, null, { signal }),
|
||||
{ errorContext, routeSpecificErrors }
|
||||
)
|
||||
}
|
||||
@@ -316,7 +307,7 @@ export const useComfyManagerService = () => {
|
||||
const errorContext = 'Checking if user set Manager to use the legacy UI'
|
||||
|
||||
return executeRequest<{ is_legacy_manager_ui: boolean }>(
|
||||
() => managerApiClient.get(ManagerRoute.IS_LEGACY_MANAGER_UI, { signal }),
|
||||
(client) => client.get(ManagerRoute.IS_LEGACY_MANAGER_UI, { signal }),
|
||||
{ errorContext }
|
||||
)
|
||||
}
|
||||
@@ -333,8 +324,8 @@ export const useComfyManagerService = () => {
|
||||
const errorContext = 'Getting ComfyUI-Manager task history'
|
||||
|
||||
return executeRequest<ManagerTaskHistory>(
|
||||
() =>
|
||||
managerApiClient.get(ManagerRoute.TASK_HISTORY, {
|
||||
(client) =>
|
||||
client.get(ManagerRoute.TASK_HISTORY, {
|
||||
params: options,
|
||||
signal
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user