From 59e2a6fb24cabbfb00b7e525202148f811e0fc63 Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Thu, 19 Dec 2024 00:03:30 +1100 Subject: [PATCH 01/19] Ignore shims script (hard forked) --- eslint.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eslint.config.js b/eslint.config.js index 7eeb8416..b620137e 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -6,7 +6,7 @@ import eslintPluginUnicorn from 'eslint-plugin-unicorn'; export default tseslint.config( // Baseline include / exclude { files: ['**/*.{js,cjs,mjs,ts,mts}'] }, - { ignores: ['dist/**/*', 'jest.config.cjs'] }, + { ignores: ['dist/**/*', 'jest.config.cjs', 'scripts/shims/**/*'] }, // Baseline eslint.configs.recommended, From 649535df22445918ec8259ba0d1c942ce0886616 Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Wed, 18 Dec 2024 23:22:39 +1100 Subject: [PATCH 02/19] Format scripts --- .prettierignore | 2 +- scripts/downloadFrontend.js | 68 ++++++++-------- scripts/downloadUV.js | 119 +++++++++++++--------------- scripts/getPackage.js | 4 +- scripts/makeComfy.js | 8 +- scripts/preMake.js | 72 +++++++++-------- scripts/prepareTypes.js | 20 ++--- scripts/releaseTypes.js | 32 ++++---- scripts/resetInstall.js | 17 ++-- scripts/todesktop/afterPack.cjs | 41 +++++----- scripts/todesktop/beforeInstall.cjs | 42 +++++----- scripts/updateFrontend.js | 40 +++++----- 12 files changed, 233 insertions(+), 232 deletions(-) diff --git a/.prettierignore b/.prettierignore index c1a693e5..d8e4670a 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,5 +3,5 @@ out dist assets .vite -scripts +scripts/shims .env_* diff --git a/scripts/downloadFrontend.js b/scripts/downloadFrontend.js index c77ee929..1e18a499 100644 --- a/scripts/downloadFrontend.js +++ b/scripts/downloadFrontend.js @@ -1,15 +1,15 @@ -import axios from 'axios' -import extract from 'extract-zip' -import fs from 'node:fs/promises' -import path from 'node:path' +import axios from 'axios'; +import extract from 'extract-zip'; +import fs from 'node:fs/promises'; +import path from 'node:path'; -import packageJson from './getPackage.js' +import packageJson from './getPackage.js'; // Example "v1.3.34" const version = process.argv[2] || packageJson.config.frontendVersion; if (!version) { - console.error('No version specified'); - process.exit(1); + console.error('No version specified'); + process.exit(1); } const url = `https://github.com/Comfy-Org/ComfyUI_frontend/releases/download/v${version}/dist.zip`; @@ -17,33 +17,33 @@ const downloadPath = 'temp_frontend.zip'; const extractPath = 'assets/ComfyUI/web_custom_versions/desktop_app'; async function downloadAndExtractFrontend() { - try { - // Create directories if they don't exist - await fs.mkdir(extractPath, { recursive: true }); - - // Download the file - console.log('Downloading frontend...'); - const response = await axios({ - method: 'GET', - url: url, - responseType: 'arraybuffer' - }); - - // Save to temporary file - await fs.writeFile(downloadPath, response.data); - - // Extract the zip file - console.log('Extracting frontend...'); - await extract(downloadPath, { dir: path.resolve(extractPath) }); - - // Clean up temporary file - await fs.unlink(downloadPath); - - console.log('Frontend downloaded and extracted successfully!'); - } catch (error) { - console.error('Error downloading frontend:', error.message); - process.exit(1); - } + try { + // Create directories if they don't exist + await fs.mkdir(extractPath, { recursive: true }); + + // Download the file + console.log('Downloading frontend...'); + const response = await axios({ + method: 'GET', + url: url, + responseType: 'arraybuffer', + }); + + // Save to temporary file + await fs.writeFile(downloadPath, response.data); + + // Extract the zip file + console.log('Extracting frontend...'); + await extract(downloadPath, { dir: path.resolve(extractPath) }); + + // Clean up temporary file + await fs.unlink(downloadPath); + + console.log('Frontend downloaded and extracted successfully!'); + } catch (error) { + console.error('Error downloading frontend:', error.message); + process.exit(1); + } } await downloadAndExtractFrontend(); diff --git a/scripts/downloadUV.js b/scripts/downloadUV.js index a99021c6..2ab3cc10 100644 --- a/scripts/downloadUV.js +++ b/scripts/downloadUV.js @@ -1,86 +1,81 @@ -import path from "node:path" -import os from 'node:os' -import fs from 'fs-extra' -import axios from 'axios' -import * as tar from 'tar' -import extractZip from 'extract-zip' -import packageJson from './getPackage.js' +import path from 'node:path'; +import os from 'node:os'; +import fs from 'fs-extra'; +import axios from 'axios'; +import * as tar from 'tar'; +import extractZip from 'extract-zip'; +import packageJson from './getPackage.js'; const uvVer = packageJson.config.uvVersion; /** @typedef {{ [key]: { zipFile: string, uvOutputFolderName: string, zip: boolean } }} UvDownloadOptions */ const options = { - win32: { - zipFile: 'uv-x86_64-pc-windows-msvc.zip', - uvOutputFolderName: 'win', - zip: true, - }, - darwin: { - zipFile: 'uv-aarch64-apple-darwin.tar.gz', - uvOutputFolderName: 'macos', - zip: false, - }, - linux: { - zipFile: 'uv-x86_64-unknown-linux-gnu.tar.gz', - uvOutputFolderName: 'linux', - zip: false, - } -} + win32: { + zipFile: 'uv-x86_64-pc-windows-msvc.zip', + uvOutputFolderName: 'win', + zip: true, + }, + darwin: { + zipFile: 'uv-aarch64-apple-darwin.tar.gz', + uvOutputFolderName: 'macos', + zip: false, + }, + linux: { + zipFile: 'uv-x86_64-unknown-linux-gnu.tar.gz', + uvOutputFolderName: 'linux', + zip: false, + }, +}; async function downloadUV() { - const allFlag = process.argv[2]; const baseDownloadURL = `https://github.com/astral-sh/uv/releases/download/${uvVer}/`; - if (allFlag) - { - if (allFlag === 'all') { - await downloadAndExtract(baseDownloadURL, options.win32); - await downloadAndExtract(baseDownloadURL, options.darwin); - await downloadAndExtract(baseDownloadURL, options.linux); - return; - } - if (allFlag === 'none') { - return; - } + if (allFlag) { + if (allFlag === 'all') { + await downloadAndExtract(baseDownloadURL, options.win32); + await downloadAndExtract(baseDownloadURL, options.darwin); + await downloadAndExtract(baseDownloadURL, options.linux); + return; + } + if (allFlag === 'none') { + return; + } } const uvDownloaded = fs.existsSync(path.join('./assets', 'uv')); if (!uvDownloaded) { - await downloadAndExtract(baseDownloadURL, options[os.platform()]); - return; + await downloadAndExtract(baseDownloadURL, options[os.platform()]); + return; } console.log('< UV Folder Exists, Skipping >'); - -}; +} /** @param {UvDownloadOptions[any]} options */ async function downloadAndExtract(baseURL, options) { - const { - zipFile, - uvOutputFolderName, - zip - } = options; - const zipFilePath = path.join('./assets', zipFile); - const outputUVFolder = path.join('./assets', 'uv', uvOutputFolderName); - await fs.mkdir(outputUVFolder, { - recursive: true - }); - const downloadedFile = await axios({ - method: 'GET', - url: baseURL + zipFile, - responseType: 'arraybuffer' - }); - fs.writeFileSync(zipFilePath, downloadedFile.data); - zip ? await extractZip(zipFilePath, { - dir: path.resolve(outputUVFolder) - }) : tar.extract({ + const { zipFile, uvOutputFolderName, zip } = options; + const zipFilePath = path.join('./assets', zipFile); + const outputUVFolder = path.join('./assets', 'uv', uvOutputFolderName); + await fs.mkdir(outputUVFolder, { + recursive: true, + }); + const downloadedFile = await axios({ + method: 'GET', + url: baseURL + zipFile, + responseType: 'arraybuffer', + }); + fs.writeFileSync(zipFilePath, downloadedFile.data); + zip + ? await extractZip(zipFilePath, { + dir: path.resolve(outputUVFolder), + }) + : tar.extract({ sync: true, file: zipFilePath, C: outputUVFolder, - "strip-components": 1 - }); - await fs.unlink(zipFilePath); - console.log(`FINISHED DOWNLOAD AND EXTRACT UV ${uvOutputFolderName}`); + 'strip-components': 1, + }); + await fs.unlink(zipFilePath); + console.log(`FINISHED DOWNLOAD AND EXTRACT UV ${uvOutputFolderName}`); } //** Download and Extract UV. Default uses OS.Platfrom. Add 'all' will download all. Add 'none' will skip */ diff --git a/scripts/getPackage.js b/scripts/getPackage.js index 52afe4fb..f305ea61 100644 --- a/scripts/getPackage.js +++ b/scripts/getPackage.js @@ -1,7 +1,7 @@ // Read the main package.json -import { createRequire } from "node:module"; +import { createRequire } from 'node:module'; /** @type {import('../package.json')} */ -const packageJson = createRequire(import.meta.url)("../package.json"); +const packageJson = createRequire(import.meta.url)('../package.json'); export default packageJson; diff --git a/scripts/makeComfy.js b/scripts/makeComfy.js index c55eb67b..25000db1 100644 --- a/scripts/makeComfy.js +++ b/scripts/makeComfy.js @@ -1,5 +1,5 @@ -import * as child_process from 'node:child_process' -import pkg from './getPackage.js' +import * as child_process from 'node:child_process'; +import pkg from './getPackage.js'; function makeAssets(gpuFlag) { const baseCommand = [ @@ -12,7 +12,7 @@ function makeAssets(gpuFlag) { '--manager-url', 'https://github.com/Comfy-Org/ComfyUI-Manager', '&&', - 'yarn run make:frontend' + 'yarn run make:frontend', ].join(' '); try { @@ -29,7 +29,7 @@ const gpuFlags = { nvidia: '--nvidia', amd: '--amd', cpu: '--cpu', - macos: '--m-series' + macos: '--m-series', }; if (!arg || !gpuFlags[arg]) { diff --git a/scripts/preMake.js b/scripts/preMake.js index 687e3d4c..bb4fc0e4 100644 --- a/scripts/preMake.js +++ b/scripts/preMake.js @@ -1,40 +1,42 @@ -import { spawnSync } from "node:child_process" -import * as os from 'node:os' -import process from "node:process" -import fs from 'fs-extra' +import { spawnSync } from 'node:child_process'; +import * as os from 'node:os'; +import process from 'node:process'; +import fs from 'fs-extra'; /** @param {{ appOutDir, packager, outDir }} arg0 */ const preMake = () => { - - const firstInstallOnToDesktopServers = - process.env.TODESKTOP_CI && process.env.TODESKTOP_INITIAL_INSTALL_PHASE; - // Do NOT run on CI - if (process.env.CI || firstInstallOnToDesktopServers) return; - - const isNvidia = process.argv.at(-1) === '--nvidia'; - - console.log(``) - - // If this folder is here assume comfy has already been installed - if (fs.existsSync('./assets/ComfyUI')) - { - console.log(">COMFYUI ALREADY BUILT<"); - return - } - - if (os.platform() === 'darwin') { - spawnSync('py -m pip install comfy-cli', [''], { shell: true, stdio:['ignore','ignore','inherit'] }); - spawnSync('yarn run make:assets:macos', [''], { shell: true, stdio: "inherit" }); - } - - if (os.platform() === 'win32') - { - spawnSync('py -m pip install comfy-cli', [''], { shell: true, stdio:['ignore','ignore','inherit'] }); - const result = spawnSync(`python -c "import os,sysconfig;print(sysconfig.get_path(""scripts"",f""{os.name}_user""))"`, [''], { shell: true, stdio: "pipe" }).stdout.toString(); - const localPythonModulePath = `PATH=${result.replaceAll('\\','\\\\').trim()};%PATH%`; - spawnSync(`set ${localPythonModulePath} && yarn run make:assets:${isNvidia ? 'nvidia' : 'cpu'}`, [''], { shell: true, stdio: "inherit" }); - - } - console.log(">PREMAKE FINISH<"); + const firstInstallOnToDesktopServers = process.env.TODESKTOP_CI && process.env.TODESKTOP_INITIAL_INSTALL_PHASE; + // Do NOT run on CI + if (process.env.CI || firstInstallOnToDesktopServers) return; + + const isNvidia = process.argv.at(-1) === '--nvidia'; + + console.log(``); + + // If this folder is here assume comfy has already been installed + if (fs.existsSync('./assets/ComfyUI')) { + console.log('>COMFYUI ALREADY BUILT<'); + return; + } + + if (os.platform() === 'darwin') { + spawnSync('py -m pip install comfy-cli', [''], { shell: true, stdio: ['ignore', 'ignore', 'inherit'] }); + spawnSync('yarn run make:assets:macos', [''], { shell: true, stdio: 'inherit' }); + } + + if (os.platform() === 'win32') { + spawnSync('py -m pip install comfy-cli', [''], { shell: true, stdio: ['ignore', 'ignore', 'inherit'] }); + const result = spawnSync( + `python -c "import os,sysconfig;print(sysconfig.get_path(""scripts"",f""{os.name}_user""))"`, + [''], + { shell: true, stdio: 'pipe' } + ).stdout.toString(); + const localPythonModulePath = `PATH=${result.replaceAll('\\', '\\\\').trim()};%PATH%`; + spawnSync(`set ${localPythonModulePath} && yarn run make:assets:${isNvidia ? 'nvidia' : 'cpu'}`, [''], { + shell: true, + stdio: 'inherit', + }); + } + console.log('>PREMAKE FINISH<'); }; export default preMake; diff --git a/scripts/prepareTypes.js b/scripts/prepareTypes.js index 1a7a0a9f..0cbba76a 100644 --- a/scripts/prepareTypes.js +++ b/scripts/prepareTypes.js @@ -1,6 +1,6 @@ -import fs from 'node:fs' -import path from 'node:path' -import mainPackage from './getPackage.js' +import fs from 'node:fs'; +import path from 'node:path'; +import mainPackage from './getPackage.js'; // Create the types-only package.json const typesPackage = { @@ -8,12 +8,9 @@ const typesPackage = { version: mainPackage.version, main: './index.mjs', types: './index.d.ts', - files: [ - 'index.d.ts', - 'index.mjs' - ], + files: ['index.d.ts', 'index.mjs'], publishConfig: { - access: 'public' + access: 'public', }, repository: mainPackage.repository, homepage: mainPackage.homepage, @@ -29,12 +26,9 @@ if (!fs.existsSync(distDir)) { } // Write the new package.json to the dist directory -fs.writeFileSync( - path.join(distDir, 'package.json'), - JSON.stringify(typesPackage, null, 2) -); +fs.writeFileSync(path.join(distDir, 'package.json'), JSON.stringify(typesPackage, null, 2)); // Create an empty yarn.lock file fs.writeFileSync(path.join(distDir, 'yarn.lock'), ''); -console.log('Types package.json and yarn.lock have been prepared in the dist directory'); \ No newline at end of file +console.log('Types package.json and yarn.lock have been prepared in the dist directory'); diff --git a/scripts/releaseTypes.js b/scripts/releaseTypes.js index 1c9fbda2..506c362b 100644 --- a/scripts/releaseTypes.js +++ b/scripts/releaseTypes.js @@ -1,33 +1,33 @@ -import { execSync } from 'node:child_process' -import { readFileSync } from 'node:fs' +import { execSync } from 'node:child_process'; +import { readFileSync } from 'node:fs'; try { // Create a new branch with version-bump prefix - console.log('Creating new branch...') - const date = new Date().toISOString().split('T')[0] - const timestamp = Date.now() - const branchName = `version-bump-${date}-${timestamp}` - execSync(`git checkout -b ${branchName} -t origin/main`, { stdio: 'inherit' }) + console.log('Creating new branch...'); + const date = new Date().toISOString().split('T')[0]; + const timestamp = Date.now(); + const branchName = `version-bump-${date}-${timestamp}`; + execSync(`git checkout -b ${branchName} -t origin/main`, { stdio: 'inherit' }); // Run npm version patch and capture the output - console.log('Bumping version...') - execSync('yarn version patch', { stdio: 'inherit' }) + console.log('Bumping version...'); + execSync('yarn version patch', { stdio: 'inherit' }); // Read the new version from package.json - const packageJson = JSON.parse(readFileSync('./package.json', 'utf8')) - const newVersion = packageJson.version + const packageJson = JSON.parse(readFileSync('./package.json', 'utf8')); + const newVersion = packageJson.version; // Commit the version bump - execSync(`git commit -am "Bump version ${newVersion}" --no-verify`, { stdio: 'inherit' }) + execSync(`git commit -am "Bump version ${newVersion}" --no-verify`, { stdio: 'inherit' }); // Create the PR - console.log('Creating PR...') + console.log('Creating PR...'); execSync( `gh pr create --title "${newVersion}(types)" --label "ReleaseTypes" --body "Automated version bump to ${newVersion}"`, { stdio: 'inherit' } - ) + ); - console.log(`✅ Successfully created PR for version ${newVersion}`) + console.log(`✅ Successfully created PR for version ${newVersion}`); } catch (error) { - console.error('❌ Error during release process:', error.message) + console.error('❌ Error during release process:', error.message); } diff --git a/scripts/resetInstall.js b/scripts/resetInstall.js index a604a9c9..2d1e905e 100644 --- a/scripts/resetInstall.js +++ b/scripts/resetInstall.js @@ -1,8 +1,8 @@ -import fs from 'node:fs' -import path from 'node:path' -import os from 'node:os' -import * as yaml from 'yaml' -import * as readline from 'node:readline' +import fs from 'node:fs'; +import path from 'node:path'; +import os from 'node:os'; +import * as yaml from 'yaml'; +import * as readline from 'node:readline'; /** * Get the path to the extra_models_config.yaml file based on the platform. @@ -25,11 +25,11 @@ function getConfigPath(filename) { async function askForConfirmation(question) { const rl = readline.createInterface({ input: process.stdin, - output: process.stdout + output: process.stdout, }); - return new Promise(resolve => { - rl.question(question + ' (y/N): ', answer => { + return new Promise((resolve) => { + rl.question(question + ' (y/N): ', (answer) => { rl.close(); resolve(answer.toLowerCase() === 'y'); }); @@ -93,7 +93,6 @@ async function main() { console.log('Skipping ComfyUI directory deletion'); } } - } catch (error) { console.error('Error during reset:', error); process.exit(1); diff --git a/scripts/todesktop/afterPack.cjs b/scripts/todesktop/afterPack.cjs index 37a40fb0..6dc22702 100644 --- a/scripts/todesktop/afterPack.cjs +++ b/scripts/todesktop/afterPack.cjs @@ -5,36 +5,41 @@ const { spawnSync } = require('child_process'); module.exports = async ({ appOutDir, packager, outDir }) => { /** - * appPkgName - string - the name of the app package - * appId - string - the app id - * shouldCodeSign - boolean - whether the app will be code signed or not - * outDir - string - the path to the output directory - * appOutDir - string - the path to the app output directory - * packager - object - the packager object - * arch - number - the architecture of the app. ia32 = 0, x64 = 1, armv7l = 2, arm64 = 3, universal = 4. - */ + * appPkgName - string - the name of the app package + * appId - string - the app id + * shouldCodeSign - boolean - whether the app will be code signed or not + * outDir - string - the path to the output directory + * appOutDir - string - the path to the app output directory + * packager - object - the packager object + * arch - number - the architecture of the app. ia32 = 0, x64 = 1, armv7l = 2, arm64 = 3, universal = 4. + */ // The purpose of this script is to move comfy files from assets to the resource folder of the app // We can not add them to extraFiles as that is done prior to building, where we need to move them AFTER - if (os.platform() === "darwin") { + if (os.platform() === 'darwin') { const appName = packager.appInfo.productFilename; const appPath = path.join(`${appOutDir}`, `${appName}.app`); const mainPath = path.dirname(outDir); const assetPath = path.join(mainPath, 'app-wrapper', 'app', 'assets'); - const resourcePath = path.join(appPath, "Contents", "Resources"); + const resourcePath = path.join(appPath, 'Contents', 'Resources'); // Remove these Git folders that mac's codesign is choking on. Need a more recursive way to just find all folders with '.git' and delete - await fs.rm(path.join(assetPath, "ComfyUI", ".git"), { recursive: true, force: true }); - await fs.rm(path.join(assetPath, "ComfyUI", 'custom_nodes', 'ComfyUI-Manager', ".git"), { recursive: true, force: true }); - await fs.rm(path.join(assetPath, "ComfyUI", 'custom_nodes', 'DesktopSettingsExtension', ".git"), { recursive: true, force: true }); - // Move rest of items to the resource folder + await fs.rm(path.join(assetPath, 'ComfyUI', '.git'), { recursive: true, force: true }); + await fs.rm(path.join(assetPath, 'ComfyUI', 'custom_nodes', 'ComfyUI-Manager', '.git'), { + recursive: true, + force: true, + }); + await fs.rm(path.join(assetPath, 'ComfyUI', 'custom_nodes', 'DesktopSettingsExtension', '.git'), { + recursive: true, + force: true, + }); + // Move rest of items to the resource folder await fs.cp(assetPath, resourcePath, { recursive: true }); // Remove other OS's UV await fs.rm(path.join(resourcePath, 'uv', 'win'), { recursive: true, force: true }); await fs.rm(path.join(resourcePath, 'uv', 'linux'), { recursive: true, force: true }); await fs.chmod(path.join(resourcePath, 'uv', 'macos', 'uv'), '755'); await fs.chmod(path.join(resourcePath, 'uv', 'macos', 'uvx'), '755'); - } if (os.platform() === 'win32') { @@ -42,8 +47,8 @@ module.exports = async ({ appOutDir, packager, outDir }) => { const appPath = path.join(`${appOutDir}`, `${appName}.exe`); const mainPath = path.dirname(outDir); const assetPath = path.join(mainPath, 'app-wrapper', 'app', 'assets'); - const resourcePath = path.join(path.dirname(appPath), "resources"); - // Move rest of items to the resource folder + const resourcePath = path.join(path.dirname(appPath), 'resources'); + // Move rest of items to the resource folder await fs.cp(assetPath, resourcePath, { recursive: true }); // Remove other OS's UV await fs.rm(path.join(resourcePath, 'uv', 'macos'), { recursive: true, force: true }); @@ -51,4 +56,4 @@ module.exports = async ({ appOutDir, packager, outDir }) => { } //TODO: Linux -} +}; diff --git a/scripts/todesktop/beforeInstall.cjs b/scripts/todesktop/beforeInstall.cjs index 4bc85066..dd792185 100644 --- a/scripts/todesktop/beforeInstall.cjs +++ b/scripts/todesktop/beforeInstall.cjs @@ -1,23 +1,29 @@ -const { spawnSync } = require("child_process"); -const path = require("path"); +const { spawnSync } = require('child_process'); +const path = require('path'); const os = require('os'); module.exports = async ({ pkgJsonPath, pkgJson, appDir, hookName }) => { - /** - * pkgJsonPath - string - path to the package.json file - * pkgJson - object - the parsed package.json file - * appDir - string - the path to the app directory - * hookName - string - the name of the hook ("todesktop:beforeInstall" or "todesktop:afterPack") - */ + /** + * pkgJsonPath - string - path to the package.json file + * pkgJson - object - the parsed package.json file + * appDir - string - the path to the app directory + * hookName - string - the name of the hook ("todesktop:beforeInstall" or "todesktop:afterPack") + */ - console.log('Before Yarn Install' , os.platform()); + console.log('Before Yarn Install', os.platform()); - if (os.platform() === "win32") - { - // ToDesktop currently does not have the min 3.12 python installed. - // Download the installer then install it - // Change stdio to get back the logs if there are issues. - const result1 = spawnSync('curl' ,['-s', 'https://www.python.org/ftp/python/3.12.7/python-3.12.7-amd64.exe'],{shell:true,stdio: 'ignore'}).toString(); - const result2 = spawnSync('python-3.12.7-amd64.exe', ['/quiet', 'InstallAllUsers=1','PrependPath=1', 'Include_test=0'],{shell:true,stdio: 'ignore'}).toString(); - } -}; \ No newline at end of file + if (os.platform() === 'win32') { + // ToDesktop currently does not have the min 3.12 python installed. + // Download the installer then install it + // Change stdio to get back the logs if there are issues. + const result1 = spawnSync('curl', ['-s', 'https://www.python.org/ftp/python/3.12.7/python-3.12.7-amd64.exe'], { + shell: true, + stdio: 'ignore', + }).toString(); + const result2 = spawnSync( + 'python-3.12.7-amd64.exe', + ['/quiet', 'InstallAllUsers=1', 'PrependPath=1', 'Include_test=0'], + { shell: true, stdio: 'ignore' } + ).toString(); + } +}; diff --git a/scripts/updateFrontend.js b/scripts/updateFrontend.js index d6795ddc..70fe2b85 100644 --- a/scripts/updateFrontend.js +++ b/scripts/updateFrontend.js @@ -1,40 +1,40 @@ -import { execSync } from 'node:child_process' -import { readFileSync, writeFileSync } from 'node:fs' +import { execSync } from 'node:child_process'; +import { readFileSync, writeFileSync } from 'node:fs'; async function main() { try { // Create a new branch with version-bump prefix - console.log('Creating new branch...') - const date = new Date().toISOString().split('T')[0] - const timestamp = Date.now() - const branchName = `version-bump-${date}-${timestamp}` - execSync(`git checkout -b ${branchName} -t origin/main`, { stdio: 'inherit' }) + console.log('Creating new branch...'); + const date = new Date().toISOString().split('T')[0]; + const timestamp = Date.now(); + const branchName = `version-bump-${date}-${timestamp}`; + execSync(`git checkout -b ${branchName} -t origin/main`, { stdio: 'inherit' }); // Get latest frontend release: https://github.com/Comfy-Org/ComfyUI_frontend/releases - const latestRelease = 'https://api.github.com/repos/Comfy-Org/ComfyUI_frontend/releases/latest' - const latestReleaseData = await fetch(latestRelease) - const latestReleaseTag = (await latestReleaseData.json()).tag_name - const version = latestReleaseTag.replace('v', '') + const latestRelease = 'https://api.github.com/repos/Comfy-Org/ComfyUI_frontend/releases/latest'; + const latestReleaseData = await fetch(latestRelease); + const latestReleaseTag = (await latestReleaseData.json()).tag_name; + const version = latestReleaseTag.replace('v', ''); // Update frontend version in package.json - const packageJson = JSON.parse(readFileSync('./package.json', 'utf8')) - packageJson.config.frontendVersion = version - writeFileSync('./package.json', JSON.stringify(packageJson, null, 2)) + const packageJson = JSON.parse(readFileSync('./package.json', 'utf8')); + packageJson.config.frontendVersion = version; + writeFileSync('./package.json', JSON.stringify(packageJson, null, 2)); // Commit the version bump - execSync(`git commit -am "[chore] Update frontend to ${version}"`, { stdio: 'inherit' }) + execSync(`git commit -am "[chore] Update frontend to ${version}"`, { stdio: 'inherit' }); // Create the PR - console.log('Creating PR...') + console.log('Creating PR...'); execSync( `gh pr create --title "[chore] Update frontend to ${version}" --label "dependencies" --body "Automated frontend update to ${version}"`, { stdio: 'inherit' } - ) + ); - console.log(`✅ Successfully created PR for frontend ${version}`) + console.log(`✅ Successfully created PR for frontend ${version}`); } catch (error) { - console.error('❌ Error during release process:', error.message) + console.error('❌ Error during release process:', error.message); } } -main() +main(); From 30d8e6f8cc60d2dacf2ddfe701dd1c1825cc0705 Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Wed, 18 Dec 2024 23:23:10 +1100 Subject: [PATCH 03/19] Remove redundant code --- scripts/todesktop/beforeInstall.cjs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/scripts/todesktop/beforeInstall.cjs b/scripts/todesktop/beforeInstall.cjs index dd792185..ccd678b1 100644 --- a/scripts/todesktop/beforeInstall.cjs +++ b/scripts/todesktop/beforeInstall.cjs @@ -16,14 +16,13 @@ module.exports = async ({ pkgJsonPath, pkgJson, appDir, hookName }) => { // ToDesktop currently does not have the min 3.12 python installed. // Download the installer then install it // Change stdio to get back the logs if there are issues. - const result1 = spawnSync('curl', ['-s', 'https://www.python.org/ftp/python/3.12.7/python-3.12.7-amd64.exe'], { + spawnSync('curl', ['-s', 'https://www.python.org/ftp/python/3.12.7/python-3.12.7-amd64.exe'], { shell: true, stdio: 'ignore', - }).toString(); - const result2 = spawnSync( - 'python-3.12.7-amd64.exe', - ['/quiet', 'InstallAllUsers=1', 'PrependPath=1', 'Include_test=0'], - { shell: true, stdio: 'ignore' } - ).toString(); + }); + spawnSync('python-3.12.7-amd64.exe', ['/quiet', 'InstallAllUsers=1', 'PrependPath=1', 'Include_test=0'], { + shell: true, + stdio: 'ignore', + }); } }; From 617e57a867e4baaa8706df8b4feba61ddcdbb1cc Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Thu, 19 Dec 2024 00:01:24 +1100 Subject: [PATCH 04/19] [Refactor] Remove ternary statement --- scripts/downloadUV.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/scripts/downloadUV.js b/scripts/downloadUV.js index 2ab3cc10..a9ba4b5c 100644 --- a/scripts/downloadUV.js +++ b/scripts/downloadUV.js @@ -64,16 +64,16 @@ async function downloadAndExtract(baseURL, options) { responseType: 'arraybuffer', }); fs.writeFileSync(zipFilePath, downloadedFile.data); - zip - ? await extractZip(zipFilePath, { - dir: path.resolve(outputUVFolder), - }) - : tar.extract({ - sync: true, - file: zipFilePath, - C: outputUVFolder, - 'strip-components': 1, - }); + if (zip) { + await extractZip(zipFilePath, { dir: path.resolve(outputUVFolder) }); + } else { + tar.extract({ + sync: true, + file: zipFilePath, + C: outputUVFolder, + 'strip-components': 1, + }); + } await fs.unlink(zipFilePath); console.log(`FINISHED DOWNLOAD AND EXTRACT UV ${uvOutputFolderName}`); } From 5c67a140d9014a4efa95e3f048d283e218a5ccf1 Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Thu, 19 Dec 2024 00:01:54 +1100 Subject: [PATCH 05/19] Add ESM top-level await --- scripts/resetInstall.js | 2 +- scripts/updateFrontend.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/resetInstall.js b/scripts/resetInstall.js index 2d1e905e..d04fee49 100644 --- a/scripts/resetInstall.js +++ b/scripts/resetInstall.js @@ -99,4 +99,4 @@ async function main() { } } -main(); +await main(); diff --git a/scripts/updateFrontend.js b/scripts/updateFrontend.js index 70fe2b85..5e769692 100644 --- a/scripts/updateFrontend.js +++ b/scripts/updateFrontend.js @@ -37,4 +37,4 @@ async function main() { } } -main(); +await main(); From c51ee3f47e321baca5bd32bbfd0138c8dc845927 Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Thu, 19 Dec 2024 00:02:52 +1100 Subject: [PATCH 06/19] Add TS types, clean up --- scripts/resetInstall.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/resetInstall.js b/scripts/resetInstall.js index d04fee49..2fee29c5 100644 --- a/scripts/resetInstall.js +++ b/scripts/resetInstall.js @@ -22,7 +22,8 @@ function getConfigPath(filename) { } } -async function askForConfirmation(question) { +/** @returns {Promise} */ +function askForConfirmation(question) { const rl = readline.createInterface({ input: process.stdin, output: process.stdout, @@ -41,12 +42,15 @@ async function main() { const configPath = getConfigPath('config.json'); const windowStorePath = getConfigPath('window.json'); const modelsConfigPath = getConfigPath('extra_models_config.yaml'); - let desktopBasePath = null; - let basePath = null; + let desktopBasePath; + /** @type {string | undefined} */ + let basePath; // Read basePath from desktop config if (fs.existsSync(configPath)) { const configContent = fs.readFileSync(configPath, 'utf8'); + + /** @type {import('../src/store/index').DesktopSettings} */ const parsed = JSON.parse(configContent); desktopBasePath = parsed?.basePath; } From fc93d52934006f8ff02d550be2dd9db9acfb19e1 Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Thu, 19 Dec 2024 00:04:01 +1100 Subject: [PATCH 07/19] Ignore ESLint warnings in scripts --- scripts/downloadFrontend.js | 1 + scripts/downloadUV.js | 2 ++ scripts/getPackage.js | 1 + scripts/launchdev.js | 1 + scripts/releaseTypes.js | 2 ++ scripts/resetInstall.js | 3 +++ scripts/updateFrontend.js | 4 ++++ 7 files changed, 14 insertions(+) diff --git a/scripts/downloadFrontend.js b/scripts/downloadFrontend.js index 1e18a499..245cd498 100644 --- a/scripts/downloadFrontend.js +++ b/scripts/downloadFrontend.js @@ -30,6 +30,7 @@ async function downloadAndExtractFrontend() { }); // Save to temporary file + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument await fs.writeFile(downloadPath, response.data); // Extract the zip file diff --git a/scripts/downloadUV.js b/scripts/downloadUV.js index a9ba4b5c..10a7ed26 100644 --- a/scripts/downloadUV.js +++ b/scripts/downloadUV.js @@ -44,6 +44,7 @@ async function downloadUV() { const uvDownloaded = fs.existsSync(path.join('./assets', 'uv')); if (!uvDownloaded) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument await downloadAndExtract(baseDownloadURL, options[os.platform()]); return; } @@ -63,6 +64,7 @@ async function downloadAndExtract(baseURL, options) { url: baseURL + zipFile, responseType: 'arraybuffer', }); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument fs.writeFileSync(zipFilePath, downloadedFile.data); if (zip) { await extractZip(zipFilePath, { dir: path.resolve(outputUVFolder) }); diff --git a/scripts/getPackage.js b/scripts/getPackage.js index f305ea61..44e81733 100644 --- a/scripts/getPackage.js +++ b/scripts/getPackage.js @@ -2,6 +2,7 @@ import { createRequire } from 'node:module'; /** @type {import('../package.json')} */ +// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const packageJson = createRequire(import.meta.url)('../package.json'); export default packageJson; diff --git a/scripts/launchdev.js b/scripts/launchdev.js index 732992cb..4deb8980 100644 --- a/scripts/launchdev.js +++ b/scripts/launchdev.js @@ -43,6 +43,7 @@ function setupMainPackageWatcher() { : ['--inspect=9223']; /** Spawn new electron process */ + // eslint-disable-next-line @typescript-eslint/no-base-to-string electronApp = spawn(String(electronPath), [...args, '.'], { stdio: 'inherit', }); diff --git a/scripts/releaseTypes.js b/scripts/releaseTypes.js index 506c362b..70390024 100644 --- a/scripts/releaseTypes.js +++ b/scripts/releaseTypes.js @@ -14,7 +14,9 @@ try { execSync('yarn version patch', { stdio: 'inherit' }); // Read the new version from package.json + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const packageJson = JSON.parse(readFileSync('./package.json', 'utf8')); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access const newVersion = packageJson.version; // Commit the version bump diff --git a/scripts/resetInstall.js b/scripts/resetInstall.js index 2fee29c5..4c66e161 100644 --- a/scripts/resetInstall.js +++ b/scripts/resetInstall.js @@ -51,6 +51,7 @@ async function main() { const configContent = fs.readFileSync(configPath, 'utf8'); /** @type {import('../src/store/index').DesktopSettings} */ + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const parsed = JSON.parse(configContent); desktopBasePath = parsed?.basePath; } @@ -58,7 +59,9 @@ async function main() { // Read base_path before deleting the config file if (fs.existsSync(modelsConfigPath)) { const configContent = fs.readFileSync(modelsConfigPath, 'utf8'); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const config = yaml.parse(configContent); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access basePath = config?.comfyui?.base_path; } else { console.log('Config file not found, nothing to remove'); diff --git a/scripts/updateFrontend.js b/scripts/updateFrontend.js index 5e769692..9bf62c2c 100644 --- a/scripts/updateFrontend.js +++ b/scripts/updateFrontend.js @@ -13,11 +13,15 @@ async function main() { // Get latest frontend release: https://github.com/Comfy-Org/ComfyUI_frontend/releases const latestRelease = 'https://api.github.com/repos/Comfy-Org/ComfyUI_frontend/releases/latest'; const latestReleaseData = await fetch(latestRelease); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, unicorn/no-await-expression-member, @typescript-eslint/no-unsafe-member-access const latestReleaseTag = (await latestReleaseData.json()).tag_name; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access const version = latestReleaseTag.replace('v', ''); // Update frontend version in package.json + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const packageJson = JSON.parse(readFileSync('./package.json', 'utf8')); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access packageJson.config.frontendVersion = version; writeFileSync('./package.json', JSON.stringify(packageJson, null, 2)); From 0453b59cbeb5739f7b5a8928967f9f73a6ce5dbf Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Thu, 19 Dec 2024 00:07:50 +1100 Subject: [PATCH 08/19] Remove redundant code --- tests/unit/main.test.ts | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/tests/unit/main.test.ts b/tests/unit/main.test.ts index 908a9eda..daf116a8 100644 --- a/tests/unit/main.test.ts +++ b/tests/unit/main.test.ts @@ -1,9 +1,7 @@ import { expect, jest, describe, it } from '@jest/globals'; jest.mock('node:path', () => ({ - join: jest.fn((...args) => { - return 'preload.js'; - }), + join: jest.fn(() => 'preload.js'), })); jest.mock('@sentry/electron/main', () => ({ @@ -39,15 +37,13 @@ jest.mock('electron', () => ({ getPath: jest.fn(), requestSingleInstanceLock: jest.fn().mockReturnValue(true), }, - BrowserWindow: jest.fn().mockImplementation((options) => { - return { - loadURL: jest.fn(), - on: jest.fn(), - webContents: { - openDevTools: jest.fn(), - }, - }; - }), + BrowserWindow: jest.fn().mockImplementation(() => ({ + loadURL: jest.fn(), + on: jest.fn(), + webContents: { + openDevTools: jest.fn(), + }, + })), ipcMain: { on: jest.fn(), handle: jest.fn(), From 701fc4d54a75848b089d0b329886ca6664e76e64 Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Thu, 19 Dec 2024 00:30:35 +1100 Subject: [PATCH 09/19] Lint tests --- eslint.config.js | 9 +++++++++ tests/e2e/startup.test.ts | 8 +++----- tests/unit/handlers/appinfoHandlers.test.ts | 4 ++-- tests/unit/handlers/pathHandler.test.ts | 8 ++++---- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index b620137e..abc5d5b6 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -60,5 +60,14 @@ export default tseslint.config( rules: { 'unicorn/no-process-exit': 'off', }, + }, + + // Tests + { + files: ['tests/**/*'], + rules: { + 'unicorn/prefer-module': 'off', + '@typescript-eslint/unbound-method': 'off', + }, } ); diff --git a/tests/e2e/startup.test.ts b/tests/e2e/startup.test.ts index e1d87ca0..44485ee6 100644 --- a/tests/e2e/startup.test.ts +++ b/tests/e2e/startup.test.ts @@ -9,11 +9,9 @@ test('launch app', async () => { console.error(`Electron stderr: ${data}`); }); - const isPackaged = await electronApp.evaluate(async ({ app }) => { - // This runs in Electron's main process, parameter here is always - // the result of the require('electron') in the main app script. - return app.isPackaged; - }); + // This runs in Electron's main process, parameter here is always + // the result of the require('electron') in the main app script. + const isPackaged = await electronApp.evaluate(({ app }) => app.isPackaged); expect(isPackaged).toBe(false); diff --git a/tests/unit/handlers/appinfoHandlers.test.ts b/tests/unit/handlers/appinfoHandlers.test.ts index 60b35532..f2c4fc9f 100644 --- a/tests/unit/handlers/appinfoHandlers.test.ts +++ b/tests/unit/handlers/appinfoHandlers.test.ts @@ -19,8 +19,8 @@ describe('AppInfoHandlers', () => { it('should register all expected handle channels', () => { const expectedChannels = [IPC_CHANNELS.IS_PACKAGED, IPC_CHANNELS.GET_ELECTRON_VERSION]; - expectedChannels.forEach((channel) => { + for (const channel of expectedChannels) { expect(ipcMain.handle).toHaveBeenCalledWith(channel, expect.any(Function)); - }); + } }); }); diff --git a/tests/unit/handlers/pathHandler.test.ts b/tests/unit/handlers/pathHandler.test.ts index 7238b2bf..7e4d342b 100644 --- a/tests/unit/handlers/pathHandler.test.ts +++ b/tests/unit/handlers/pathHandler.test.ts @@ -20,16 +20,16 @@ describe('PathHandlers', () => { it('should register all expected handle channels', () => { const expectedChannelsForHandle = [IPC_CHANNELS.GET_MODEL_CONFIG_PATH]; - expectedChannelsForHandle.forEach((channel) => { + for (const channel of expectedChannelsForHandle) { expect(ipcMain.handle).toHaveBeenCalledWith(channel, expect.any(Function)); - }); + } }); it('should register all expected on channels', () => { const expectedChannelsForOn = [IPC_CHANNELS.OPEN_LOGS_PATH, IPC_CHANNELS.OPEN_PATH]; - expectedChannelsForOn.forEach((channel) => { + for (const channel of expectedChannelsForOn) { expect(ipcMain.on).toHaveBeenCalledWith(channel, expect.any(Function)); - }); + } }); }); From f508a0ea577afd967524b0963d1bb971add07a11 Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Thu, 19 Dec 2024 01:03:44 +1100 Subject: [PATCH 10/19] Remove stylistic ESLint rule !array.length is acceptable here. --- eslint.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/eslint.config.js b/eslint.config.js index abc5d5b6..a46e7fa7 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -51,6 +51,7 @@ export default tseslint.config( 'unicorn/no-null': 'off', 'unicorn/prevent-abbreviations': 'off', 'unicorn/switch-case-braces': 'off', + 'unicorn/explicit-length-check': 'off', }, }, From 6a98ec58787886aef7fce9b825207c1db8aee994 Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Thu, 19 Dec 2024 01:05:26 +1100 Subject: [PATCH 11/19] Ignore ESLint errors on yaml parsing No easy solution here; this is already in the wild. Needs proper reimplementation at some point. --- src/config/comfyServerConfig.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/config/comfyServerConfig.ts b/src/config/comfyServerConfig.ts index 7982c936..0a344bcb 100644 --- a/src/config/comfyServerConfig.ts +++ b/src/config/comfyServerConfig.ts @@ -140,8 +140,9 @@ export class ComfyServerConfig { public static async readConfigFile(configPath: string): Promise | null> { try { const fileContent = await fsPromises.readFile(configPath, 'utf8'); - const config = yaml.parse(fileContent); - return config; + // TODO: Reimplement with validation and error reporting. + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return yaml.parse(fileContent); } catch (error) { log.error(`Error reading config file ${configPath}:`, error); return null; @@ -188,9 +189,12 @@ export class ComfyServerConfig { public static async readBasePathFromConfig(configPath: string): Promise { try { const fileContent = await fsPromises.readFile(configPath, 'utf8'); + // TODO: Reimplement with validation and error reporting. + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const config = yaml.parse(fileContent); // Fallback to legacy yaml format, where we have everything under root 'comfyui'. + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access const base_path = config?.comfyui_desktop?.base_path ?? config?.comfyui?.base_path; if (typeof base_path !== 'string') { log.warn(`Base path in YAML config was invalid: [${ComfyServerConfig.configPath}]`); From 26decb277eef3b681e1caf8c9602872f1ce1df68 Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Thu, 19 Dec 2024 02:01:36 +1100 Subject: [PATCH 12/19] nit --- src/config/comfySettings.ts | 2 ++ src/main-process/comfyDesktopApp.ts | 2 +- src/main-process/comfyServer.ts | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/config/comfySettings.ts b/src/config/comfySettings.ts index 6e492319..cdfe5728 100644 --- a/src/config/comfySettings.ts +++ b/src/config/comfySettings.ts @@ -41,6 +41,8 @@ export class ComfySettings { } try { const fileContent = await fs.readFile(this.filePath, 'utf8'); + // TODO: Reimplement with validation and error reporting. + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment this.settings = JSON.parse(fileContent); } catch (error) { log.error(`Settings file cannot be loaded.`, error); diff --git a/src/main-process/comfyDesktopApp.ts b/src/main-process/comfyDesktopApp.ts index e94034f7..9bc13d15 100644 --- a/src/main-process/comfyDesktopApp.ts +++ b/src/main-process/comfyDesktopApp.ts @@ -9,7 +9,7 @@ import { AppWindow } from './appWindow'; import { ComfyServer } from './comfyServer'; import { ComfyServerConfig } from '../config/comfyServerConfig'; import fs from 'node:fs'; -import { InstallOptions, type ElectronContextMenuOptions, type TorchDeviceType } from '../preload'; +import { InstallOptions, type ElectronContextMenuOptions } from '../preload'; import path from 'node:path'; import { ansiCodes, getModelsDirectory, validateHardware } from '../utils'; import { DownloadManager } from '../models/DownloadManager'; diff --git a/src/main-process/comfyServer.ts b/src/main-process/comfyServer.ts index 40a1550d..ff6066d4 100644 --- a/src/main-process/comfyServer.ts +++ b/src/main-process/comfyServer.ts @@ -103,9 +103,9 @@ export class ComfyServer { comfyUILog.transports.file.fileName = 'comfyui.log'; // TODO: Check if electron-log has updated types + // @ts-expect-error electron-log types are broken. data and return type are `string`. comfyUILog.transports.file.transforms.push(({ data }) => { - // @ts-expect-error electron-log types are broken. data and return type are `string`. - return typeof data === 'string' ? data.replaceAll(ansiCodes, '') : data; + return typeof data === 'string' ? (data as string).replaceAll(ansiCodes, '') : data; }); const comfyServerProcess = this.virtualEnvironment.runPythonCommand(this.launchArgs, { From cd5cd39d7c6e581f57b24813926c2f7f49f59050 Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Thu, 19 Dec 2024 02:03:19 +1100 Subject: [PATCH 13/19] [Refactor] if-else => switch --- src/virtualEnvironment.ts | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/virtualEnvironment.ts b/src/virtualEnvironment.ts index 1511d9e7..fe1b8de2 100644 --- a/src/virtualEnvironment.ts +++ b/src/virtualEnvironment.ts @@ -80,14 +80,18 @@ export class VirtualEnvironment { ? path.join(process.resourcesPath, 'uv') : path.join(app.getAppPath(), 'assets', 'uv'); - if (process.platform === 'win32') { - this.uvPath = path.join(uvFolder, 'win', 'uv.exe'); - } else if (process.platform === 'linux') { - this.uvPath = path.join(uvFolder, 'linux', 'uv'); - } else if (process.platform === 'darwin') { - this.uvPath = path.join(uvFolder, 'macos', 'uv'); - } else { - throw new Error(`Unsupported platform: ${process.platform}`); + switch (process.platform) { + case 'win32': + this.uvPath = path.join(uvFolder, 'win', 'uv.exe'); + break; + case 'linux': + this.uvPath = path.join(uvFolder, 'linux', 'uv'); + break; + case 'darwin': + this.uvPath = path.join(uvFolder, 'macos', 'uv'); + break; + default: + throw new Error(`Unsupported platform: ${process.platform}`); } log.info(`Using uv at ${this.uvPath}`); From 6c23235c3674c1c15e00ba1de1bda07a8465dc41 Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Wed, 18 Dec 2024 12:10:29 +1100 Subject: [PATCH 14/19] [Refactor] Remove redundant code --- src/store/desktopConfig.ts | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/store/desktopConfig.ts b/src/store/desktopConfig.ts index 35dcb435..cf4a99c3 100644 --- a/src/store/desktopConfig.ts +++ b/src/store/desktopConfig.ts @@ -91,26 +91,16 @@ export class DesktopConfig { * @returns A promise that resolves on successful save, or rejects with the first caught error. */ async setAsync(key: Key, value: DesktopSettings[Key]): Promise { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { log.info(`Saving setting: [${key}]`, value); - try { - this.#store.set(key, value); - resolve(); - } catch (error) { - reject(error); - } + this.#store.set(key, value); + resolve(); }); } /** @inheritdoc {@link ElectronStore.get} */ async getAsync(key: Key): Promise { - return new Promise((resolve, reject) => { - try { - resolve(this.#store.get(key)); - } catch (error) { - reject(error); - } - }); + return new Promise((resolve) => resolve(this.#store.get(key))); } } From eee902106f064d1e15916667bf2996568d6553df Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Thu, 19 Dec 2024 03:21:22 +1100 Subject: [PATCH 15/19] Remove unnecessary use of static class --- src/install/installationValidator.ts | 2 +- src/main-process/comfyDesktopApp.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/install/installationValidator.ts b/src/install/installationValidator.ts index 2c7ec75e..c2f0c07b 100644 --- a/src/install/installationValidator.ts +++ b/src/install/installationValidator.ts @@ -13,7 +13,7 @@ export class InstallationValidator { * @param options The options paramter of {@link dialog.showMessageBox}, filled with defaults for invalid config * @returns */ - static async showInvalidFileAndQuit(file: string, options: MessageBoxOptions): Promise { + async showInvalidFileAndQuit(file: string, options: MessageBoxOptions): Promise { const defaults: Partial = { title: 'Invalid file', type: 'error', diff --git a/src/main-process/comfyDesktopApp.ts b/src/main-process/comfyDesktopApp.ts index 9bc13d15..2424b1da 100644 --- a/src/main-process/comfyDesktopApp.ts +++ b/src/main-process/comfyDesktopApp.ts @@ -290,7 +290,7 @@ export class ComfyDesktopApp { default: // 'error': Explain and quit // TODO: Support link? Something? - await InstallationValidator.showInvalidFileAndQuit(ComfyServerConfig.configPath, { + await new InstallationValidator().showInvalidFileAndQuit(ComfyServerConfig.configPath, { message: `Unable to read the YAML configuration file. Please ensure this file is available and can be read: ${ComfyServerConfig.configPath} From 61d378aff56d222dd6c1c4c0c3462e94809b22b3 Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Thu, 19 Dec 2024 03:22:18 +1100 Subject: [PATCH 16/19] Annotate remaining low-priority ESLint items --- src/handlers/pathHandlers.ts | 3 +++ src/install/installWizard.ts | 7 +++++-- src/main-process/appWindow.ts | 5 +++++ src/main-process/comfyDesktopApp.ts | 4 ++++ src/preload.ts | 4 ++++ 5 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/handlers/pathHandlers.ts b/src/handlers/pathHandlers.ts index 8e33d39d..0c4e71cd 100644 --- a/src/handlers/pathHandlers.ts +++ b/src/handlers/pathHandlers.ts @@ -15,6 +15,7 @@ export class PathHandlers { registerHandlers() { ipcMain.on(IPC_CHANNELS.OPEN_LOGS_PATH, (): void => { + // eslint-disable-next-line @typescript-eslint/no-floating-promises shell.openPath(app.getPath('logs')); }); @@ -24,6 +25,7 @@ export class PathHandlers { ipcMain.on(IPC_CHANNELS.OPEN_PATH, (event, folderPath: string): void => { log.info(`Opening path: ${folderPath}`); + // eslint-disable-next-line @typescript-eslint/no-floating-promises shell.openPath(folderPath); }); @@ -86,6 +88,7 @@ export class PathHandlers { */ ipcMain.handle( IPC_CHANNELS.VALIDATE_COMFYUI_SOURCE, + // eslint-disable-next-line @typescript-eslint/require-await async (event, path: string): Promise<{ isValid: boolean; error?: string }> => { const isValid = ComfyConfigManager.isComfyUIDirectory(path); return { diff --git a/src/install/installWizard.ts b/src/install/installWizard.ts index b82cd41a..6bd90526 100644 --- a/src/install/installWizard.ts +++ b/src/install/installWizard.ts @@ -2,7 +2,7 @@ import path from 'node:path'; import log from 'electron-log/main'; import fs from 'node:fs'; import { InstallOptions } from '../preload'; -import { DEFAULT_SETTINGS } from '../config/comfySettings'; +import { DEFAULT_SETTINGS, type ComfySettingsData } from '../config/comfySettings'; import { ComfyServerConfig, ModelPaths } from '../config/comfyServerConfig'; import { ComfyConfigManager } from '../config/comfyConfigManager'; @@ -55,7 +55,10 @@ export class InstallWizard { */ public initializeSettings() { const settingsPath = path.join(this.basePath, 'user', 'default', 'comfy.settings.json'); - const existingSettings = fs.existsSync(settingsPath) ? JSON.parse(fs.readFileSync(settingsPath, 'utf8')) : {}; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const existingSettings: ComfySettingsData = fs.existsSync(settingsPath) + ? JSON.parse(fs.readFileSync(settingsPath, 'utf8')) + : {}; const settings = { ...DEFAULT_SETTINGS, diff --git a/src/main-process/appWindow.ts b/src/main-process/appWindow.ts index 249f085d..34538949 100644 --- a/src/main-process/appWindow.ts +++ b/src/main-process/appWindow.ts @@ -45,6 +45,7 @@ export class AppWindow { x: storedX, y: storedY, webPreferences: { + // eslint-disable-next-line unicorn/prefer-module preload: path.join(__dirname, '../build/preload.cjs'), nodeIntegration: true, contextIsolation: true, @@ -183,6 +184,7 @@ export class AppWindow { } private setupWindowEvents(): void { + // eslint-disable-next-line unicorn/consistent-function-scoping const updateBounds = () => { if (!this.window) return; @@ -202,6 +204,7 @@ export class AppWindow { this.window.on('move', updateBounds); this.window.webContents.setWindowOpenHandler(({ url }) => { + // eslint-disable-next-line @typescript-eslint/no-floating-promises shell.openExternal(url); return { action: 'deny' }; }); @@ -265,6 +268,7 @@ export class AppWindow { this.show(); // Mac Only if (process.platform === 'darwin') { + // eslint-disable-next-line @typescript-eslint/no-floating-promises app.dock.show(); } }, @@ -304,6 +308,7 @@ export class AppWindow { const aboutMenuItem = { label: 'About ComfyUI', click: () => { + // eslint-disable-next-line @typescript-eslint/no-floating-promises dialog.showMessageBox({ title: 'About', message: `ComfyUI v${app.getVersion()}`, diff --git a/src/main-process/comfyDesktopApp.ts b/src/main-process/comfyDesktopApp.ts index 2424b1da..b4236d0a 100644 --- a/src/main-process/comfyDesktopApp.ts +++ b/src/main-process/comfyDesktopApp.ts @@ -110,12 +110,14 @@ export class ComfyDesktopApp { } ); + // eslint-disable-next-line @typescript-eslint/require-await ipcMain.handle(IPC_CHANNELS.GET_BASE_PATH, async (): Promise => { return this.basePath; }); ipcMain.handle(IPC_CHANNELS.IS_FIRST_TIME_SETUP, () => { return !ComfyServerConfig.exists(); }); + // eslint-disable-next-line @typescript-eslint/require-await ipcMain.handle(IPC_CHANNELS.REINSTALL, async () => { log.info('Reinstalling...'); this.reinstall(); @@ -127,6 +129,7 @@ export class ComfyDesktopApp { ipcMain.handle( IPC_CHANNELS.SEND_ERROR_TO_SENTRY, + // eslint-disable-next-line @typescript-eslint/require-await async (_event, { error, extras }: SentryErrorDetail): Promise => { try { return Sentry.captureMessage(error, { @@ -334,6 +337,7 @@ If this problem persists, back up and delete the config file, then restart the a return relaunchApplication(delay); } + // eslint-disable-next-line @typescript-eslint/no-floating-promises dialog .showMessageBox({ type: 'question', diff --git a/src/preload.ts b/src/preload.ts index ead4d9f8..07d2ec4b 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -54,12 +54,14 @@ const electronAPI = { onProgressUpdate: (callback: (update: { status: ProgressStatus }) => void) => { ipcRenderer.on(IPC_CHANNELS.LOADING_PROGRESS, (_event, value) => { console.info(`Received ${IPC_CHANNELS.LOADING_PROGRESS} event`, value); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument callback(value); }); }, onLogMessage: (callback: (message: string) => void) => { ipcRenderer.on(IPC_CHANNELS.LOG_MESSAGE, (_event, value) => { console.info(`Received ${IPC_CHANNELS.LOG_MESSAGE} event`, value); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument callback(value); }); }, @@ -113,6 +115,7 @@ const electronAPI = { }, DownloadManager: { onDownloadProgress: (callback: (progress: DownloadProgressUpdate) => void) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument ipcRenderer.on(IPC_CHANNELS.DOWNLOAD_PROGRESS, (_event, progress) => callback(progress)); }, startDownload: (url: string, path: string, filename: string): Promise => { @@ -238,6 +241,7 @@ const electronAPI = { * @returns The last GPU detected by `validateHardware` - runs during installation */ getDetectedGpu: async (): Promise => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return return await ipcRenderer.invoke(IPC_CHANNELS.GET_GPU); }, }, From 2ed8c96c1201c03393a129b257e5a441e6593a0f Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Thu, 19 Dec 2024 04:20:45 +1100 Subject: [PATCH 17/19] Lint configs --- vite.base.config.ts | 2 +- vite.preload.config.ts | 2 +- vite.types.config.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vite.base.config.ts b/vite.base.config.ts index 9a215b63..948703b9 100644 --- a/vite.base.config.ts +++ b/vite.base.config.ts @@ -2,7 +2,7 @@ import { builtinModules } from 'node:module'; import type { ConfigEnv, Plugin, UserConfig } from 'vite'; import pkg from './package.json'; -export const builtins = ['electron', ...builtinModules.map((m) => [m, `node:${m}`]).flat()]; +export const builtins = ['electron', ...builtinModules.flatMap((m) => [m, `node:${m}`])]; export const external = [ ...builtins, diff --git a/vite.preload.config.ts b/vite.preload.config.ts index 11ae331b..2fbb774b 100644 --- a/vite.preload.config.ts +++ b/vite.preload.config.ts @@ -1,4 +1,4 @@ -import type { ConfigEnv, UserConfig } from 'vite'; +import type { UserConfig } from 'vite'; import { defineConfig, mergeConfig } from 'vite'; import { getBuildConfig, external } from './vite.base.config'; diff --git a/vite.types.config.ts b/vite.types.config.ts index 76fa6c80..c68df3d6 100644 --- a/vite.types.config.ts +++ b/vite.types.config.ts @@ -1,11 +1,11 @@ import { defineConfig } from 'vite'; import dts from 'vite-plugin-dts'; -import { resolve } from 'path'; +import path from 'node:path'; export default defineConfig({ build: { lib: { - entry: resolve(__dirname, 'src/main_types.ts'), + entry: path.resolve(import.meta.dirname, 'src/main_types.ts'), name: 'comfyui-electron-api', fileName: 'index', formats: ['es'], From 6f5943b93f84ebc216b67733439df42941f95138 Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Thu, 19 Dec 2024 04:35:51 +1100 Subject: [PATCH 18/19] Lint playwright config --- playwright.setup.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/playwright.setup.ts b/playwright.setup.ts index 0c74fcfa..fe048a4b 100644 --- a/playwright.setup.ts +++ b/playwright.setup.ts @@ -1,18 +1,17 @@ -import { type FullConfig } from '@playwright/test'; -import { spawn } from 'child_process'; +import { spawn } from 'node:child_process'; -async function globalSetup(config: FullConfig) { +async function globalSetup() { console.log('globalSetup'); - return new Promise(async (resolve, reject) => { + return new Promise((resolve, reject) => { const electron = spawn('node', ['./scripts/launchdev.js']); electron.on('close', () => { - reject('process failed to start'); + reject(new Error('process failed to start')); }); - electron.stdout.on('data', (data) => { - if (data.indexOf('App ready') >= 0) { + electron.stdout.on('data', (data: string | Buffer) => { + if (data.includes('App ready')) { resolve(); } }); From e0876f74efd9f659f813fcc8f1ac6d1a450bb29c Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Thu, 19 Dec 2024 04:36:11 +1100 Subject: [PATCH 19/19] nit --- playwright.setup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright.setup.ts b/playwright.setup.ts index fe048a4b..8a27fc4d 100644 --- a/playwright.setup.ts +++ b/playwright.setup.ts @@ -1,7 +1,7 @@ import { spawn } from 'node:child_process'; async function globalSetup() { - console.log('globalSetup'); + console.log('Playwright globalSetup called'); return new Promise((resolve, reject) => { const electron = spawn('node', ['./scripts/launchdev.js']);