├── .github └── workflows │ └── publish.yml ├── .gitignore ├── LICENSE ├── README.md ├── __init__.py ├── classes ├── NodeInstaller.py └── NodeScriptRunner.py ├── config.py ├── nodejs ├── project1 │ ├── app.js │ └── package.json ├── project2 │ ├── app.js │ └── package.json └── project3 │ ├── app.js │ └── package.json ├── pyproject.toml ├── requirements.txt └── web └── assets └── img └── logo.jpg /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish to Comfy registry 2 | on: 3 | workflow_dispatch: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - "pyproject.toml" 9 | 10 | jobs: 11 | publish-node: 12 | name: Publish Custom Node to registry 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Check out code 16 | uses: actions/checkout@v4 17 | - name: Publish Custom Node 18 | uses: Comfy-Org/publish-node-action@main 19 | with: 20 | personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }} ## Add your own personal access token to your Github Repository secrets and reference it here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *.pyc 5 | *$py.class 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | build/ 13 | develop-eggs/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 105 | __pypackages__/ 106 | 107 | # Celery stuff 108 | celerybeat-schedule 109 | celerybeat.pid 110 | 111 | # SageMath parsed files 112 | *.sage.py 113 | 114 | # Environments 115 | .env 116 | .venv 117 | env/ 118 | venv/ 119 | ENV/ 120 | env.bak/ 121 | venv.bak/ 122 | 123 | # Spyder project settings 124 | .spyderproject 125 | .spyproject 126 | 127 | # Rope project settings 128 | .ropeproject 129 | 130 | # mkdocs documentation 131 | /site 132 | 133 | # mypy 134 | .mypy_cache/ 135 | .dmypy.json 136 | dmypy.json 137 | 138 | # Pyre type checker 139 | .pyre/ 140 | 141 | # pytype static type analyzer 142 | .pytype/ 143 | 144 | # Cython debug symbols 145 | cython_debug/ 146 | 147 | # PyCharm 148 | # JetBrains specific template is maintainted in a separate JetBrains.gitignore that can 149 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 150 | # and can be added to the global gitignore or merged into this file. For a more nuclear 151 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 152 | #.idea/ 153 | *.pyc 154 | 155 | .idea 156 | /node_modules 157 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2024 Daxton Caylor 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![COMFY-UI](https://github.com/daxcay/ComfyUI-NODEJS/assets/164315771/1b5fcdbf-ec3e-4a43-8311-43e20d73b705) 2 | 3 | # ComfyUI-NODEJS 4 | 5 | This node allows the execution of Node.js application within ComfyUI by leveraging the **ComfyUI-NODEJS**, which starts alongside ComfyUI and facilitates the installation of Node.js. The integration enables Python subprocesses to execute Node.js scripts. 6 | 7 | ## Features: 8 | 9 | - Node.js Installer: An semi-automated installation process of nodejs for windows users only. 10 | - Package Installer: Supports the installation and automatic updating of Node.js packages upon each startup. 11 | - Multiple scripts Execution: Enables running multiple projects simultaneously. 12 | - Graceful Shutdown: The service terminates when ComfyUI exits. 13 | 14 | ## NodeJS Installation: 15 | 16 | **Note: For non-windows user please install NodeJS before running this node** 17 | 18 | **NodeJS Installation: https://nodejs.org/en/download** 19 | 20 | **Windows users can skip this section** 21 | 22 | For any query you can join my discord server: https://discord.gg/Z44Zjpurjp 23 | 24 | ## Node Installation: 25 | 26 | 1. Using **comfy-cli** 27 | 28 | ```comfy node registry-install comfyui-nodejs``` 29 | 30 | 3. Using **manual method** 31 | - Go to your Comfyui > Custom Nodes folder 32 | - Run CMD from folder path box or right click on empty area and click open in terminal. 33 | - Copy and Paste this command git clone ```https://github.com/daxcay/ComfyUI-NODEJS.git``` 34 | - Then go inside ComfyUI-NODEJS with cmd or open new and type pip install -r requirements.txt to install the requirements. 35 | 36 | 4. Using Comfy Manager (https://github.com/ltdrdata/ComfyUI-Manager) 37 | - Inside ComfyUI > Click Manager Button on Side. 38 | - Click Install Custom Node and Search for nodejs and Install this node: 39 | 40 | ![image](https://github.com/daxcay/ComfyUI-NODEJS/assets/164315771/8cb85775-0eb0-4392-b4c3-979785a86a13) 41 | 42 | - Restart ComfyUI and it should be good to go 43 | 44 | ## Configuration 45 | 46 | To run nodejs project(s) you will need to do paste your project(s) folder in the **nodejs** directory of **ComfyUI-NODEJS**. 47 | 48 | ```ComfyUI\custom_nodes\ComfyUI-NODEJS\nodejs``` 49 | 50 | ![image](https://github.com/daxcay/ComfyUI-NODEJS/assets/164315771/9adabe4a-c25a-4604-85f3-7f2020167f30) 51 | 52 | ![image](https://github.com/daxcay/ComfyUI-NODEJS/assets/164315771/c6d990c0-7f3e-40ef-8a20-874d798f2c7b) 53 | 54 | **To run a project successfully verify the below steps carefully.** 55 | 56 | ### Project structure to be followed 57 | 58 | Every project should have two mandatory files in root folder one **app.js** and another **package.json** like this 59 | 60 | ![image](https://github.com/daxcay/ComfyUI-NODEJS/assets/164315771/c6731bf1-6db8-479f-ba53-f593a1bcf31f) 61 | 62 | **app.js** is just for representation actual name could be anything. (main.js, foo.js). 63 | but in package.json file mention correct name. 64 | 65 | **package.json** looks something like this: 66 | 67 | ``` 68 | { 69 | "name": "project1", 70 | "version": "1.0.0", 71 | "description": "", 72 | "main": "app.js", 73 | "scripts": { 74 | "dev" : "node dev.js", 75 | "production" : "node app.js", 76 | "test": "node test.js" 77 | }, 78 | "author": "", 79 | "license": "ISC", 80 | "dependencies": { 81 | "express": "^4.19.2" 82 | } 83 | } 84 | ``` 85 | 86 | Ensure your project package.json to have a "production" script in scripts objects. 87 | 88 | ![image](https://github.com/daxcay/ComfyUI-NODEJS/assets/164315771/af32aef5-87e6-41f2-b095-6ee8798b0977) 89 | 90 | Now run/restart **comfyui**. 91 | 92 | Open any browser and head to ```http://localhost:3000```. If NodeJs is installed successfully it should return: 93 | 94 | ![image](https://github.com/daxcay/ComfyUI-NODEJS/assets/164315771/480baf8e-6a37-44fe-8e7d-c012dc637fcd) 95 | 96 | **Demo projects are given in nodejs folder in case you don't understand anything. delete them when running actual projects or build upon them.** 97 | 98 | 99 | # Credits 100 | 101 | ◉ Daxton Caylor - ComfyUI Node Developer 102 | - Discord - daxtoncaylor 103 | - Email - daxtoncaylor@gmail.com 104 | - Discord server: https://discord.gg/UyGkJycvyW 105 | - Commission Status: 🟢 **Open** 🟢 106 | 107 | # Support ❤️ 108 | - Buy me a coffee: https://buymeacoffee.com/daxtoncaylor 109 | - If you like to suppport me you can donate me on paypal: https://paypal.me/daxtoncaylor 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Daxton Caylor 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | """ 22 | @author: Daxton Caylor 23 | @title: ComfyUI-NODEJS 24 | @nickname: ComfyUI-NODEJS 25 | @description: This node enables someone to run any nodejs application alongside comfyui. 26 | """ 27 | 28 | import os, platform 29 | from .classes.NodeInstaller import NodeInstaller 30 | from .classes.NodeScriptRunner import NodeScriptRunner 31 | from .config import * 32 | 33 | NODE_JS_FOLDER = os.path.join(os.path.dirname(os.path.abspath(__file__)), NODE_JS_FOLDER) 34 | 35 | if NODE_JS_ACTIVE: 36 | 37 | canRunScripts = 0 38 | 39 | nodeInstaller = NodeInstaller(NODE_JS_INSTALLER_URL) 40 | nodeScriptRunner = NodeScriptRunner() 41 | 42 | if platform.system() == "Windows": 43 | print("[COMFYUI_NODEJS] --> NODEJS WAS FOUND IN YOUR OS") 44 | if nodeInstaller.check_for_node_js() is not True: 45 | print("[COMFYUI_NODEJS] --> DOWNLOADING NODEJS") 46 | nodeInstaller.download_nodejs() 47 | print("[COMFYUI_NODEJS] --> INSTALLING NODEJS") 48 | nodeInstaller.install_nodejs() 49 | 50 | canRunScripts = 1 51 | else: 52 | if nodeInstaller.check_for_node_js() is not True: 53 | print("[COMFYUI_NODEJS] --> NODEJS WAS NOT FOUND IN YOUR OS PLEASE INSTALL NODEJS TO RUN THIS NODE CORRECTLY") 54 | else: 55 | canRunScripts = 1 56 | 57 | if canRunScripts: 58 | projects = nodeInstaller.get_dependencies_and_production_scripts(NODE_JS_FOLDER) 59 | 60 | for project_name, project_info in projects.items(): 61 | 62 | dependencies = project_info['dependencies'] 63 | if dependencies: 64 | print(f"[COMFYUI_NODEJS] --> Dependencies for project '{project_name}':") 65 | for dependency, version in dependencies.items(): 66 | version = version.replace('^', '@') 67 | nodeInstaller.install_npm_package(f"{dependency}@{version}") 68 | print(f"{dependency}: {version}") 69 | else: 70 | print(f"No dependencies found for project '{project_name}'") 71 | 72 | for project_name, project_info in projects.items(): 73 | production = project_info['production'] 74 | if production: 75 | print(f"[COMFYUI_NODEJS] --> Script for project '{project_name}':") 76 | nodeScriptRunner.add(os.path.join(NODE_JS_FOLDER, project_name),production.split()) 77 | else: 78 | print(f"No scripts found for project '{project_name}'") 79 | 80 | nodeScriptRunner.run() 81 | 82 | else: 83 | print("[COMFYUI_NODEJS] --> CONTACT DEVELOPER FOR ASSISTANCE") 84 | 85 | NODE_CLASS_MAPPINGS = {} 86 | NODE_DISPLAY_NAME_MAPPINGS = {} 87 | 88 | # WEB_DIRECTORY = "./web" 89 | -------------------------------------------------------------------------------- /classes/NodeInstaller.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Daxton Caylor 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | import os 22 | import json 23 | import requests 24 | import subprocess 25 | import tempfile 26 | from tqdm import tqdm 27 | import shutil 28 | 29 | 30 | class NodeInstaller: 31 | 32 | def __init__(self, installer_url): 33 | self.installer_url = installer_url 34 | self.installer_path = None 35 | 36 | def check_for_node_js(self): 37 | return (shutil.which('node') is not None) 38 | 39 | def download_nodejs(self): 40 | temp_dir = tempfile.gettempdir() 41 | self.installer_path = os.path.join(temp_dir, "nodejs_installer.msi") 42 | response = requests.get(self.installer_url, stream=True) 43 | total_size = int(response.headers.get('content-length', 0)) 44 | block_size = 1024 45 | progress_bar = tqdm(total=total_size, unit='iB', unit_scale=True) 46 | 47 | with open(self.installer_path, 'wb') as file: 48 | for data in response.iter_content(block_size): 49 | progress_bar.update(len(data)) 50 | file.write(data) 51 | 52 | progress_bar.close() 53 | if total_size != 0 and progress_bar.n != total_size: 54 | print("An error occurred during the download.") 55 | else: 56 | print("Node.js installer downloaded successfully.") 57 | 58 | def install_nodejs(self): 59 | if self.installer_path is None: 60 | print("Node.js installer has not been downloaded yet.") 61 | return 62 | process = subprocess.Popen([self.installer_path], shell=True) 63 | process.wait() 64 | 65 | def install_all_packages(self, package_list): 66 | for package_name in package_list: 67 | self.install_npm_package(package_name) 68 | 69 | def install_npm_package(self, package_name): 70 | install_command = f"npm install {package_name}" 71 | 72 | try: 73 | print("") 74 | process = subprocess.Popen( 75 | install_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) 76 | for line in tqdm(iter(process.stdout.readline, b''), desc=f"Installing {package_name}", unit='B', unit_scale=True, leave=False): 77 | pass 78 | process.stdout.close() 79 | process.wait() 80 | print(f"\nnpm package '{package_name}' installed successfully.") 81 | except subprocess.CalledProcessError as e: 82 | print(f"An error occurred: {e}") 83 | 84 | def get_dependencies_and_production_scripts(self, directory_path): 85 | folders_with_info = {} 86 | try: 87 | entries = os.listdir(directory_path) 88 | folders = [entry for entry in entries if os.path.isdir( 89 | os.path.join(directory_path, entry))] 90 | for folder in folders: 91 | folder_path = os.path.join(directory_path, folder) 92 | package_json_path = os.path.join(folder_path, 'package.json') 93 | if os.path.exists(package_json_path): 94 | with open(package_json_path, 'r') as json_file: 95 | data = json.load(json_file) 96 | dependencies = data.get('dependencies', {}) 97 | production_script = data.get('scripts', {}).get('production', None) 98 | folders_with_info[folder] = {'dependencies': dependencies, 'production': production_script} 99 | else: 100 | folders_with_info[folder] = {'dependencies': None, 'production': None} 101 | return folders_with_info 102 | except FileNotFoundError: 103 | return f"The directory {directory_path} does not exist." 104 | except PermissionError: 105 | return f"Permission denied to access the directory {directory_path}." 106 | except Exception as e: 107 | return f"An error occurred: {e}" 108 | -------------------------------------------------------------------------------- /classes/NodeScriptRunner.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Daxton Caylor 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | import shutil 22 | import subprocess 23 | import time 24 | import threading 25 | 26 | 27 | class NodeScriptRunner: 28 | def __init__(self): 29 | self.scripts = [] 30 | self.processes = [] 31 | self.should_run = True 32 | 33 | def check_for_node_js(self): 34 | return shutil.which('node') is not None 35 | 36 | def add(self, cwd, script): 37 | self.scripts.append((cwd, script)) 38 | 39 | def start_script(self, cwd, script): 40 | process = subprocess.Popen(script, cwd=cwd, stdout=None, stderr=None) 41 | self.processes.append((process, cwd, script)) 42 | print(f"Project script '{script}' in '{cwd}' started.") 43 | return process 44 | 45 | def monitor_scripts(self): 46 | while self.should_run: 47 | for i, (process, cwd, script) in enumerate(self.processes): 48 | if process.poll() is not None: # Check if the process has terminated 49 | print(f"Project script '{script}' in '{cwd}' terminated unexpectedly.") 50 | new_process = self.start_script(cwd, script) 51 | self.processes[i] = (new_process, cwd, script) 52 | time.sleep(1) # Check every second 53 | 54 | def run(self): 55 | try: 56 | if not self.check_for_node_js(): 57 | print("Node.js is not installed or not found in the system path.") 58 | return 59 | 60 | for cwd, script in self.scripts: 61 | self.start_script(cwd, script) 62 | 63 | # monitor_thread = threading.Thread(target=self.monitor_scripts) 64 | # monitor_thread.start() 65 | except FileNotFoundError: 66 | print("Node.js is not installed or not found in the system path.") 67 | except Exception as e: 68 | print(f'NodeJS failed to start script. Error: {e}') 69 | 70 | def terminate_background_js(self): 71 | self.should_run = False # Stop monitoring 72 | for process, cwd, script in self.processes: 73 | if process: 74 | process.terminate() 75 | print(f"Project script '{script}' in '{cwd}' terminated.") 76 | else: 77 | print("No background JavaScript process is running.") 78 | 79 | def __del__(self): 80 | self.terminate_background_js() 81 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Daxton Caylor 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | NODE_JS_ACTIVE = True 22 | NODE_JS_INSTALLER_URL = "https://nodejs.org/dist/v20.11.1/node-v20.11.1-x64.msi" 23 | NODE_JS_FOLDER = "nodejs" -------------------------------------------------------------------------------- /nodejs/project1/app.js: -------------------------------------------------------------------------------- 1 | console.log("Project1: Hello") -------------------------------------------------------------------------------- /nodejs/project1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "project1", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "production" : "node app.js" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "express": "^4.19.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /nodejs/project2/app.js: -------------------------------------------------------------------------------- 1 | console.log("Project2: Hello") -------------------------------------------------------------------------------- /nodejs/project2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "project1", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "production" : "node app.js" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "express": "^4.19.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /nodejs/project3/app.js: -------------------------------------------------------------------------------- 1 | console.log("NodeJS: Script is working!") 2 | const express = require('express') 3 | const app = express() 4 | const port = 3000 5 | 6 | app.get('/', (req, res) => { 7 | res.send('i love you 3000!') 8 | }) 9 | 10 | app.listen(port, () => { 11 | console.log(`Example app listening on port ${port}`) 12 | }) -------------------------------------------------------------------------------- /nodejs/project3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "project1", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "production" : "node app.js" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "express": "^4.19.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "comfyui-nodejs" 3 | description = "This node allows the execution of Node.js application within ComfyUI by leveraging the ComfyUI-NODEJS, which starts alongside ComfyUI and facilitates the installation of Node.js. The integration enables Python subprocesses to execute Node.js scripts." 4 | version = "1.0.0" 5 | license = { file = "LICENSE" } 6 | dependencies = [] 7 | 8 | [project.urls] 9 | Repository = "https://github.com/daxcay/ComfyUI-NODEJS" 10 | # Used by Comfy Registry https://comfyregistry.org 11 | 12 | [tool.comfy] 13 | PublisherId = "daxcay" 14 | DisplayName = "ComfyUI-NODEJS" 15 | Icon = "https://raw.githubusercontent.com/daxcay/ComfyUI-NODEJS/main/web/assets/img/logo.jpg" 16 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daxcay/ComfyUI-NODEJS/089d3e8ef63ef609099e5ac3ca6b7d202a0e2fe9/requirements.txt -------------------------------------------------------------------------------- /web/assets/img/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daxcay/ComfyUI-NODEJS/089d3e8ef63ef609099e5ac3ca6b7d202a0e2fe9/web/assets/img/logo.jpg --------------------------------------------------------------------------------