mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-05 15:40:10 +00:00
refactor: load extensions dynamically according to the configuration file
This commit is contained in:
committed by
Alexander Brown
parent
ddbd26c062
commit
bb2c99749a
@@ -88,7 +88,7 @@ import type {
|
||||
LightConfig,
|
||||
ModelConfig,
|
||||
SceneConfig
|
||||
} from '@/extensions/core/load3d/interfaces'
|
||||
} from '@/extensions/core/extensions/load3d/interfaces'
|
||||
|
||||
const sceneConfig = defineModel<SceneConfig>('sceneConfig')
|
||||
const modelConfig = defineModel<ModelConfig>('modelConfig')
|
||||
|
||||
@@ -22,7 +22,7 @@ import Button from 'primevue/button'
|
||||
import { computed } from 'vue'
|
||||
|
||||
import PopupSlider from '@/components/load3d/controls/PopupSlider.vue'
|
||||
import type { CameraType } from '@/extensions/core/load3d/interfaces'
|
||||
import type { CameraType } from '@/extensions/core/extensions/load3d/interfaces'
|
||||
|
||||
const cameraType = defineModel<CameraType>('cameraType')
|
||||
const fov = defineModel<number>('fov')
|
||||
|
||||
@@ -35,7 +35,7 @@ import Button from 'primevue/button'
|
||||
import Slider from 'primevue/slider'
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
|
||||
import type { MaterialMode } from '@/extensions/core/load3d/interfaces'
|
||||
import type { MaterialMode } from '@/extensions/core/extensions/load3d/interfaces'
|
||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
|
||||
const lightIntensity = defineModel<number>('lightIntensity')
|
||||
|
||||
@@ -68,7 +68,7 @@ import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
import type {
|
||||
MaterialMode,
|
||||
UpDirection
|
||||
} from '@/extensions/core/load3d/interfaces'
|
||||
} from '@/extensions/core/extensions/load3d/interfaces'
|
||||
import { t } from '@/i18n'
|
||||
|
||||
const materialMode = defineModel<MaterialMode>('materialMode')
|
||||
|
||||
@@ -95,7 +95,7 @@ import Button from 'primevue/button'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
import PopupSlider from '@/components/load3d/controls/PopupSlider.vue'
|
||||
import type { BackgroundRenderModeType } from '@/extensions/core/load3d/interfaces'
|
||||
import type { BackgroundRenderModeType } from '@/extensions/core/extensions/load3d/interfaces'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'updateBackgroundImage', file: File | null): void
|
||||
|
||||
@@ -31,7 +31,7 @@ import Select from 'primevue/select'
|
||||
import Slider from 'primevue/slider'
|
||||
import { computed } from 'vue'
|
||||
|
||||
import type { CameraType } from '@/extensions/core/load3d/interfaces'
|
||||
import type { CameraType } from '@/extensions/core/extensions/load3d/interfaces'
|
||||
import { t } from '@/i18n'
|
||||
|
||||
const cameras = [
|
||||
|
||||
@@ -29,7 +29,7 @@ import { computed } from 'vue'
|
||||
import type {
|
||||
MaterialMode,
|
||||
UpDirection
|
||||
} from '@/extensions/core/load3d/interfaces'
|
||||
} from '@/extensions/core/extensions/load3d/interfaces'
|
||||
import { t } from '@/i18n'
|
||||
|
||||
const upDirection = defineModel<UpDirection>('upDirection')
|
||||
|
||||
@@ -2,8 +2,8 @@ import { toRef } from '@vueuse/core'
|
||||
import type { MaybeRef } from '@vueuse/core'
|
||||
import { nextTick, ref, toRaw, watch } from 'vue'
|
||||
|
||||
import Load3d from '@/extensions/core/load3d/Load3d'
|
||||
import Load3dUtils from '@/extensions/core/load3d/Load3dUtils'
|
||||
import Load3d from '@/extensions/core/extensions/load3d/Load3d'
|
||||
import Load3dUtils from '@/extensions/core/extensions/load3d/Load3dUtils'
|
||||
import type {
|
||||
AnimationItem,
|
||||
CameraConfig,
|
||||
@@ -13,7 +13,7 @@ import type {
|
||||
ModelConfig,
|
||||
SceneConfig,
|
||||
UpDirection
|
||||
} from '@/extensions/core/load3d/interfaces'
|
||||
} from '@/extensions/core/extensions/load3d/interfaces'
|
||||
import { t } from '@/i18n'
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
|
||||
import { useToastStore } from '@/platform/updates/common/toastStore'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { computed, ref, toValue } from 'vue'
|
||||
import type { MaybeRefOrGetter } from 'vue'
|
||||
|
||||
import { SUPPORTED_EXTENSIONS } from '@/extensions/core/load3d/interfaces'
|
||||
import { SUPPORTED_EXTENSIONS } from '@/extensions/core/extensions/load3d/interfaces'
|
||||
import { t } from '@/i18n'
|
||||
import { useToastStore } from '@/platform/updates/common/toastStore'
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { ref, toRaw, watch } from 'vue'
|
||||
|
||||
import Load3d from '@/extensions/core/load3d/Load3d'
|
||||
import Load3dUtils from '@/extensions/core/load3d/Load3dUtils'
|
||||
import Load3d from '@/extensions/core/extensions/load3d/Load3d'
|
||||
import Load3dUtils from '@/extensions/core/extensions/load3d/Load3dUtils'
|
||||
import type {
|
||||
BackgroundRenderModeType,
|
||||
CameraType,
|
||||
MaterialMode,
|
||||
UpDirection
|
||||
} from '@/extensions/core/load3d/interfaces'
|
||||
} from '@/extensions/core/extensions/load3d/interfaces'
|
||||
import { t } from '@/i18n'
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
|
||||
import { useToastStore } from '@/platform/updates/common/toastStore'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { app } from '../../scripts/app'
|
||||
import { ComfyApp } from '../../scripts/app'
|
||||
import { $el, ComfyDialog } from '../../scripts/ui'
|
||||
import { app } from '@/scripts/app'
|
||||
import { ComfyApp } from '@/scripts/app'
|
||||
import { $el, ComfyDialog } from '@/scripts/ui'
|
||||
|
||||
export class ClipspaceDialog extends ComfyDialog {
|
||||
static items: Array<
|
||||
@@ -0,0 +1,5 @@
|
||||
import { defineComfyExtConfig } from '@/extensions/utils'
|
||||
|
||||
export default defineComfyExtConfig({
|
||||
comfyCloud: true,
|
||||
})
|
||||
@@ -0,0 +1,5 @@
|
||||
import { defineComfyExtConfig } from '@/extensions/utils'
|
||||
|
||||
export default defineComfyExtConfig({
|
||||
comfyCloud: true,
|
||||
})
|
||||
@@ -0,0 +1,5 @@
|
||||
import { defineComfyExtConfig } from '@/extensions/utils'
|
||||
|
||||
export default defineComfyExtConfig({
|
||||
comfyCloud: true,
|
||||
})
|
||||
@@ -0,0 +1,5 @@
|
||||
import { defineComfyExtConfig } from '@/extensions/utils'
|
||||
|
||||
export default defineComfyExtConfig({
|
||||
comfyCloud: true,
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
import { defineComfyExtConfig } from '@/extensions/utils'
|
||||
|
||||
export default defineComfyExtConfig({
|
||||
comfyCloud: {
|
||||
subscriptionRequired: true,
|
||||
},
|
||||
})
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
isComboWidget
|
||||
} from '@/lib/litegraph/src/litegraph'
|
||||
|
||||
import { app } from '../../scripts/app'
|
||||
import { app } from '@/scripts/app'
|
||||
|
||||
// Adds filtering to combo context menus
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { app } from '../../scripts/app'
|
||||
import { app } from '@/scripts/app'
|
||||
|
||||
// Allows you to edit the attention weight by holding ctrl (or cmd) and using the up/down arrow keys
|
||||
|
||||
@@ -25,10 +25,10 @@ import { ExecutableGroupNodeChildDTO } from '@/utils/executableGroupNodeChildDTO
|
||||
import { GROUP } from '@/utils/executableGroupNodeDto'
|
||||
import { deserialiseAndCreate, serialise } from '@/utils/vintageClipboard'
|
||||
|
||||
import { api } from '../../scripts/api'
|
||||
import { app } from '../../scripts/app'
|
||||
import { ManageGroupDialog } from './groupNodeManage'
|
||||
import { mergeIfValid } from './widgetInputs'
|
||||
import { api } from '@/scripts/api'
|
||||
import { app } from '@/scripts/app'
|
||||
import { ManageGroupDialog } from '../groupNodeManage'
|
||||
import { mergeIfValid } from '../widgetInputs'
|
||||
|
||||
type GroupNodeWorkflowData = {
|
||||
external: ComfyLink[]
|
||||
@@ -6,11 +6,11 @@ import {
|
||||
} from '@/lib/litegraph/src/litegraph'
|
||||
import { useToastStore } from '@/platform/updates/common/toastStore'
|
||||
|
||||
import { type ComfyApp, app } from '../../scripts/app'
|
||||
import { $el } from '../../scripts/ui'
|
||||
import { ComfyDialog } from '../../scripts/ui/dialog'
|
||||
import { DraggableList } from '../../scripts/ui/draggableList'
|
||||
import { GroupNodeConfig, GroupNodeHandler } from './groupNode'
|
||||
import { type ComfyApp, app } from '@/scripts/app'
|
||||
import { $el } from '@/scripts/ui'
|
||||
import { ComfyDialog } from '@/scripts/ui/dialog'
|
||||
import { DraggableList } from '@/scripts/ui/draggableList'
|
||||
import { GroupNodeConfig, GroupNodeHandler } from '../groupNode'
|
||||
import './groupNodeManage.css'
|
||||
|
||||
const ORDER: symbol = Symbol()
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
import type { ComfyExtension } from '@/types/comfy'
|
||||
|
||||
import { app } from '../../scripts/app'
|
||||
import { app } from '@/scripts/app'
|
||||
|
||||
function setNodeMode(node: LGraphNode, mode: number) {
|
||||
node.mode = mode
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
type AnimationItem,
|
||||
type AnimationManagerInterface,
|
||||
type EventManagerInterface
|
||||
} from '@/extensions/core/load3d/interfaces'
|
||||
} from './interfaces'
|
||||
|
||||
export class AnimationManager implements AnimationManagerInterface {
|
||||
currentAnimation: THREE.AnimationMixer | null = null
|
||||
@@ -1,11 +1,11 @@
|
||||
import Load3d from '@/extensions/core/load3d/Load3d'
|
||||
import Load3dUtils from '@/extensions/core/load3d/Load3dUtils'
|
||||
import Load3d from './Load3d'
|
||||
import Load3dUtils from './Load3dUtils'
|
||||
import type {
|
||||
CameraConfig,
|
||||
LightConfig,
|
||||
ModelConfig,
|
||||
SceneConfig
|
||||
} from '@/extensions/core/load3d/interfaces'
|
||||
} from './interfaces'
|
||||
import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'
|
||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
import { api } from '@/scripts/api'
|
||||
@@ -1,7 +1,7 @@
|
||||
import { t } from '@/i18n'
|
||||
import type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'
|
||||
import { useToastStore } from '@/platform/updates/common/toastStore'
|
||||
import Load3d from '@/extensions/core/load3d/Load3d'
|
||||
import Load3d from './Load3d'
|
||||
import { LiteGraph } from '@/lib/litegraph/src/litegraph'
|
||||
|
||||
const EXPORT_FORMATS = [
|
||||
@@ -3,9 +3,9 @@ import { nextTick } from 'vue'
|
||||
import Load3D from '@/components/load3d/Load3D.vue'
|
||||
import Load3DViewerContent from '@/components/load3d/Load3dViewerContent.vue'
|
||||
import { nodeToLoad3dMap, useLoad3d } from '@/composables/useLoad3d'
|
||||
import { createExportMenuItems } from '@/extensions/core/load3d/exportMenuHelper'
|
||||
import Load3DConfiguration from '@/extensions/core/load3d/Load3DConfiguration'
|
||||
import Load3dUtils from '@/extensions/core/load3d/Load3dUtils'
|
||||
import { createExportMenuItems } from './exportMenuHelper'
|
||||
import Load3DConfiguration from './Load3DConfiguration'
|
||||
import Load3dUtils from './Load3dUtils'
|
||||
import { t } from '@/i18n'
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
|
||||
import type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'
|
||||
@@ -1,7 +1,7 @@
|
||||
import { t } from '@/i18n'
|
||||
import { api } from '../../../scripts/api'
|
||||
import { ComfyApp } from '../../../scripts/app'
|
||||
import { $el, ComfyDialog } from '../../../scripts/ui'
|
||||
import { api } from '@/scripts/api'
|
||||
import { ComfyApp } from '@/scripts/app'
|
||||
import { $el, ComfyDialog } from '@/scripts/ui'
|
||||
import { ClipspaceDialog } from '../clipspace'
|
||||
import { imageLayerFilenamesByTimestamp } from './utils/maskEditorLayerFilenames'
|
||||
import { CanvasHistory } from './CanvasHistory'
|
||||
@@ -1,13 +1,13 @@
|
||||
import _ from 'es-toolkit/compat'
|
||||
|
||||
import { app } from '../../scripts/app'
|
||||
import { ComfyApp } from '../../scripts/app'
|
||||
import { ClipspaceDialog } from './clipspace'
|
||||
import { MaskEditorDialog } from './maskeditor/MaskEditorDialog'
|
||||
import { MaskEditorDialogOld } from './maskEditorOld'
|
||||
import { app } from '@/scripts/app'
|
||||
import { ComfyApp } from '@/scripts/app'
|
||||
import { ClipspaceDialog } from '../clipspace'
|
||||
import { MaskEditorDialog } from './MaskEditorDialog'
|
||||
import { MaskEditorDialogOld } from '../../maskEditorOld'
|
||||
|
||||
// Import styles to inject into document
|
||||
import './maskeditor/styles'
|
||||
import './styles'
|
||||
|
||||
// Function to open the mask editor
|
||||
function openMaskEditor(): void {
|
||||
@@ -7,10 +7,10 @@ import { useDialogService } from '@/services/dialogService'
|
||||
import type { ComfyExtension } from '@/types/comfy'
|
||||
import { deserialiseAndCreate } from '@/utils/vintageClipboard'
|
||||
|
||||
import { api } from '../../scripts/api'
|
||||
import { app } from '../../scripts/app'
|
||||
import { $el, ComfyDialog } from '../../scripts/ui'
|
||||
import { GroupNodeConfig, GroupNodeHandler } from './groupNode'
|
||||
import { api } from '@/scripts/api'
|
||||
import { app } from '@/scripts/app'
|
||||
import { $el, ComfyDialog } from '@/scripts/ui'
|
||||
import { GroupNodeConfig, GroupNodeHandler } from '../groupNode'
|
||||
|
||||
// Adds the ability to save and add multiple nodes as a template
|
||||
// To save:
|
||||
@@ -1,8 +1,8 @@
|
||||
import { LGraphCanvas, LiteGraph } from '@/lib/litegraph/src/litegraph'
|
||||
import { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
||||
|
||||
import { app } from '../../scripts/app'
|
||||
import { ComfyWidgets } from '../../scripts/widgets'
|
||||
import { app } from '@/scripts/app'
|
||||
import { ComfyWidgets } from '@/scripts/widgets'
|
||||
|
||||
// Node that add notes to your project
|
||||
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
} from '@/lib/litegraph/src/litegraph'
|
||||
import type { ISlotType } from '@/lib/litegraph/src/interfaces'
|
||||
|
||||
import { app } from '../../scripts/app'
|
||||
import { getWidgetConfig, mergeIfValid, setWidgetConfig } from './widgetInputs'
|
||||
import { app } from '@/scripts/app'
|
||||
import { getWidgetConfig, mergeIfValid, setWidgetConfig } from '../widgetInputs'
|
||||
|
||||
// Node that allows you to redirect connections for cleaner graphs
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { applyTextReplacements } from '@/utils/searchAndReplace'
|
||||
|
||||
import { app } from '../../scripts/app'
|
||||
import { app } from '@/scripts/app'
|
||||
|
||||
const saveNodeTypes = new Set([
|
||||
'SaveImage',
|
||||
@@ -2,8 +2,8 @@ import { nextTick } from 'vue'
|
||||
|
||||
import Load3D from '@/components/load3d/Load3D.vue'
|
||||
import { useLoad3d } from '@/composables/useLoad3d'
|
||||
import { createExportMenuItems } from '@/extensions/core/load3d/exportMenuHelper'
|
||||
import Load3DConfiguration from '@/extensions/core/load3d/Load3DConfiguration'
|
||||
import { createExportMenuItems } from '../load3d/exportMenuHelper'
|
||||
import Load3DConfiguration from '../load3d/Load3DConfiguration'
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
|
||||
import type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'
|
||||
import { type CustomInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2'
|
||||
@@ -1,6 +1,6 @@
|
||||
import { LGraphCanvas, LiteGraph } from '@/lib/litegraph/src/litegraph'
|
||||
|
||||
import { app } from '../../scripts/app'
|
||||
import { app } from '@/scripts/app'
|
||||
|
||||
let touchZooming = false
|
||||
let touchCount = 0
|
||||
@@ -1,7 +1,7 @@
|
||||
import { LiteGraph } from '@/lib/litegraph/src/litegraph'
|
||||
|
||||
import { app } from '../../scripts/app'
|
||||
import { ComfyWidgets } from '../../scripts/widgets'
|
||||
import { app } from '@/scripts/app'
|
||||
import { ComfyWidgets } from '@/scripts/widgets'
|
||||
|
||||
// Adds defaults for quickly adding nodes with middle click on the input/output
|
||||
|
||||
@@ -21,8 +21,8 @@ import { useAudioService } from '@/services/audioService'
|
||||
import { type NodeLocatorId } from '@/types'
|
||||
import { getNodeByLocatorId } from '@/utils/graphTraversalUtil'
|
||||
|
||||
import { api } from '../../scripts/api'
|
||||
import { app } from '../../scripts/app'
|
||||
import { api } from '@/scripts/api'
|
||||
import { app } from '@/scripts/app'
|
||||
|
||||
async function uploadFile(
|
||||
audioWidget: IStringWidget,
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
isComboInputSpecV1
|
||||
} from '@/schemas/nodeDefSchema'
|
||||
|
||||
import { app } from '../../scripts/app'
|
||||
import { app } from '@/scripts/app'
|
||||
|
||||
// Adds an upload button to the nodes
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { t } from '@/i18n'
|
||||
import { useToastStore } from '@/platform/updates/common/toastStore'
|
||||
|
||||
import { api } from '../../scripts/api'
|
||||
import { app } from '../../scripts/app'
|
||||
import { api } from '@/scripts/api'
|
||||
import { app } from '@/scripts/app'
|
||||
|
||||
const WEBCAM_READY = Symbol()
|
||||
|
||||
@@ -1,38 +1,15 @@
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import { dispatchComfyExtensions } from '../dispatch'
|
||||
|
||||
import './clipspace'
|
||||
import './contextMenuFilter'
|
||||
import './dynamicPrompts'
|
||||
import './editAttention'
|
||||
import './electronAdapter'
|
||||
import './groupNode'
|
||||
import './groupNodeManage'
|
||||
import './groupOptions'
|
||||
import './load3d'
|
||||
import './maskeditor'
|
||||
import './matchType'
|
||||
import './nodeTemplates'
|
||||
import './noteNode'
|
||||
import './previewAny'
|
||||
import './rerouteNode'
|
||||
import './saveImageExtraOutput'
|
||||
import './saveMesh'
|
||||
import './selectionBorder'
|
||||
import './simpleTouchSupport'
|
||||
import './slotDefaults'
|
||||
import './uploadAudio'
|
||||
import './uploadImage'
|
||||
import './webcamCapture'
|
||||
import './widgetInputs'
|
||||
export async function importExtensions() {
|
||||
console.log('importExtensions running...')
|
||||
|
||||
// Cloud-only extensions - tree-shaken in OSS builds
|
||||
if (isCloud) {
|
||||
await import('./cloudRemoteConfig')
|
||||
await import('./cloudBadges')
|
||||
await import('./cloudSessionCookie')
|
||||
await import('./cloudFeedbackTopbarButton')
|
||||
const extConfigs = import.meta.glob(`./extensions/*/comfy.ext.config.ts`, {
|
||||
// Since each config is small, we only import the default export and use eager mode for better tree-shaking and performance.
|
||||
import: 'default',
|
||||
eager: true,
|
||||
})
|
||||
const extensionEntrance = import.meta.glob(`./extensions/*/index.ts`)
|
||||
|
||||
if (window.__CONFIG__?.subscription_required) {
|
||||
await import('./cloudSubscription')
|
||||
}
|
||||
dispatchComfyExtensions({ configs: extConfigs, entrance: extensionEntrance })
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { api } from '../../scripts/api'
|
||||
import { app } from '../../scripts/app'
|
||||
import { ComfyApp } from '../../scripts/app'
|
||||
import { $el, ComfyDialog } from '../../scripts/ui'
|
||||
import { ClipspaceDialog } from './clipspace'
|
||||
import { ClipspaceDialog } from './extensions/clipspace'
|
||||
|
||||
// Helper function to convert a data URL to a Blob object
|
||||
// @ts-expect-error fixme ts strict error
|
||||
|
||||
32
src/extensions/dispatch.ts
Normal file
32
src/extensions/dispatch.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import type {
|
||||
ComfyExtensionConfigs,
|
||||
ComfyExtensionEntrance,
|
||||
ComfyExtensionLoadContext
|
||||
} from './types'
|
||||
import { formatExtensions, shouldLoadExtension } from './utils'
|
||||
|
||||
const extLoadContext: ComfyExtensionLoadContext = {
|
||||
get isCloud() {
|
||||
return isCloud
|
||||
},
|
||||
get subscriptionRequired() {
|
||||
return !!window.__CONFIG__?.subscription_required
|
||||
}
|
||||
}
|
||||
|
||||
export async function dispatchComfyExtensions(options: {
|
||||
configs: ComfyExtensionConfigs
|
||||
entrance: ComfyExtensionEntrance
|
||||
}) {
|
||||
const { configs, entrance } = options
|
||||
const extensions = formatExtensions(entrance, configs)
|
||||
for (const extension of Object.values(extensions)) {
|
||||
if (shouldLoadExtension(extLoadContext, extension.config)) {
|
||||
const module = await extension.entry()
|
||||
console.log('✅ extension', extension.name, 'loaded', extension, module)
|
||||
} else {
|
||||
console.log('❌ extension', extension.name, 'disabled', extension.config)
|
||||
}
|
||||
}
|
||||
}
|
||||
30
src/extensions/types.ts
Normal file
30
src/extensions/types.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
export interface ComfyExtensionConfig {
|
||||
comfyCloud?:
|
||||
| boolean
|
||||
| {
|
||||
subscriptionRequired: boolean
|
||||
}
|
||||
}
|
||||
export type ComfyExtensionConfigs = Record<
|
||||
string,
|
||||
ComfyExtensionConfig | undefined
|
||||
>
|
||||
|
||||
export interface ComfyExtensionLoadContext {
|
||||
readonly isCloud: boolean
|
||||
readonly subscriptionRequired: boolean
|
||||
}
|
||||
|
||||
export type ComfyExtensionEntry = () => Promise<Record<string, unknown>>
|
||||
export type ComfyExtensionEntrance = Record<
|
||||
string,
|
||||
ComfyExtensionEntry | undefined
|
||||
>
|
||||
|
||||
export interface ComfyExtensionPackage {
|
||||
name?: string
|
||||
path?: string
|
||||
config?: ComfyExtensionConfig
|
||||
entry: ComfyExtensionEntry
|
||||
}
|
||||
export type ComfyExtensionPackages = Record<string, ComfyExtensionPackage>
|
||||
59
src/extensions/utils.ts
Normal file
59
src/extensions/utils.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import type {
|
||||
ComfyExtensionConfig,
|
||||
ComfyExtensionConfigs,
|
||||
ComfyExtensionEntrance,
|
||||
ComfyExtensionLoadContext,
|
||||
ComfyExtensionPackages
|
||||
} from './types'
|
||||
|
||||
export function defineComfyExtConfig(
|
||||
config: ComfyExtensionConfig
|
||||
): ComfyExtensionConfig {
|
||||
return config
|
||||
}
|
||||
|
||||
export function formatExtensions(
|
||||
entrance: ComfyExtensionEntrance,
|
||||
configs: ComfyExtensionConfigs
|
||||
): ComfyExtensionPackages {
|
||||
const pkgs: ComfyExtensionPackages = {}
|
||||
for (const [entryPath, entry] of Object.entries(entrance)) {
|
||||
const pathArr = entryPath.split('/')
|
||||
const name = pathArr.at(-2)!
|
||||
const path = pathArr.slice(0, -1).join('/')
|
||||
if (!name) {
|
||||
console.error(`Extension`, path, `has no name`)
|
||||
continue
|
||||
}
|
||||
if (!entry) {
|
||||
console.error(`Extension`, path, `has no entrance`)
|
||||
continue
|
||||
}
|
||||
|
||||
const config = configs[`${path}/comfy.ext.config.ts`]
|
||||
if (!config) {
|
||||
console.warn(`⚠️ Extension`, path, `has no config`)
|
||||
}
|
||||
pkgs[name] = { name, path, config, entry }
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
export function shouldLoadExtension(
|
||||
ctx: ComfyExtensionLoadContext,
|
||||
extConfig: ComfyExtensionConfig | undefined
|
||||
): boolean {
|
||||
// No Config -> Load Extension
|
||||
if (!extConfig) return true
|
||||
|
||||
// Cloud Only Extension
|
||||
const { comfyCloud } = extConfig
|
||||
if (comfyCloud) {
|
||||
if (!ctx.isCloud) return false
|
||||
if (comfyCloud === true) return true
|
||||
return comfyCloud.subscriptionRequired && ctx.subscriptionRequired
|
||||
}
|
||||
|
||||
// Default Extension -> Load Extension
|
||||
return true
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { PrimitiveNode } from '@/extensions/core/widgetInputs'
|
||||
import type { PrimitiveNode } from '@/extensions/core/extensions/widgetInputs'
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
||||
|
||||
export const isPrimitiveNode = (
|
||||
|
||||
@@ -35,7 +35,8 @@ export const useExtensionService = () => {
|
||||
|
||||
// Need to load core extensions first as some custom extensions
|
||||
// may depend on them.
|
||||
await import('../extensions/core/index')
|
||||
const { importExtensions } = await import('../extensions/core/index')
|
||||
await importExtensions()
|
||||
extensionStore.captureCoreExtensions()
|
||||
await Promise.all(
|
||||
extensions
|
||||
|
||||
@@ -2,7 +2,7 @@ import { toRaw } from 'vue'
|
||||
|
||||
import { nodeToLoad3dMap } from '@/composables/useLoad3d'
|
||||
import { useLoad3dViewer } from '@/composables/useLoad3dViewer'
|
||||
import type Load3d from '@/extensions/core/load3d/Load3d'
|
||||
import type Load3d from '@/extensions/core/extensions/load3d/Load3d'
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
||||
import type { NodeId } from '@/platform/workflow/validation/schemas/workflowSchema'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { GroupNodeHandler } from '@/extensions/core/groupNode'
|
||||
import type { GroupNodeHandler } from '@/extensions/core/extensions/groupNode'
|
||||
import { ExecutableNodeDTO } from '@/lib/litegraph/src/litegraph'
|
||||
import type {
|
||||
ExecutableLGraphNode,
|
||||
|
||||
@@ -2,16 +2,16 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { nextTick, ref } from 'vue'
|
||||
|
||||
import { nodeToLoad3dMap, useLoad3d } from '@/composables/useLoad3d'
|
||||
import Load3d from '@/extensions/core/load3d/Load3d'
|
||||
import Load3dUtils from '@/extensions/core/load3d/Load3dUtils'
|
||||
import Load3d from '@/extensions/core/extensions/load3d/Load3d'
|
||||
import Load3dUtils from '@/extensions/core/extensions/load3d/Load3dUtils'
|
||||
import { useToastStore } from '@/platform/updates/common/toastStore'
|
||||
import { api } from '@/scripts/api'
|
||||
|
||||
vi.mock('@/extensions/core/load3d/Load3d', () => ({
|
||||
vi.mock('@/extensions/core/extensions/load3d/Load3d', () => ({
|
||||
default: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('@/extensions/core/load3d/Load3dUtils', () => ({
|
||||
vi.mock('@/extensions/core/extensions/load3d/Load3dUtils', () => ({
|
||||
default: {
|
||||
splitFilePath: vi.fn(),
|
||||
getResourceURL: vi.fn(),
|
||||
|
||||
@@ -2,8 +2,8 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { nextTick } from 'vue'
|
||||
|
||||
import { useLoad3dViewer } from '@/composables/useLoad3dViewer'
|
||||
import Load3d from '@/extensions/core/load3d/Load3d'
|
||||
import Load3dUtils from '@/extensions/core/load3d/Load3dUtils'
|
||||
import Load3d from '@/extensions/core/extensions/load3d/Load3d'
|
||||
import Load3dUtils from '@/extensions/core/extensions/load3d/Load3dUtils'
|
||||
import { useToastStore } from '@/platform/updates/common/toastStore'
|
||||
import { useLoad3dService } from '@/services/load3dService'
|
||||
|
||||
@@ -15,7 +15,7 @@ vi.mock('@/platform/updates/common/toastStore', () => ({
|
||||
useToastStore: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('@/extensions/core/load3d/Load3dUtils', () => ({
|
||||
vi.mock('@/extensions/core/extensions/load3d/Load3dUtils', () => ({
|
||||
default: {
|
||||
uploadFile: vi.fn()
|
||||
}
|
||||
@@ -25,7 +25,7 @@ vi.mock('@/i18n', () => ({
|
||||
t: vi.fn((key) => key)
|
||||
}))
|
||||
|
||||
vi.mock('@/extensions/core/load3d/Load3d', () => ({
|
||||
vi.mock('@/extensions/core/extensions/load3d/Load3d', () => ({
|
||||
default: vi.fn()
|
||||
}))
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { imageLayerFilenamesIfApplicable } from '@/extensions/core/maskeditor/utils/maskEditorLayerFilenames'
|
||||
import { imageLayerFilenamesIfApplicable } from '@/extensions/core/extensions/maskeditor/utils/maskEditorLayerFilenames'
|
||||
|
||||
describe('imageLayerFilenamesIfApplicable', () => {
|
||||
// In case the naming scheme changes, this test will ensure CI fails if developers forget to support the old naming scheme. (Causing MaskEditor to lose layer data for previously-saved images.)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import type { GroupNodeHandler } from '@/extensions/core/groupNode'
|
||||
import type { GroupNodeHandler } from '@/extensions/core/extensions/groupNode'
|
||||
import type {
|
||||
ExecutableLGraphNode,
|
||||
ExecutionId,
|
||||
|
||||
Reference in New Issue
Block a user