diff --git a/apps/desktop/.npmrc b/apps/desktop/.npmrc index e69de29bb2d..45715ebd02f 100644 --- a/apps/desktop/.npmrc +++ b/apps/desktop/.npmrc @@ -0,0 +1,3 @@ +# For electron-builder +# https://github.com/electron-userland/electron-builder/issues/6289#issuecomment-1042620422 +shamefully-hoist=true \ No newline at end of file diff --git a/apps/desktop/electron-builder.ts b/apps/desktop/electron-builder.ts index d1e2077e56f..825c575ce49 100644 --- a/apps/desktop/electron-builder.ts +++ b/apps/desktop/electron-builder.ts @@ -1,90 +1,83 @@ +import { Configuration, TargetConfiguration } from 'electron-builder'; + /** - * Electron Builder Configuration - * @see https://www.electron.build/configuration/configuration + * @see https://www.electron.build/#documentation */ - -import { join } from "node:path"; -import type { Configuration } from "electron-builder"; -import pkg from "./package.json"; - -const currentYear = new Date().getFullYear(); -const author = pkg.author?.name ?? pkg.author; -const authorInKebabCase = author.replace(/\s+/g, "-"); -const appId = `com.${authorInKebabCase}.${pkg.name}`.toLowerCase(); - const config: Configuration = { - appId, - productName: pkg.displayName, - copyright: `Copyright © ${currentYear} — ${author}`, - electronVersion: pkg.devDependencies.electron.replace(/^\^/, ""), - - // Directories - directories: { - output: "release", - buildResources: join(pkg.resources, "build"), - }, - - files: [ - "dist/**/*", - "package.json", - { - from: pkg.resources, - to: "resources", - filter: ["**/*"], - }, - "!node_modules/@superset/**/*", - ], - - // Build optimization - npmRebuild: false, - buildDependenciesFromSource: false, - nodeGypRebuild: false, - - // macOS - mac: { - icon: join(pkg.resources, "build/icons/icon.icns"), - category: "public.app-category.utilities", - target: [ - { - target: "default", - arch: ["universal"], - }, - ], - hardenedRuntime: true, - gatekeeperAssess: false, - notarize: false, - }, - - // Deep linking protocol - protocols: { - name: pkg.displayName, - schemes: ["superset"], - }, - - // Linux - linux: { - icon: join(pkg.resources, "build/icons"), - category: "Utility", - synopsis: pkg.description, - target: ["AppImage", "deb"], - }, - - // Windows - win: { - icon: join(pkg.resources, "build/icons/icon.ico"), - target: [ - { - target: "nsis", - arch: ["x64"], - }, - ], - }, - - // NSIS installer (Windows) - nsis: { - oneClick: false, - allowToChangeInstallationDirectory: true, - }, + appId: 'dev.onlook.studio', + asar: true, + directories: { + output: 'release/${version}', + }, + files: ['dist-electron', 'dist'], + extraResources: [ + { + from: 'resources/bun', + to: 'bun', + filter: ['**/*'], + }, + ], + mac: { + artifactName: '${productName}-${arch}.${ext}', + category: 'public.app-category.developer-tools', + hardenedRuntime: true, + gatekeeperAssess: false, + target: [ + { + target: 'dmg', + arch: ['x64', 'arm64'], + } as TargetConfiguration, + { + target: 'zip', + arch: ['x64', 'arm64'], + } as TargetConfiguration, + ], + }, + win: { + target: [ + { + target: 'nsis', + arch: ['x64'], + } as TargetConfiguration, + ], + artifactName: '${productName}-setup.${ext}', + azureSignOptions: { + publisherName: 'On Off, Inc', + certificateProfileName: 'public-trust-onlook', + codeSigningAccountName: 'trusted-onlook', + endpoint: 'https://eus.codesigning.azure.net', + timestampDigest: 'SHA256', + timestampRfc3161: 'http://timestamp.acs.microsoft.com', + }, + }, + linux: { + target: [ + { + target: 'AppImage', + arch: ['x64', 'arm64'], + } as TargetConfiguration, + { + target: 'deb', + arch: ['x64', 'arm64'], + } as TargetConfiguration, + ], + artifactName: '${productName}-${arch}.${ext}', + category: 'Utility', + executableName: 'Onlook', + icon: 'build/icon.icns', + protocols: [ + { + name: 'onlook', + schemes: ['onlook'], + }, + ], + }, + nsis: {}, + publish: { + provider: 'github', + owner: 'onlook-dev', + repo: 'onlook', + }, }; -export default config; +export default config; \ No newline at end of file diff --git a/apps/desktop/electron.vite.config.ts b/apps/desktop/electron.vite.config.ts index 58e2eb19d21..f019fb2345c 100644 --- a/apps/desktop/electron.vite.config.ts +++ b/apps/desktop/electron.vite.config.ts @@ -1,112 +1,101 @@ -import { dirname, normalize, resolve } from "node:path"; -import tailwindcss from "@tailwindcss/vite"; -import reactPlugin from "@vitejs/plugin-react"; -import { codeInspectorPlugin } from "code-inspector-plugin"; -import { config } from "dotenv"; -import { defineConfig, externalizeDepsPlugin } from "electron-vite"; -import injectProcessEnvPlugin from "rollup-plugin-inject-process-env"; -import tsconfigPathsPlugin from "vite-tsconfig-paths"; -import { main, resources } from "./package.json"; -import { getPortSync } from "./src/main/lib/port-manager"; - -// Load .env from monorepo root -// Use override: true to ensure .env values take precedence over inherited env vars -config({ path: resolve(__dirname, "../../.env"), override: true }); - -// Extract base output directory (dist/) from main path -const devPath = normalize(dirname(main)).split(/\/|\\/g)[0]; - -const tsconfigPaths = tsconfigPathsPlugin({ - projects: [resolve("tsconfig.json")], -}); - -export default defineConfig({ - main: { - plugins: [ - tsconfigPaths, - externalizeDepsPlugin({ - exclude: ["@superset/*", "electron-store"], - }), - ], - - build: { - rollupOptions: { - input: { - index: resolve("src/main/index.ts"), - }, - - output: { - dir: resolve(devPath, "main"), - }, - }, - }, - resolve: { - alias: {}, - }, - }, - - preload: { - plugins: [ - tsconfigPaths, - externalizeDepsPlugin({ - exclude: ["trpc-electron"], - }), - ], - - build: { - outDir: resolve(devPath, "preload"), - rollupOptions: { - input: { - index: resolve("src/preload/index.ts"), - }, - }, - }, - }, - - renderer: { - define: { - "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV), - "process.platform": JSON.stringify(process.platform), - "import.meta.env.ENABLE_NEW_UI": JSON.stringify( - process.env.ENABLE_NEW_UI || "false", - ), - "import.meta.env.DEV_SERVER_PORT": JSON.stringify(getPortSync()), - }, - - server: { - port: getPortSync(), - strictPort: false, // Allow fallback to next available port - }, - - plugins: [ - tsconfigPaths, - tailwindcss(), - reactPlugin(), - - codeInspectorPlugin({ - bundler: "vite", - hotKeys: ["altKey"], - hideConsole: true, - }), - ], - - publicDir: resolve(resources, "public"), - - build: { - outDir: resolve(devPath, "renderer"), - - rollupOptions: { - plugins: [ - injectProcessEnvPlugin({ - NODE_ENV: "production", - platform: process.platform, - }), - ], - - input: { - index: resolve("src/renderer/index.html"), - }, - }, - }, - }, -}); +import react from '@vitejs/plugin-react'; +import { cpSync, rmSync } from 'node:fs'; +import path from 'node:path'; +import { defineConfig } from 'vite'; +import electron from 'vite-plugin-electron/simple'; +import pkg from './package.json'; + +// https://vitejs.dev/config/ +export default defineConfig(({ command }) => { + rmSync('dist-electron', { + recursive: true, + force: true, + }); + const isServe = command === 'serve'; + const isBuild = command === 'build'; + const sourcemap = isServe || !!process.env.VSCODE_DEBUG; + + try { + cpSync('resources', 'dist-electron/main/resources', { recursive: true }); + console.log('✓ Resources folder copied to dist-electron'); + } catch (err) { + console.error('Failed to copy resources folder:', err); + } + + return { + resolve: { + alias: { + '@': path.join(__dirname, 'src'), + common: path.join(__dirname, 'common'), + }, + }, + optimizeDeps: { + exclude: ['node_modules/.vite/deps'], + }, + plugins: [ + react(), + electron({ + main: { + // Shortcut of `build.lib.entry` + entry: 'electron/main/index.ts', + onstart(args) { + if (process.env.VSCODE_DEBUG) { + console.log( + /* For `.vscode/.debug.script.mjs` */ '[startup] Electron App', + ); + } else { + args.startup(); + } + }, + vite: { + build: { + sourcemap: sourcemap ? 'inline' : undefined, + minify: isBuild, + outDir: 'dist-electron/main', + rollupOptions: { + external: Object.keys( + 'dependencies' in pkg ? pkg.dependencies : {}, + ), + }, + }, + }, + }, + preload: { + input: { + index: 'electron/preload/browserview/index.ts', + webview: 'electron/preload/webview/index.ts', + }, + vite: { + build: { + sourcemap: sourcemap ? 'inline' : undefined, + minify: isBuild, + outDir: 'dist-electron/preload', + rollupOptions: { + external: Object.keys(pkg.dependencies ?? {}), + output: { + format: 'cjs', + entryFileNames: '[name].js', + inlineDynamicImports: false, + }, + }, + }, + }, + }, + // Ployfill the Electron and Node.js API for Renderer process. + // If you want use Node.js in Renderer process, the `nodeIntegration` needs to be enabled in the Main process. + // See 👉 https://github.com/electron-vite/vite-plugin-electron-renderer + renderer: {}, + }), + ], + server: process.env.VSCODE_DEBUG + ? (() => { + const url = new URL(pkg.debug.env.VITE_DEV_SERVER_URL); + return { + host: url.hostname, + port: +url.port, + }; + })() + : undefined, + clearScreen: false, + }; +}); \ No newline at end of file diff --git a/apps/desktop/package.json b/apps/desktop/package.json index d8bc24a33c1..8d2f4b4ccb6 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -16,6 +16,7 @@ "compile:app": "electron-vite build", "prebuild": "bun run clean:dev && bun run compile:app", "build": "electron-builder", + "package": "electron-builder --config electron-builder.ts", "install:deps": "electron-builder install-app-deps", "make:release": "tsx ./src/lib/electron-app/release/modules/release.ts", "release": "electron-builder --publish always", @@ -76,11 +77,12 @@ "tailwind-merge": "^2.6.0", "trpc-electron": "^0.1.2", "zod": "^4.1.12", - "zustand": "^5.0.8" + "zustand": "^5.0.8", + "open": "^10.2.0", + "@superset/ui": "workspace:*" }, "devDependencies": { "@biomejs/biome": "^2.2.6", - "@superset/ui": "workspace:*", "@tailwindcss/vite": "^4.0.9", "@types/http-proxy": "^1.17.17", "@types/lodash": "^4.17.20", @@ -92,11 +94,10 @@ "@vitejs/plugin-react": "^5.0.1", "code-inspector-plugin": "^1.2.2", "cross-env": "^10.0.0", - "electron": "^39.1.2", + "electron": "39.1.2", "electron-builder": "^26.0.12", "electron-extension-installer": "^2.0.0", "electron-vite": "^4.0.0", - "open": "^10.2.0", "rimraf": "^6.0.1", "rollup-plugin-inject-process-env": "^1.3.1", "tailwindcss": "^4.0.9", diff --git a/bun.lock b/bun.lock index fb41bf96a84..d9078f104f5 100644 --- a/bun.lock +++ b/bun.lock @@ -81,6 +81,7 @@ "@dnd-kit/utilities": "^3.2.2", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-label": "^2.1.8", + "@superset/ui": "workspace:*", "@tanstack/react-query": "^5.90.10", "@trpc/client": "^11.7.1", "@trpc/react-query": "^11.7.1", @@ -109,6 +110,7 @@ "lowdb": "^7.0.1", "nanoid": "^5.1.6", "node-pty": "1.1.0-beta30", + "open": "^10.2.0", "react": "^19.1.1", "react-arborist": "^3.4.3", "react-dnd": "^16.0.1", @@ -129,7 +131,6 @@ }, "devDependencies": { "@biomejs/biome": "^2.2.6", - "@superset/ui": "workspace:*", "@tailwindcss/vite": "^4.0.9", "@types/http-proxy": "^1.17.17", "@types/lodash": "^4.17.20", @@ -145,7 +146,6 @@ "electron-builder": "^26.0.12", "electron-extension-installer": "^2.0.0", "electron-vite": "^4.0.0", - "open": "^10.2.0", "rimraf": "^6.0.1", "rollup-plugin-inject-process-env": "^1.3.1", "tailwindcss": "^4.0.9",