diff --git a/gitnexus-desktop/electron-builder.yml b/gitnexus-desktop/electron-builder.yml index 63789686b..61fa41057 100644 --- a/gitnexus-desktop/electron-builder.yml +++ b/gitnexus-desktop/electron-builder.yml @@ -51,4 +51,4 @@ linux: - AppImage nsis: oneClick: false - allowToChangeInstallationDirectory: true \ No newline at end of file + allowToChangeInstallationDirectory: true diff --git a/gitnexus-desktop/electron.vite.config.ts b/gitnexus-desktop/electron.vite.config.ts index cfbb761cd..820ff1a67 100644 --- a/gitnexus-desktop/electron.vite.config.ts +++ b/gitnexus-desktop/electron.vite.config.ts @@ -45,4 +45,4 @@ export default { }, }, }, -}; \ No newline at end of file +}; diff --git a/gitnexus-desktop/package.json b/gitnexus-desktop/package.json index 82ec26adc..40f7fdb88 100644 --- a/gitnexus-desktop/package.json +++ b/gitnexus-desktop/package.json @@ -34,4 +34,4 @@ "typescript": "^6.0.3", "vite": "^7.0.0" } -} \ No newline at end of file +} diff --git a/gitnexus-desktop/scripts/ensure-gitnexus-runtime.mjs b/gitnexus-desktop/scripts/ensure-gitnexus-runtime.mjs index a55a52848..4250fbb01 100644 --- a/gitnexus-desktop/scripts/ensure-gitnexus-runtime.mjs +++ b/gitnexus-desktop/scripts/ensure-gitnexus-runtime.mjs @@ -129,7 +129,9 @@ const ensureDesktopRendererPortAvailable = () => { process.exit(1); } - console.info(`Stopping stale desktop renderer process on port ${desktopRendererPort} (PID ${owner.pid}).`); + console.info( + `Stopping stale desktop renderer process on port ${desktopRendererPort} (PID ${owner.pid}).`, + ); killProcessTree(owner.pid); }; diff --git a/gitnexus-desktop/scripts/package.mjs b/gitnexus-desktop/scripts/package.mjs index d6917b5b9..e7e741d9b 100644 --- a/gitnexus-desktop/scripts/package.mjs +++ b/gitnexus-desktop/scripts/package.mjs @@ -11,18 +11,32 @@ const workspaceRoot = path.resolve(packageRoot, '..'); const gitnexusRoot = path.join(workspaceRoot, 'gitnexus'); const gitnexusWebRoot = path.join(workspaceRoot, 'gitnexus-web'); const releaseRoot = path.join(packageRoot, 'release'); -const desktopPackageJson = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8')); -const desktopPackageLock = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package-lock.json'), 'utf8')); -const electronVersion = desktopPackageJson.devDependencies?.electron?.replace(/^[^\d]*/, '') ?? '41.2.1'; -const electronBuilderVersion = desktopPackageJson.devDependencies?.['electron-builder']?.replace(/^[^\d]*/, '') ?? '26.8.1'; +const desktopPackageJson = JSON.parse( + fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'), +); +const desktopPackageLock = JSON.parse( + fs.readFileSync(path.join(packageRoot, 'package-lock.json'), 'utf8'), +); +const electronVersion = + desktopPackageJson.devDependencies?.electron?.replace(/^[^\d]*/, '') ?? '41.2.1'; +const electronBuilderVersion = + desktopPackageJson.devDependencies?.['electron-builder']?.replace(/^[^\d]*/, '') ?? '26.8.1'; const appBuilderLibVersion = - desktopPackageLock.packages?.['node_modules/app-builder-lib']?.version ?? electronBuilderVersion.replace(/^[^\d]*/, ''); + desktopPackageLock.packages?.['node_modules/app-builder-lib']?.version ?? + electronBuilderVersion.replace(/^[^\d]*/, ''); const stamp = new Date().toISOString().replace(/[:.]/g, '-'); const outputDir = path.join(releaseRoot, stamp); const generatedBuilderConfigPath = path.join(outputDir, 'electron-builder.generated.json'); const requiredNsisTemplateFiles = [ path.join(packageRoot, 'node_modules', 'app-builder-lib', 'templates', 'nsis', 'messages.yml'), - path.join(packageRoot, 'node_modules', 'app-builder-lib', 'templates', 'nsis', 'assistedMessages.yml'), + path.join( + packageRoot, + 'node_modules', + 'app-builder-lib', + 'templates', + 'nsis', + 'assistedMessages.yml', + ), ]; const supportedTargetHosts = { '--linux': 'linux', @@ -142,7 +156,9 @@ const overlayDirectoryContents = (sourceDirectory, destinationDirectory) => { }; const repairAppBuilderLibPackage = () => { - const repairDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'gitnexus-desktop-app-builder-lib-')); + const repairDirectory = fs.mkdtempSync( + path.join(os.tmpdir(), 'gitnexus-desktop-app-builder-lib-'), + ); try { const tarballName = `app-builder-lib-${appBuilderLibVersion}.tgz`; @@ -150,7 +166,10 @@ const repairAppBuilderLibPackage = () => { const extractedPackageRoot = path.join(repairDirectory, 'package'); const installedPackageRoot = path.join(packageRoot, 'node_modules', 'app-builder-lib'); - runCommand(`npm pack app-builder-lib@${appBuilderLibVersion} --pack-destination "${repairDirectory}"`, packageRoot); + runCommand( + `npm pack app-builder-lib@${appBuilderLibVersion} --pack-destination "${repairDirectory}"`, + packageRoot, + ); runCommand(`tar -xzf "${tarballPath}" -C "${repairDirectory}"`, packageRoot); overlayDirectoryContents(extractedPackageRoot, installedPackageRoot); } finally { @@ -159,7 +178,9 @@ const repairAppBuilderLibPackage = () => { }; const assertSupportedHostForRequestedTargets = () => { - const unsupportedTargets = requestedTargets.filter((target) => supportedTargetHosts[target] !== process.platform); + const unsupportedTargets = requestedTargets.filter( + (target) => supportedTargetHosts[target] !== process.platform, + ); if (unsupportedTargets.length === 0) { return; @@ -185,13 +206,17 @@ const ensureDesktopToolchainHealthy = () => { return; } - const missingNsisTemplates = requiredNsisTemplateFiles.filter((filePath) => !fs.existsSync(filePath)); + const missingNsisTemplates = requiredNsisTemplateFiles.filter( + (filePath) => !fs.existsSync(filePath), + ); if (missingNsisTemplates.length === 0) { return; } - console.warn('[build] electron-builder NSIS templates are missing. Restoring app-builder-lib package contents first...'); + console.warn( + '[build] electron-builder NSIS templates are missing. Restoring app-builder-lib package contents first...', + ); try { repairAppBuilderLibPackage(); @@ -203,7 +228,9 @@ const ensureDesktopToolchainHealthy = () => { return; } - console.warn('[build] Package overlay repair was not enough. Reinstalling electron-builder next...'); + console.warn( + '[build] Package overlay repair was not enough. Reinstalling electron-builder next...', + ); const targetedRepairWorked = tryRunCommand( `npm install --no-save --package-lock=false electron-builder@${electronBuilderVersion}`, @@ -218,7 +245,9 @@ const ensureDesktopToolchainHealthy = () => { runCommand('npm ci', packageRoot); } - const unresolvedTemplates = requiredNsisTemplateFiles.filter((filePath) => !fs.existsSync(filePath)); + const unresolvedTemplates = requiredNsisTemplateFiles.filter( + (filePath) => !fs.existsSync(filePath), + ); if (unresolvedTemplates.length > 0) { throw new Error( @@ -275,4 +304,4 @@ if (artifacts.length > 0) { for (const artifact of artifacts) { console.log(` - ${artifact}`); } -} \ No newline at end of file +} diff --git a/gitnexus-desktop/src/main/main.ts b/gitnexus-desktop/src/main/main.ts index fbd84ee57..d7325d9a7 100644 --- a/gitnexus-desktop/src/main/main.ts +++ b/gitnexus-desktop/src/main/main.ts @@ -209,7 +209,11 @@ const isAnyHttpUrlReady = async (urls: string[], expectedMarkers?: string[]): Pr return false; }; -const waitForUrlReady = async (url: string, timeoutMs: number, expectedMarkers?: string[]): Promise => { +const waitForUrlReady = async ( + url: string, + timeoutMs: number, + expectedMarkers?: string[], +): Promise => { const deadline = Date.now() + timeoutMs; while (Date.now() < deadline) { @@ -250,18 +254,26 @@ const getGitNexusWebDevRoot = (): string => { }; const getNodeCommand = (): string => { - return process.env.npm_node_execpath || process.env.NODE || (process.platform === 'win32' ? 'node.exe' : 'node'); + return ( + process.env.npm_node_execpath || + process.env.NODE || + (process.platform === 'win32' ? 'node.exe' : 'node') + ); }; const spawnGitNexusServer = (): ChildProcess => { - const childProcess = spawn(getNodeCommand(), [getGitNexusCliEntry(), 'serve', '--host', GITNEXUS_HOST], { - cwd: getGitNexusRuntimeDir(), - env: { - ...process.env, + const childProcess = spawn( + getNodeCommand(), + [getGitNexusCliEntry(), 'serve', '--host', GITNEXUS_HOST], + { + cwd: getGitNexusRuntimeDir(), + env: { + ...process.env, + }, + stdio: ['ignore', 'pipe', 'pipe'], + windowsHide: true, }, - stdio: ['ignore', 'pipe', 'pipe'], - windowsHide: true, - }); + ); childProcess.stdout?.on('data', (chunk) => { appendGitNexusServerOutput(chunk); @@ -312,8 +324,22 @@ const spawnWebDevServer = (): ChildProcess => { const command = process.platform === 'win32' ? 'cmd.exe' : 'npm'; const args = process.platform === 'win32' - ? ['/d', '/s', '/c', `npm run dev -- --host ${GITNEXUS_WEB_DEV_HOST} --port ${GITNEXUS_WEB_DEV_PORT} --strictPort`] - : ['run', 'dev', '--', '--host', GITNEXUS_WEB_DEV_HOST, '--port', String(GITNEXUS_WEB_DEV_PORT), '--strictPort']; + ? [ + '/d', + '/s', + '/c', + `npm run dev -- --host ${GITNEXUS_WEB_DEV_HOST} --port ${GITNEXUS_WEB_DEV_PORT} --strictPort`, + ] + : [ + 'run', + 'dev', + '--', + '--host', + GITNEXUS_WEB_DEV_HOST, + '--port', + String(GITNEXUS_WEB_DEV_PORT), + '--strictPort', + ]; const childProcess = spawn(command, args, { cwd: getGitNexusWebDevRoot(), @@ -352,7 +378,11 @@ const ensureWebDevServerStarted = async (): Promise => { webDevServerProcess = spawnWebDevServer(); } - await waitForUrlReady(GITNEXUS_WEB_DEV_URL, GITNEXUS_WEB_READY_TIMEOUT_MS, GITNEXUS_WEB_EXPECTED_MARKERS); + await waitForUrlReady( + GITNEXUS_WEB_DEV_URL, + GITNEXUS_WEB_READY_TIMEOUT_MS, + GITNEXUS_WEB_EXPECTED_MARKERS, + ); }; const normalizeStaticPath = (rootDir: string, requestPath: string): string | null => { @@ -454,7 +484,11 @@ const stopWebDevServer = (): void => { }; const stopGitNexusServer = (): void => { - if (!gitNexusServerProcess || !gitNexusServerProcess.pid || gitNexusServerProcess.exitCode !== null) { + if ( + !gitNexusServerProcess || + !gitNexusServerProcess.pid || + gitNexusServerProcess.exitCode !== null + ) { return; } @@ -559,7 +593,9 @@ const createEmbeddedContentView = (contentUrl: string): BrowserView => { contentView.webContents.on('dom-ready', () => { void contentView.webContents.insertCSS(EMBEDDED_APP_SCROLLBAR_CSS).catch((error) => { - console.warn(`[gitnexus-desktop] Failed to inject embedded app CSS: ${getErrorMessage(error)}`); + console.warn( + `[gitnexus-desktop] Failed to inject embedded app CSS: ${getErrorMessage(error)}`, + ); }); }); @@ -761,4 +797,4 @@ app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit(); } -}); \ No newline at end of file +}); diff --git a/gitnexus-desktop/src/main/preload.ts b/gitnexus-desktop/src/main/preload.ts index 26a246210..3e24dc14c 100644 --- a/gitnexus-desktop/src/main/preload.ts +++ b/gitnexus-desktop/src/main/preload.ts @@ -7,47 +7,50 @@ const DESKTOP_WINDOW_STATE_CHANGED_CHANNEL = 'gitnexus-desktop:window-state-chan const DESKTOP_SHELL_TITLEBAR_HEIGHT = process.platform === 'darwin' ? 38 : 0; type DesktopShellState = { - appName: string; - isAlwaysOnTop: boolean; - isMaximized: boolean; - platform: NodeJS.Platform; - titleBarHeight: number; + appName: string; + isAlwaysOnTop: boolean; + isMaximized: boolean; + platform: NodeJS.Platform; + titleBarHeight: number; }; type DesktopWindowAction = 'close' | 'minimize' | 'toggle-always-on-top' | 'toggle-maximize'; const invokeWindowAction = (action: DesktopWindowAction): Promise => { - return ipcRenderer.invoke(DESKTOP_WINDOW_ACTION_CHANNEL, action) as Promise; + return ipcRenderer.invoke( + DESKTOP_WINDOW_ACTION_CHANNEL, + action, + ) as Promise; }; contextBridge.exposeInMainWorld('gitnexusDesktop', { - appName: DESKTOP_APP_NAME, - platform: process.platform, - titleBarHeight: DESKTOP_SHELL_TITLEBAR_HEIGHT, - close: async (): Promise => { - await invokeWindowAction('close'); - }, - getShellState: (): Promise => { - return ipcRenderer.invoke(DESKTOP_GET_SHELL_STATE_CHANNEL) as Promise; - }, - minimize: (): Promise => { - return invokeWindowAction('minimize'); - }, - onWindowStateChanged: (callback: (state: DesktopShellState) => void): (() => void) => { - const listener = (_event: IpcRendererEvent, state: DesktopShellState): void => { - callback(state); - }; + appName: DESKTOP_APP_NAME, + platform: process.platform, + titleBarHeight: DESKTOP_SHELL_TITLEBAR_HEIGHT, + close: async (): Promise => { + await invokeWindowAction('close'); + }, + getShellState: (): Promise => { + return ipcRenderer.invoke(DESKTOP_GET_SHELL_STATE_CHANNEL) as Promise; + }, + minimize: (): Promise => { + return invokeWindowAction('minimize'); + }, + onWindowStateChanged: (callback: (state: DesktopShellState) => void): (() => void) => { + const listener = (_event: IpcRendererEvent, state: DesktopShellState): void => { + callback(state); + }; - ipcRenderer.on(DESKTOP_WINDOW_STATE_CHANGED_CHANNEL, listener); + ipcRenderer.on(DESKTOP_WINDOW_STATE_CHANGED_CHANNEL, listener); - return () => { - ipcRenderer.removeListener(DESKTOP_WINDOW_STATE_CHANGED_CHANNEL, listener); - }; - }, - toggleAlwaysOnTop: (): Promise => { - return invokeWindowAction('toggle-always-on-top'); - }, - toggleMaximize: (): Promise => { - return invokeWindowAction('toggle-maximize'); - }, -}); \ No newline at end of file + return () => { + ipcRenderer.removeListener(DESKTOP_WINDOW_STATE_CHANGED_CHANNEL, listener); + }; + }, + toggleAlwaysOnTop: (): Promise => { + return invokeWindowAction('toggle-always-on-top'); + }, + toggleMaximize: (): Promise => { + return invokeWindowAction('toggle-maximize'); + }, +}); diff --git a/gitnexus-desktop/src/renderer/src/App.tsx b/gitnexus-desktop/src/renderer/src/App.tsx index ff0da6b24..e30af9a0b 100644 --- a/gitnexus-desktop/src/renderer/src/App.tsx +++ b/gitnexus-desktop/src/renderer/src/App.tsx @@ -40,7 +40,8 @@ const fallbackDesktopApi: DesktopApi = { toggleMaximize: async () => defaultDesktopState, }; -const desktopApi = (window as Window & { gitnexusDesktop?: DesktopApi }).gitnexusDesktop ?? fallbackDesktopApi; +const desktopApi = + (window as Window & { gitnexusDesktop?: DesktopApi }).gitnexusDesktop ?? fallbackDesktopApi; const styles = ` :root { @@ -352,4 +353,4 @@ export default function App() { ); -} \ No newline at end of file +} diff --git a/gitnexus-desktop/src/renderer/src/main.tsx b/gitnexus-desktop/src/renderer/src/main.tsx index 6c73f3dd3..2da67de25 100644 --- a/gitnexus-desktop/src/renderer/src/main.tsx +++ b/gitnexus-desktop/src/renderer/src/main.tsx @@ -44,7 +44,8 @@ const fallbackDesktopApi: DesktopApi = { toggleMaximize: async () => defaultDesktopState, }; -const desktopApi = (window as Window & { gitnexusDesktop?: DesktopApi }).gitnexusDesktop ?? fallbackDesktopApi; +const desktopApi = + (window as Window & { gitnexusDesktop?: DesktopApi }).gitnexusDesktop ?? fallbackDesktopApi; const shellState: DesktopShellState = { ...defaultDesktopState, @@ -203,4 +204,4 @@ void desktopApi.getShellState().then((state) => { desktopApi.onWindowStateChanged((state) => { applyShellState(state); -}); \ No newline at end of file +}); diff --git a/gitnexus-desktop/src/renderer/src/styles.css b/gitnexus-desktop/src/renderer/src/styles.css index 8a0d83978..73a906450 100644 --- a/gitnexus-desktop/src/renderer/src/styles.css +++ b/gitnexus-desktop/src/renderer/src/styles.css @@ -19,4 +19,4 @@ body { font-size: 2rem; font-weight: 600; letter-spacing: 0.04em; -} \ No newline at end of file +} diff --git a/gitnexus-desktop/tsconfig.json b/gitnexus-desktop/tsconfig.json index ff748f438..7ad3df4a4 100644 --- a/gitnexus-desktop/tsconfig.json +++ b/gitnexus-desktop/tsconfig.json @@ -12,4 +12,4 @@ "path": "./tsconfig.renderer.json" } ] -} \ No newline at end of file +} diff --git a/gitnexus-desktop/tsconfig.node.json b/gitnexus-desktop/tsconfig.node.json index 8a32c3da0..ddd5f3a97 100644 --- a/gitnexus-desktop/tsconfig.node.json +++ b/gitnexus-desktop/tsconfig.node.json @@ -15,4 +15,4 @@ "noEmit": true }, "include": ["electron.vite.config.ts", "src/main/**/*.ts"] -} \ No newline at end of file +} diff --git a/gitnexus-desktop/tsconfig.renderer.json b/gitnexus-desktop/tsconfig.renderer.json index fddcbdc58..3b41876f8 100644 --- a/gitnexus-desktop/tsconfig.renderer.json +++ b/gitnexus-desktop/tsconfig.renderer.json @@ -18,4 +18,4 @@ "types": ["vite/client"] }, "include": ["src/renderer/src/main.tsx"] -} \ No newline at end of file +}