mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-19 22:09:37 +00:00
Compare commits
5 Commits
bl-refacto
...
feat/conso
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e80a5789c | ||
|
|
81ddfc2f58 | ||
|
|
e19f0b2da9 | ||
|
|
afecff6c94 | ||
|
|
5afeee258f |
@@ -160,12 +160,15 @@ export function useTemplateWorkflows() {
|
||||
*/
|
||||
const fetchTemplateJson = async (id: string, sourceModule: string) => {
|
||||
if (sourceModule === 'default') {
|
||||
// Default templates provided by frontend are served on this separate endpoint
|
||||
return fetch(api.fileURL(`/templates/${id}.json`)).then((r) => r.json())
|
||||
// Default templates provided by frontend are served as static files
|
||||
const response = await fetch(api.fileURL(`/templates/${id}.json`))
|
||||
return await response.json()
|
||||
} else {
|
||||
return fetch(
|
||||
api.apiURL(`/workflow_templates/${sourceModule}/${id}.json`)
|
||||
).then((r) => r.json())
|
||||
// Custom node templates served via API
|
||||
const response = await api.fetchApi(
|
||||
`/workflow_templates/${sourceModule}/${id}.json`
|
||||
)
|
||||
return await response.json()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { OBJExporter } from 'three/examples/jsm/exporters/OBJExporter'
|
||||
import { STLExporter } from 'three/examples/jsm/exporters/STLExporter'
|
||||
|
||||
import { t } from '@/i18n'
|
||||
import { api } from '@/scripts/api'
|
||||
import { useToastStore } from '@/stores/toastStore'
|
||||
|
||||
export class ModelExporter {
|
||||
@@ -36,7 +37,18 @@ export class ModelExporter {
|
||||
desiredFilename: string
|
||||
): Promise<void> {
|
||||
try {
|
||||
const response = await fetch(url)
|
||||
// Check if this is a ComfyUI relative URL
|
||||
const isComfyUrl = url.startsWith('/') || url.includes('/view?')
|
||||
|
||||
let response: Response
|
||||
if (isComfyUrl) {
|
||||
// Use ComfyUI API client for internal URLs
|
||||
response = await fetch(api.apiURL(url))
|
||||
} else {
|
||||
// Use direct fetch for external URLs
|
||||
response = await fetch(url)
|
||||
}
|
||||
|
||||
const blob = await response.blob()
|
||||
|
||||
const link = document.createElement('a')
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import axios from 'axios'
|
||||
import {
|
||||
type Auth,
|
||||
GithubAuthProvider,
|
||||
@@ -44,6 +45,14 @@ export class FirebaseAuthStoreError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
// Customer API client - follows the same pattern as other services
|
||||
const customerApiClient = axios.create({
|
||||
baseURL: COMFY_API_BASE_URL,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
|
||||
export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
|
||||
// State
|
||||
const loading = ref(false)
|
||||
@@ -129,27 +138,27 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
|
||||
)
|
||||
}
|
||||
|
||||
const response = await fetch(`${COMFY_API_BASE_URL}/customers/balance`, {
|
||||
headers: {
|
||||
...authHeader,
|
||||
'Content-Type': 'application/json'
|
||||
let balanceData
|
||||
try {
|
||||
const response = await customerApiClient.get('/customers/balance', {
|
||||
headers: authHeader
|
||||
})
|
||||
balanceData = response.data
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error) && error.response) {
|
||||
if (error.response.status === 404) {
|
||||
// Customer not found is expected for new users
|
||||
return null
|
||||
}
|
||||
const errorData = error.response.data
|
||||
throw new FirebaseAuthStoreError(
|
||||
t('toastMessages.failedToFetchBalance', {
|
||||
error: errorData.message
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
// Customer not found is expected for new users
|
||||
return null
|
||||
}
|
||||
const errorData = await response.json()
|
||||
throw new FirebaseAuthStoreError(
|
||||
t('toastMessages.failedToFetchBalance', {
|
||||
error: errorData.message
|
||||
})
|
||||
)
|
||||
throw error
|
||||
}
|
||||
|
||||
const balanceData = await response.json()
|
||||
// Update the last balance update time
|
||||
lastBalanceUpdateTime.value = new Date()
|
||||
balance.value = balanceData
|
||||
@@ -165,23 +174,26 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
|
||||
throw new FirebaseAuthStoreError(t('toastMessages.userNotAuthenticated'))
|
||||
}
|
||||
|
||||
const createCustomerRes = await fetch(`${COMFY_API_BASE_URL}/customers`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...authHeader,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
if (!createCustomerRes.ok) {
|
||||
throw new FirebaseAuthStoreError(
|
||||
t('toastMessages.failedToCreateCustomer', {
|
||||
error: createCustomerRes.statusText
|
||||
})
|
||||
let createCustomerResJson: CreateCustomerResponse
|
||||
try {
|
||||
const createCustomerRes = await customerApiClient.post(
|
||||
'/customers',
|
||||
{},
|
||||
{
|
||||
headers: authHeader
|
||||
}
|
||||
)
|
||||
createCustomerResJson = createCustomerRes.data
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
throw new FirebaseAuthStoreError(
|
||||
t('toastMessages.failedToCreateCustomer', {
|
||||
error: error.response?.statusText || error.message
|
||||
})
|
||||
)
|
||||
}
|
||||
throw error
|
||||
}
|
||||
|
||||
const createCustomerResJson: CreateCustomerResponse =
|
||||
await createCustomerRes.json()
|
||||
if (!createCustomerResJson?.id) {
|
||||
throw new FirebaseAuthStoreError(
|
||||
t('toastMessages.failedToCreateCustomer', {
|
||||
@@ -282,25 +294,26 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
|
||||
customerCreated.value = true
|
||||
}
|
||||
|
||||
const response = await fetch(`${COMFY_API_BASE_URL}/customers/credit`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...authHeader,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(requestBodyContent)
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json()
|
||||
throw new FirebaseAuthStoreError(
|
||||
t('toastMessages.failedToInitiateCreditPurchase', {
|
||||
error: errorData.message
|
||||
})
|
||||
try {
|
||||
const response = await customerApiClient.post(
|
||||
'/customers/credit',
|
||||
requestBodyContent,
|
||||
{
|
||||
headers: authHeader
|
||||
}
|
||||
)
|
||||
return response.data
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error) && error.response) {
|
||||
const errorData = error.response.data
|
||||
throw new FirebaseAuthStoreError(
|
||||
t('toastMessages.failedToInitiateCreditPurchase', {
|
||||
error: errorData.message
|
||||
})
|
||||
)
|
||||
}
|
||||
throw error
|
||||
}
|
||||
|
||||
return response.json()
|
||||
}
|
||||
|
||||
const initiateCreditPurchase = async (
|
||||
@@ -316,27 +329,26 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
|
||||
throw new FirebaseAuthStoreError(t('toastMessages.userNotAuthenticated'))
|
||||
}
|
||||
|
||||
const response = await fetch(`${COMFY_API_BASE_URL}/customers/billing`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...authHeader,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
...(requestBody && {
|
||||
body: JSON.stringify(requestBody)
|
||||
})
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json()
|
||||
throw new FirebaseAuthStoreError(
|
||||
t('toastMessages.failedToAccessBillingPortal', {
|
||||
error: errorData.message
|
||||
})
|
||||
try {
|
||||
const response = await customerApiClient.post(
|
||||
'/customers/billing',
|
||||
requestBody,
|
||||
{
|
||||
headers: authHeader
|
||||
}
|
||||
)
|
||||
return response.data
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error) && error.response) {
|
||||
const errorData = error.response.data
|
||||
throw new FirebaseAuthStoreError(
|
||||
t('toastMessages.failedToAccessBillingPortal', {
|
||||
error: errorData.message
|
||||
})
|
||||
)
|
||||
}
|
||||
throw error
|
||||
}
|
||||
|
||||
return response.json()
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import axios from 'axios'
|
||||
import * as firebaseAuth from 'firebase/auth'
|
||||
import { createPinia, setActivePinia } from 'pinia'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
@@ -5,6 +6,30 @@ import * as vuefire from 'vuefire'
|
||||
|
||||
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
|
||||
|
||||
// Mock axios before any imports that use it
|
||||
vi.mock('axios', () => {
|
||||
const mockAxiosInstance = {
|
||||
get: vi.fn().mockResolvedValue({
|
||||
data: { balance: { credits: 0 } },
|
||||
status: 200
|
||||
}),
|
||||
post: vi.fn().mockResolvedValue({
|
||||
data: { id: 'test-customer-id' },
|
||||
status: 201
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
default: {
|
||||
create: vi.fn().mockReturnValue(mockAxiosInstance),
|
||||
isAxiosError: vi.fn().mockImplementation(() => false)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const mockedAxios = vi.mocked(axios)
|
||||
const mockAxiosInstance = mockedAxios.create() as any
|
||||
|
||||
// Mock fetch
|
||||
const mockFetch = vi.fn()
|
||||
vi.stubGlobal('fetch', mockFetch)
|
||||
@@ -91,7 +116,18 @@ describe('useFirebaseAuthStore', () => {
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks()
|
||||
vi.clearAllMocks()
|
||||
|
||||
// Reset axios mock responses to defaults
|
||||
mockAxiosInstance.get.mockResolvedValue({
|
||||
data: { balance: { credits: 0 } },
|
||||
status: 200
|
||||
})
|
||||
mockAxiosInstance.post.mockResolvedValue({
|
||||
data: { id: 'test-customer-id' },
|
||||
status: 201
|
||||
})
|
||||
;(mockedAxios.isAxiosError as any).mockReturnValue(false)
|
||||
|
||||
// Mock useFirebaseAuth to return our mock auth object
|
||||
vi.mocked(vuefire.useFirebaseAuth).mockReturnValue(mockAuth as any)
|
||||
|
||||
Reference in New Issue
Block a user