diff --git a/packages/shared-frontend-utils/package.json b/packages/shared-frontend-utils/package.json new file mode 100644 index 0000000000..fa25c37a37 --- /dev/null +++ b/packages/shared-frontend-utils/package.json @@ -0,0 +1,22 @@ +{ + "name": "@comfyorg/shared-frontend-utils", + "private": true, + "version": "1.0.0", + "description": "Shared frontend utils for ComfyUI Frontend", + "scripts": { + "typecheck": "tsc --noEmit" + }, + "keywords": [], + "packageManager": "pnpm@10.17.1", + "type": "module", + "exports": { + "./formatUtil": "./src/formatUtil.ts", + "./networkUtil": "./src/networkUtil.ts" + }, + "dependencies": { + "axios": "^1.11.0" + }, + "devDependencies": { + "typescript": "^5.9.2" + } +} diff --git a/src/utils/formatUtil.ts b/packages/shared-frontend-utils/src/formatUtil.ts similarity index 93% rename from src/utils/formatUtil.ts rename to packages/shared-frontend-utils/src/formatUtil.ts index 9d4f0c2702..a5d525c82d 100644 --- a/src/utils/formatUtil.ts +++ b/packages/shared-frontend-utils/src/formatUtil.ts @@ -1,5 +1,4 @@ -import type { ResultItem } from '@/schemas/apiSchema' -import type { operations } from '@/types/comfyRegistryTypes' +import type { operations } from '@comfyorg/registry-types' export function formatCamelCase(str: string): string { // Check if the string is camel case @@ -194,27 +193,6 @@ export function isValidUrl(url: string): boolean { return false } } -const hasAnnotation = (filepath: string): boolean => - /\[(input|output|temp)\]/i.test(filepath) - -const createAnnotation = (filepath: string, rootFolder = 'input'): string => - !hasAnnotation(filepath) && rootFolder !== 'input' ? ` [${rootFolder}]` : '' - -const createPath = (filename: string, subfolder = ''): string => - subfolder ? `${subfolder}/${filename}` : filename - -/** Creates annotated filepath in format used by folder_paths.py */ -export function createAnnotatedPath( - item: string | ResultItem, - options: { rootFolder?: string; subfolder?: string } = {} -): string { - const { rootFolder = 'input', subfolder } = options - if (typeof item === 'string') - return `${createPath(item, subfolder)}${createAnnotation(item, rootFolder)}` - return `${createPath(item.filename ?? '', item.subfolder)}${ - item.type ? createAnnotation(item.type, rootFolder) : '' - }` -} /** * Parses a filepath into its filename and subfolder components. diff --git a/src/utils/networkUtil.ts b/packages/shared-frontend-utils/src/networkUtil.ts similarity index 81% rename from src/utils/networkUtil.ts rename to packages/shared-frontend-utils/src/networkUtil.ts index bc29d81e5f..7ae5972326 100644 --- a/src/utils/networkUtil.ts +++ b/packages/shared-frontend-utils/src/networkUtil.ts @@ -1,8 +1,5 @@ import axios from 'axios' -import { electronAPI } from './envUtil' -import { isValidUrl } from './formatUtil' - const VALID_STATUS_CODES = [200, 201, 301, 302, 307, 308] export const checkUrlReachable = async (url: string): Promise => { try { @@ -14,17 +11,6 @@ export const checkUrlReachable = async (url: string): Promise => { } } -/** - * Check if a mirror is reachable from the electron App. - * @param mirror - The mirror to check. - * @returns True if the mirror is reachable, false otherwise. - */ -export const checkMirrorReachable = async (mirror: string) => { - return ( - isValidUrl(mirror) && (await electronAPI().NetWork.canAccessUrl(mirror)) - ) -} - /** * Checks if the user is likely in mainland China by: * 1. Checking navigator.language diff --git a/packages/shared-frontend-utils/tsconfig.json b/packages/shared-frontend-utils/tsconfig.json new file mode 100644 index 0000000000..60c7df1811 --- /dev/null +++ b/packages/shared-frontend-utils/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist" + }, + "include": ["src/**/*"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7c9e6dc89e..2768d1af2a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -373,6 +373,16 @@ importers: packages/registry-types: {} + packages/shared-frontend-utils: + dependencies: + axios: + specifier: ^1.11.0 + version: 1.11.0 + devDependencies: + typescript: + specifier: ^5.9.2 + version: 5.9.2 + packages/tailwind-utils: dependencies: clsx: diff --git a/scripts/collect-i18n-general.ts b/scripts/collect-i18n-general.ts index 53c813fb76..8907133f1b 100644 --- a/scripts/collect-i18n-general.ts +++ b/scripts/collect-i18n-general.ts @@ -1,12 +1,15 @@ import * as fs from 'fs' import { comfyPageFixture as test } from '../browser_tests/fixtures/ComfyPage' +import { + formatCamelCase, + normalizeI18nKey +} from '../packages/shared-frontend-utils/src/formatUtil' import { CORE_MENU_COMMANDS } from '../src/constants/coreMenuCommands' import { DESKTOP_DIALOGS } from '../src/constants/desktopDialogs' import { SERVER_CONFIG_ITEMS } from '../src/constants/serverConfig' import type { FormItem, SettingParams } from '../src/platform/settings/types' import type { ComfyCommandImpl } from '../src/stores/commandStore' -import { formatCamelCase, normalizeI18nKey } from '../src/utils/formatUtil' const localePath = './src/locales/en/main.json' const commandsPath = './src/locales/en/commands.json' diff --git a/scripts/collect-i18n-node-defs.ts b/scripts/collect-i18n-node-defs.ts index 99ab97a663..46d85ad734 100644 --- a/scripts/collect-i18n-node-defs.ts +++ b/scripts/collect-i18n-node-defs.ts @@ -3,8 +3,8 @@ import * as fs from 'fs' import type { ComfyNodeDef } from '@/schemas/nodeDefSchema' import { comfyPageFixture as test } from '../browser_tests/fixtures/ComfyPage' +import { normalizeI18nKey } from '../packages/shared-frontend-utils/src/formatUtil' import type { ComfyNodeDefImpl } from '../src/stores/nodeDefStore' -import { normalizeI18nKey } from '../src/utils/formatUtil' const localePath = './src/locales/en/main.json' const nodeDefsPath = './src/locales/en/nodeDefs.json' diff --git a/src/components/install/mirror/MirrorItem.vue b/src/components/install/mirror/MirrorItem.vue index 3665d66c9f..204ab1034c 100644 --- a/src/components/install/mirror/MirrorItem.vue +++ b/src/components/install/mirror/MirrorItem.vue @@ -60,8 +60,8 @@ import { computed, onMounted, ref, watch } from 'vue' import UrlInput from '@/components/common/UrlInput.vue' import type { UVMirror } from '@/constants/uvMirrors' import { st } from '@/i18n' +import { checkMirrorReachable } from '@/utils/electronMirrorCheck' import { normalizeI18nKey } from '@/utils/formatUtil' -import { checkMirrorReachable } from '@/utils/networkUtil' import { ValidationState } from '@/utils/validationUtil' const FILE_URL_SCHEME = 'file://' diff --git a/src/extensions/core/electronAdapter.ts b/src/extensions/core/electronAdapter.ts index 718639b475..ac6239d082 100644 --- a/src/extensions/core/electronAdapter.ts +++ b/src/extensions/core/electronAdapter.ts @@ -6,8 +6,8 @@ import { useToastStore } from '@/platform/updates/common/toastStore' import { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore' import { app } from '@/scripts/app' import { useDialogService } from '@/services/dialogService' +import { checkMirrorReachable } from '@/utils/electronMirrorCheck' import { electronAPI as getElectronAPI, isElectron } from '@/utils/envUtil' -import { checkMirrorReachable } from '@/utils/networkUtil' // Desktop documentation URLs const DESKTOP_DOCS = { diff --git a/src/renderer/extensions/vueNodes/widgets/composables/useImageUploadWidget.ts b/src/renderer/extensions/vueNodes/widgets/composables/useImageUploadWidget.ts index 28b1228cde..3be0dde046 100644 --- a/src/renderer/extensions/vueNodes/widgets/composables/useImageUploadWidget.ts +++ b/src/renderer/extensions/vueNodes/widgets/composables/useImageUploadWidget.ts @@ -9,7 +9,7 @@ import type { InputSpec } from '@/schemas/nodeDefSchema' import type { ComfyWidgetConstructor } from '@/scripts/widgets' import { useNodeOutputStore } from '@/stores/imagePreviewStore' import { isImageUploadInput } from '@/types/nodeDefAugmentation' -import { createAnnotatedPath } from '@/utils/formatUtil' +import { createAnnotatedPath } from '@/utils/createAnnotatedPath' import { addToComboValues } from '@/utils/litegraphUtil' const ACCEPTED_IMAGE_TYPES = 'image/png,image/jpeg,image/webp' diff --git a/src/utils/createAnnotatedPath.ts b/src/utils/createAnnotatedPath.ts new file mode 100644 index 0000000000..c178d19646 --- /dev/null +++ b/src/utils/createAnnotatedPath.ts @@ -0,0 +1,23 @@ +import type { ResultItem } from '@/schemas/apiSchema' + +const hasAnnotation = (filepath: string): boolean => + /\[(input|output|temp)\]/i.test(filepath) + +const createAnnotation = (filepath: string, rootFolder = 'input'): string => + !hasAnnotation(filepath) && rootFolder !== 'input' ? ` [${rootFolder}]` : '' + +const createPath = (filename: string, subfolder = ''): string => + subfolder ? `${subfolder}/${filename}` : filename + +/** Creates annotated filepath in format used by folder_paths.py */ +export function createAnnotatedPath( + item: string | ResultItem, + options: { rootFolder?: string; subfolder?: string } = {} +): string { + const { rootFolder = 'input', subfolder } = options + if (typeof item === 'string') + return `${createPath(item, subfolder)}${createAnnotation(item, rootFolder)}` + return `${createPath(item.filename ?? '', item.subfolder)}${ + item.type ? createAnnotation(item.type, rootFolder) : '' + }` +} diff --git a/src/utils/electronMirrorCheck.ts b/src/utils/electronMirrorCheck.ts new file mode 100644 index 0000000000..8242fb6fa4 --- /dev/null +++ b/src/utils/electronMirrorCheck.ts @@ -0,0 +1,13 @@ +import { electronAPI } from '@/utils/envUtil' +import { isValidUrl } from '@/utils/formatUtil' + +/** + * Check if a mirror is reachable from the electron App. + * @param mirror - The mirror to check. + * @returns True if the mirror is reachable, false otherwise. + */ +export const checkMirrorReachable = async (mirror: string) => { + return ( + isValidUrl(mirror) && (await electronAPI().NetWork.canAccessUrl(mirror)) + ) +} diff --git a/tsconfig.json b/tsconfig.json index 3af5495b63..dcd08734d0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,7 +22,13 @@ "verbatimModuleSyntax": true, "baseUrl": ".", "paths": { - "@/*": ["src/*"] + "@/*": ["src/*"], + "@/utils/formatUtil": [ + "packages/shared-frontend-utils/src/formatUtil.ts" + ], + "@/utils/networkUtil": [ + "packages/shared-frontend-utils/src/networkUtil.ts" + ] }, "typeRoots": ["src/types", "node_modules/@types"], "outDir": "./dist", diff --git a/vite.config.mts b/vite.config.mts index 9c50268a9b..ab5ebf4120 100644 --- a/vite.config.mts +++ b/vite.config.mts @@ -190,6 +190,9 @@ export default defineConfig({ resolve: { alias: { + '@/utils/formatUtil': '/packages/shared-frontend-utils/src/formatUtil.ts', + '@/utils/networkUtil': + '/packages/shared-frontend-utils/src/networkUtil.ts', '@': '/src' } }, diff --git a/vitest.config.ts b/vitest.config.ts index 244aae16f1..23320a000b 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -37,6 +37,9 @@ export default defineConfig({ }, resolve: { alias: { + '@/utils/formatUtil': '/packages/shared-frontend-utils/src/formatUtil.ts', + '@/utils/networkUtil': + '/packages/shared-frontend-utils/src/networkUtil.ts', '@': '/src' } },