vue-cli-plugin-electron-haunv 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/dev-runner.js +71 -0
- package/bin/hot-reload.js +1 -0
- package/generator/index.js +29 -0
- package/generator/template/electron/main.js +30 -0
- package/generator/template/electron/preload.js +5 -0
- package/index.js +8 -41
- package/package.json +16 -56
- package/LICENSE +0 -21
- package/README.md +0 -250
- package/bin/cli.js +0 -87
- package/generator/template/index.html +0 -15
- package/generator/template/package.json +0 -28
- package/generator/template/src/App.vue +0 -125
- package/generator/template/src/background.js +0 -88
- package/generator/template/src/main.js +0 -4
- package/generator/template/src/preload.js +0 -31
- package/generator/template/vite.config.js +0 -36
- package/index.d.ts +0 -180
- package/lib/build.js +0 -128
- package/lib/config.js +0 -25
- package/lib/nativeDeps.js +0 -85
- package/lib/plugin.js +0 -40
- package/lib/protocol.js +0 -55
- package/lib/serve.js +0 -99
- package/lib/vitePlugin.js +0 -65
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div id="app">
|
|
3
|
-
<header class="app-header">
|
|
4
|
-
<img src="./assets/logo.svg" alt="Vue + Electron" class="logo" />
|
|
5
|
-
<h1>Vue 3 + Vite + Electron</h1>
|
|
6
|
-
</header>
|
|
7
|
-
|
|
8
|
-
<main class="app-main">
|
|
9
|
-
<p class="tagline">
|
|
10
|
-
Edit <code>src/App.vue</code> and save to see hot-reload in action.
|
|
11
|
-
</p>
|
|
12
|
-
|
|
13
|
-
<div class="info-cards">
|
|
14
|
-
<div class="card">
|
|
15
|
-
<h2>⚡ Vite</h2>
|
|
16
|
-
<p>Lightning-fast HMR during development.</p>
|
|
17
|
-
</div>
|
|
18
|
-
<div class="card">
|
|
19
|
-
<h2>🖥 Electron</h2>
|
|
20
|
-
<p>Cross-platform desktop apps with web tech.</p>
|
|
21
|
-
</div>
|
|
22
|
-
<div class="card">
|
|
23
|
-
<h2>💚 Vue 3</h2>
|
|
24
|
-
<p>Composition API, TypeScript, and more.</p>
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
|
|
28
|
-
<p class="version">Electron API available: {{ hasElectronAPI ? '✅' : '❌' }}</p>
|
|
29
|
-
</main>
|
|
30
|
-
</div>
|
|
31
|
-
</template>
|
|
32
|
-
|
|
33
|
-
<script setup>
|
|
34
|
-
import { ref, onMounted } from 'vue'
|
|
35
|
-
|
|
36
|
-
const hasElectronAPI = ref(false)
|
|
37
|
-
|
|
38
|
-
onMounted(() => {
|
|
39
|
-
hasElectronAPI.value = typeof window.electronAPI !== 'undefined'
|
|
40
|
-
})
|
|
41
|
-
</script>
|
|
42
|
-
|
|
43
|
-
<style>
|
|
44
|
-
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
45
|
-
|
|
46
|
-
body {
|
|
47
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
48
|
-
background: #0d1117;
|
|
49
|
-
color: #c9d1d9;
|
|
50
|
-
min-height: 100vh;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
#app {
|
|
54
|
-
display: flex;
|
|
55
|
-
flex-direction: column;
|
|
56
|
-
align-items: center;
|
|
57
|
-
padding: 40px 20px;
|
|
58
|
-
gap: 32px;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
.app-header {
|
|
62
|
-
display: flex;
|
|
63
|
-
flex-direction: column;
|
|
64
|
-
align-items: center;
|
|
65
|
-
gap: 16px;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
.logo { width: 80px; height: 80px; }
|
|
69
|
-
|
|
70
|
-
h1 {
|
|
71
|
-
font-size: 2rem;
|
|
72
|
-
font-weight: 700;
|
|
73
|
-
background: linear-gradient(135deg, #42b883, #35495e);
|
|
74
|
-
-webkit-background-clip: text;
|
|
75
|
-
-webkit-text-fill-color: transparent;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
.tagline {
|
|
79
|
-
font-size: 1.1rem;
|
|
80
|
-
color: #8b949e;
|
|
81
|
-
text-align: center;
|
|
82
|
-
margin-bottom: 24px;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
.tagline code {
|
|
86
|
-
background: #161b22;
|
|
87
|
-
padding: 2px 8px;
|
|
88
|
-
border-radius: 4px;
|
|
89
|
-
font-family: monospace;
|
|
90
|
-
color: #58a6ff;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
.info-cards {
|
|
94
|
-
display: grid;
|
|
95
|
-
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
96
|
-
gap: 20px;
|
|
97
|
-
width: 100%;
|
|
98
|
-
max-width: 700px;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
.card {
|
|
102
|
-
background: #161b22;
|
|
103
|
-
border: 1px solid #30363d;
|
|
104
|
-
border-radius: 12px;
|
|
105
|
-
padding: 24px;
|
|
106
|
-
text-align: center;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.card h2 { font-size: 1.3rem; margin-bottom: 8px; }
|
|
110
|
-
.card p { color: #8b949e; font-size: 0.95rem; }
|
|
111
|
-
|
|
112
|
-
.version {
|
|
113
|
-
margin-top: 16px;
|
|
114
|
-
font-size: 0.9rem;
|
|
115
|
-
color: #8b949e;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
.app-main {
|
|
119
|
-
display: flex;
|
|
120
|
-
flex-direction: column;
|
|
121
|
-
align-items: center;
|
|
122
|
-
width: 100%;
|
|
123
|
-
max-width: 800px;
|
|
124
|
-
}
|
|
125
|
-
</style>
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
import { app, protocol, BrowserWindow } from 'electron'
|
|
4
|
-
import { createProtocol } from 'vite-plugin-electron-builder/lib/protocol'
|
|
5
|
-
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
|
|
6
|
-
import path from 'path'
|
|
7
|
-
|
|
8
|
-
const isDevelopment = process.env.NODE_ENV !== 'production'
|
|
9
|
-
|
|
10
|
-
// Register the custom protocol before app is ready (required for security)
|
|
11
|
-
protocol.registerSchemesAsPrivileged([
|
|
12
|
-
{
|
|
13
|
-
scheme: 'app',
|
|
14
|
-
privileges: {
|
|
15
|
-
secure: true,
|
|
16
|
-
standard: true
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
])
|
|
20
|
-
|
|
21
|
-
let win
|
|
22
|
-
|
|
23
|
-
async function createWindow() {
|
|
24
|
-
win = new BrowserWindow({
|
|
25
|
-
width: 800,
|
|
26
|
-
height: 600,
|
|
27
|
-
webPreferences: {
|
|
28
|
-
// NOTE: Do NOT enable nodeIntegration in production for security
|
|
29
|
-
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION === 'true',
|
|
30
|
-
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
|
|
31
|
-
preload: path.join(__dirname, 'preload.js') // optional
|
|
32
|
-
}
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
if (isDevelopment) {
|
|
36
|
-
// Load from Vite dev server
|
|
37
|
-
await win.loadURL(process.env.VITE_DEV_SERVER_URL || 'http://localhost:8080')
|
|
38
|
-
win.webContents.openDevTools()
|
|
39
|
-
} else {
|
|
40
|
-
// Use custom protocol for production
|
|
41
|
-
createProtocol('app')
|
|
42
|
-
await win.loadURL('app://./index.html')
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
win.on('closed', () => {
|
|
46
|
-
win = null
|
|
47
|
-
})
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Install Vue Devtools in development
|
|
51
|
-
app.whenReady().then(async () => {
|
|
52
|
-
if (isDevelopment && !process.env.IS_TEST) {
|
|
53
|
-
try {
|
|
54
|
-
await installExtension(VUEJS_DEVTOOLS)
|
|
55
|
-
} catch (e) {
|
|
56
|
-
console.error('Vue Devtools failed to install:', e.toString())
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
await createWindow()
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
// Quit when all windows are closed (except on macOS)
|
|
63
|
-
app.on('window-all-closed', () => {
|
|
64
|
-
if (process.platform !== 'darwin') {
|
|
65
|
-
app.quit()
|
|
66
|
-
}
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
app.on('activate', () => {
|
|
70
|
-
if (win === null) {
|
|
71
|
-
createWindow()
|
|
72
|
-
}
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
// Exit cleanly in development mode
|
|
76
|
-
if (isDevelopment) {
|
|
77
|
-
if (process.platform === 'win32') {
|
|
78
|
-
process.on('message', (data) => {
|
|
79
|
-
if (data === 'graceful-exit') {
|
|
80
|
-
app.quit()
|
|
81
|
-
}
|
|
82
|
-
})
|
|
83
|
-
} else {
|
|
84
|
-
process.on('SIGTERM', () => {
|
|
85
|
-
app.quit()
|
|
86
|
-
})
|
|
87
|
-
}
|
|
88
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Preload script - runs in a privileged context before the renderer.
|
|
5
|
-
* Use contextBridge to safely expose APIs to the renderer.
|
|
6
|
-
*
|
|
7
|
-
* Docs: https://www.electronjs.org/docs/latest/tutorial/context-isolation
|
|
8
|
-
*/
|
|
9
|
-
const { contextBridge, ipcRenderer } = require('electron')
|
|
10
|
-
|
|
11
|
-
// Expose a safe API to the renderer process via window.electronAPI
|
|
12
|
-
contextBridge.exposeInMainWorld('electronAPI', {
|
|
13
|
-
// Example: send a message to the main process
|
|
14
|
-
sendMessage: (channel, data) => {
|
|
15
|
-
const allowedChannels = ['app:minimize', 'app:maximize', 'app:close', 'app:ready']
|
|
16
|
-
if (allowedChannels.includes(channel)) {
|
|
17
|
-
ipcRenderer.send(channel, data)
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
|
|
21
|
-
// Example: receive a message from the main process
|
|
22
|
-
onMessage: (channel, callback) => {
|
|
23
|
-
const allowedChannels = ['app:update-available', 'app:update-downloaded']
|
|
24
|
-
if (allowedChannels.includes(channel)) {
|
|
25
|
-
ipcRenderer.on(channel, (_event, ...args) => callback(...args))
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
// Expose app version
|
|
30
|
-
getVersion: () => ipcRenderer.invoke('app:get-version'),
|
|
31
|
-
})
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vite'
|
|
2
|
-
import vue from '@vitejs/plugin-vue'
|
|
3
|
-
import { createElectronPlugin } from 'vite-plugin-electron-builder'
|
|
4
|
-
import path from 'path'
|
|
5
|
-
|
|
6
|
-
// https://vitejs.dev/config/
|
|
7
|
-
export default defineConfig({
|
|
8
|
-
plugins: [
|
|
9
|
-
vue(),
|
|
10
|
-
createElectronPlugin({
|
|
11
|
-
// Path to Electron main process entry
|
|
12
|
-
mainProcessFile: 'src/background.js',
|
|
13
|
-
|
|
14
|
-
// Output directory for compiled main process
|
|
15
|
-
outputDir: 'dist_electron',
|
|
16
|
-
|
|
17
|
-
// Optional: path to preload script
|
|
18
|
-
preload: 'src/preload.js',
|
|
19
|
-
|
|
20
|
-
// Optional: electron-builder overrides
|
|
21
|
-
builderOptions: {
|
|
22
|
-
appId: 'com.example.myapp',
|
|
23
|
-
productName: 'My Vue Electron App',
|
|
24
|
-
linux: { target: ['AppImage', 'deb'] },
|
|
25
|
-
win: { target: ['nsis'] },
|
|
26
|
-
mac: { target: ['dmg'] },
|
|
27
|
-
},
|
|
28
|
-
}),
|
|
29
|
-
],
|
|
30
|
-
|
|
31
|
-
resolve: {
|
|
32
|
-
alias: {
|
|
33
|
-
'@': path.resolve(__dirname, 'src'),
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
})
|
package/index.d.ts
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import type { Plugin, UserConfig } from 'vite'
|
|
2
|
-
|
|
3
|
-
// ─── Option Types ─────────────────────────────────────────────────────────────
|
|
4
|
-
|
|
5
|
-
export interface ElectronBuilderOptions {
|
|
6
|
-
/**
|
|
7
|
-
* Relative path to the Electron main process entry file.
|
|
8
|
-
* @default 'src/background.js'
|
|
9
|
-
*/
|
|
10
|
-
mainProcessFile?: string
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Output directory for the compiled main process and packaged app.
|
|
14
|
-
* @default 'dist_electron'
|
|
15
|
-
*/
|
|
16
|
-
outputDir?: string
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Output directory for the Vite renderer build.
|
|
20
|
-
* @default 'dist'
|
|
21
|
-
*/
|
|
22
|
-
rendererOutputDir?: string
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Path to the preload script (relative to project root).
|
|
26
|
-
* When set, it is compiled alongside the main process.
|
|
27
|
-
*/
|
|
28
|
-
preload?: string
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Additional glob patterns to watch for main-process hot-reload.
|
|
32
|
-
* Defaults to watching src/background.{js,ts} and src/preload/**
|
|
33
|
-
*/
|
|
34
|
-
mainProcessWatch?: string[]
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Enable Node integration in the renderer process.
|
|
38
|
-
* ⚠ Keep this false in production for security.
|
|
39
|
-
* @default false
|
|
40
|
-
*/
|
|
41
|
-
nodeIntegration?: boolean
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Enable context isolation between main and renderer processes.
|
|
45
|
-
* @default true
|
|
46
|
-
*/
|
|
47
|
-
contextIsolation?: boolean
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Custom Electron protocol scheme used in production (e.g. 'app').
|
|
51
|
-
* @default 'app'
|
|
52
|
-
*/
|
|
53
|
-
customFileProtocol?: string
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Extra Electron CLI flags appended during `electron:serve`.
|
|
57
|
-
* @example ['--inspect=5858', '--remote-debugging-port=9222']
|
|
58
|
-
*/
|
|
59
|
-
electronCliArgs?: string[]
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Native (C++ addon) module names to externalize from the esbuild bundle.
|
|
63
|
-
* These will be loaded at runtime from node_modules instead.
|
|
64
|
-
* @default []
|
|
65
|
-
*/
|
|
66
|
-
externals?: string[]
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* electron-builder configuration overrides applied during packaging.
|
|
70
|
-
*/
|
|
71
|
-
builderOptions?: ElectronBuilderConfig
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Additional Vite config applied to the main-process compilation step.
|
|
75
|
-
*/
|
|
76
|
-
mainProcessViteConfig?: Partial<UserConfig>
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Set to true if you want to skip TypeScript compilation for the main process.
|
|
80
|
-
* @default false
|
|
81
|
-
*/
|
|
82
|
-
disableMainProcessTypescript?: boolean
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// ─── Result Types ─────────────────────────────────────────────────────────────
|
|
86
|
-
|
|
87
|
-
export interface ServeResult {
|
|
88
|
-
/** Gracefully stop Electron and the file watcher. */
|
|
89
|
-
stop: () => Promise<void>
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// ─── Primary API ──────────────────────────────────────────────────────────────
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* The main Vite plugin. Add this to your vite.config.js plugins array.
|
|
96
|
-
*
|
|
97
|
-
* @example
|
|
98
|
-
* // vite.config.js
|
|
99
|
-
* import { defineConfig } from 'vite'
|
|
100
|
-
* import vue from '@vitejs/plugin-vue'
|
|
101
|
-
* import { createElectronPlugin } from 'vite-plugin-electron-builder'
|
|
102
|
-
*
|
|
103
|
-
* export default defineConfig({
|
|
104
|
-
* plugins: [
|
|
105
|
-
* vue(),
|
|
106
|
-
* createElectronPlugin({ mainProcessFile: 'src/background.js' })
|
|
107
|
-
* ]
|
|
108
|
-
* })
|
|
109
|
-
*/
|
|
110
|
-
export function createElectronPlugin(options?: ElectronBuilderOptions): Plugin
|
|
111
|
-
|
|
112
|
-
// ─── Lower-level Plugin Hooks ─────────────────────────────────────────────────
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Vite plugin that handles the development serve phase only.
|
|
116
|
-
* Use `createElectronPlugin` instead unless you need fine-grained control.
|
|
117
|
-
*/
|
|
118
|
-
export function electronServePlugin(options?: ElectronBuilderOptions): Plugin
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Vite plugin that handles the production build phase only.
|
|
122
|
-
* Use `createElectronPlugin` instead unless you need fine-grained control.
|
|
123
|
-
*/
|
|
124
|
-
export function electronBuildPlugin(options?: ElectronBuilderOptions): Plugin
|
|
125
|
-
|
|
126
|
-
// ─── Build Utilities ─────────────────────────────────────────────────────────
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Compile the Electron main process (and optional preload) using esbuild.
|
|
130
|
-
* Called automatically during build; exposed for custom pipelines.
|
|
131
|
-
*/
|
|
132
|
-
export function buildMain(options?: ElectronBuilderOptions): Promise<void>
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Package the app with electron-builder after the renderer has been built.
|
|
136
|
-
* Called automatically during build; exposed for custom pipelines.
|
|
137
|
-
*/
|
|
138
|
-
export function buildRenderer(options?: ElectronBuilderOptions): Promise<void>
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Start the Electron development server with hot-reload.
|
|
142
|
-
* Compiles the main process, launches Electron, and watches source files.
|
|
143
|
-
*/
|
|
144
|
-
export function serve(options?: ElectronBuilderOptions): Promise<void>
|
|
145
|
-
|
|
146
|
-
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Register a secure custom file protocol in the Electron main process.
|
|
150
|
-
* Prevents path traversal and falls back to index.html for SPA routing.
|
|
151
|
-
*
|
|
152
|
-
* @param scheme Protocol name, e.g. 'app'
|
|
153
|
-
* @param basePath Override the directory from which files are served.
|
|
154
|
-
*
|
|
155
|
-
* @example
|
|
156
|
-
* // src/background.js
|
|
157
|
-
* import { createProtocol } from 'vite-plugin-electron-builder/lib/protocol'
|
|
158
|
-
*
|
|
159
|
-
* app.whenReady().then(() => {
|
|
160
|
-
* createProtocol('app')
|
|
161
|
-
* win.loadURL('app://./index.html')
|
|
162
|
-
* })
|
|
163
|
-
*/
|
|
164
|
-
export function createProtocol(scheme: string, basePath?: string): void
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Scan node_modules for packages that contain native (.node) binaries.
|
|
168
|
-
* Useful for automatically populating the `externals` option.
|
|
169
|
-
*
|
|
170
|
-
* @param projectRoot Absolute path to the project root (default: cwd)
|
|
171
|
-
*/
|
|
172
|
-
export function getNativeDeps(projectRoot?: string): Promise<string[]>
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Normalise plugin options, applying all defaults.
|
|
176
|
-
* Useful for tooling that needs to introspect resolved config.
|
|
177
|
-
*/
|
|
178
|
-
export function getConfig(
|
|
179
|
-
options?: ElectronBuilderOptions
|
|
180
|
-
): Required<ElectronBuilderOptions>
|
package/lib/build.js
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const path = require('path')
|
|
4
|
-
const fs = require('fs-extra')
|
|
5
|
-
const chalk = require('chalk')
|
|
6
|
-
const { build: electronBuilderBuild } = require('electron-builder')
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Build the Electron main process using esbuild.
|
|
10
|
-
* @param {object} options
|
|
11
|
-
* @param {string} [options.mainProcessFile] - entry point
|
|
12
|
-
* @param {string} [options.outputDir] - output dir (default: dist-electron)
|
|
13
|
-
* @param {'development'|'production'} [options.mode]
|
|
14
|
-
*/
|
|
15
|
-
async function buildMain(options = {}) {
|
|
16
|
-
const outputDir = options.outputDir || 'dist_electron'
|
|
17
|
-
const mode = options.mode || 'production'
|
|
18
|
-
const cwd = process.cwd()
|
|
19
|
-
|
|
20
|
-
const possibleEntries = [
|
|
21
|
-
options.mainProcessFile,
|
|
22
|
-
path.join(cwd, 'src/background.ts'),
|
|
23
|
-
path.join(cwd, 'src/background.js'),
|
|
24
|
-
path.join(cwd, 'src/main/index.ts'),
|
|
25
|
-
path.join(cwd, 'src/main/index.js'),
|
|
26
|
-
path.join(cwd, 'electron/main.ts'),
|
|
27
|
-
path.join(cwd, 'electron/main.js'),
|
|
28
|
-
].filter(Boolean)
|
|
29
|
-
|
|
30
|
-
const entry = possibleEntries.find((p) => fs.existsSync(p))
|
|
31
|
-
if (!entry) {
|
|
32
|
-
console.warn(chalk.yellow('[electron-builder] No main process entry found.'))
|
|
33
|
-
return
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
await fs.ensureDir(path.join(cwd, outputDir))
|
|
37
|
-
|
|
38
|
-
const esbuild = requireEsbuild()
|
|
39
|
-
if (!esbuild) {
|
|
40
|
-
throw new Error('[electron-builder] esbuild is required. Run: npm install -D esbuild')
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
await esbuild.build({
|
|
44
|
-
entryPoints: [entry],
|
|
45
|
-
bundle: true,
|
|
46
|
-
platform: 'node',
|
|
47
|
-
target: `node${process.versions.node.split('.')[0]}`,
|
|
48
|
-
outfile: path.join(cwd, outputDir, 'main.js'),
|
|
49
|
-
external: ['electron', ...getExternalModules(cwd)],
|
|
50
|
-
define: { 'process.env.NODE_ENV': JSON.stringify(mode) },
|
|
51
|
-
sourcemap: mode === 'development',
|
|
52
|
-
minify: mode === 'production',
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
const preloadEntry = findPreload(cwd)
|
|
56
|
-
if (preloadEntry) {
|
|
57
|
-
await esbuild.build({
|
|
58
|
-
entryPoints: [preloadEntry],
|
|
59
|
-
bundle: true,
|
|
60
|
-
platform: 'node',
|
|
61
|
-
target: `node${process.versions.node.split('.')[0]}`,
|
|
62
|
-
outfile: path.join(cwd, outputDir, 'preload.js'),
|
|
63
|
-
external: ['electron'],
|
|
64
|
-
sourcemap: mode === 'development',
|
|
65
|
-
minify: mode === 'production',
|
|
66
|
-
})
|
|
67
|
-
console.log(chalk.green('[electron-builder] Preload script compiled'))
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
console.log(chalk.green('[electron-builder] Main process compiled'))
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Package the app using electron-builder
|
|
75
|
-
* @param {object} options
|
|
76
|
-
* @param {string} [options.rendererOutputDir] - Vite build output (default: 'dist')
|
|
77
|
-
* @param {string} [options.electronOutputDir] - compiled main output (default: 'dist_electron')
|
|
78
|
-
* @param {object} [options.builderOptions] - electron-builder config overrides
|
|
79
|
-
*/
|
|
80
|
-
async function buildRenderer(options = {}) {
|
|
81
|
-
const cwd = process.cwd()
|
|
82
|
-
const rendererOutput = options.rendererOutputDir || 'dist'
|
|
83
|
-
const electronOutput = options.electronOutputDir || 'dist_electron'
|
|
84
|
-
|
|
85
|
-
console.log(chalk.blue('[electron-builder] Packaging with electron-builder...'))
|
|
86
|
-
|
|
87
|
-
const builderConfig = {
|
|
88
|
-
directories: {
|
|
89
|
-
output: path.join(cwd, electronOutput, 'release'),
|
|
90
|
-
app: cwd,
|
|
91
|
-
},
|
|
92
|
-
files: [
|
|
93
|
-
`${rendererOutput}/**/*`,
|
|
94
|
-
`${electronOutput}/main.js`,
|
|
95
|
-
`${electronOutput}/preload.js`,
|
|
96
|
-
'package.json',
|
|
97
|
-
],
|
|
98
|
-
...(options.builderOptions || {}),
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const result = await electronBuilderBuild({ config: builderConfig })
|
|
102
|
-
console.log(chalk.green('[electron-builder] Packaging complete:'), result)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function requireEsbuild() {
|
|
106
|
-
try { return require('esbuild') } catch { return null }
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function findPreload(cwd) {
|
|
110
|
-
const candidates = [
|
|
111
|
-
path.join(cwd, 'src/preload.ts'),
|
|
112
|
-
path.join(cwd, 'src/preload.js'),
|
|
113
|
-
path.join(cwd, 'src/preload/index.ts'),
|
|
114
|
-
path.join(cwd, 'src/preload/index.js'),
|
|
115
|
-
path.join(cwd, 'electron/preload.ts'),
|
|
116
|
-
path.join(cwd, 'electron/preload.js'),
|
|
117
|
-
]
|
|
118
|
-
return candidates.find((p) => fs.existsSync(p)) || null
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function getExternalModules(cwd) {
|
|
122
|
-
try {
|
|
123
|
-
const pkg = require(path.join(cwd, 'package.json'))
|
|
124
|
-
return Object.keys(pkg.dependencies || {})
|
|
125
|
-
} catch { return [] }
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
module.exports = { buildMain, buildRenderer }
|
package/lib/config.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Normalize and apply defaults to plugin options.
|
|
5
|
-
* @param {import('..').ElectronBuilderOptions} options
|
|
6
|
-
* @returns {Required<import('..').ElectronBuilderOptions>}
|
|
7
|
-
*/
|
|
8
|
-
function getConfig(options = {}) {
|
|
9
|
-
return {
|
|
10
|
-
mainProcessFile: options.mainProcessFile || 'src/background.js',
|
|
11
|
-
outputDir: options.outputDir || 'dist_electron',
|
|
12
|
-
mainProcessViteConfig: options.mainProcessViteConfig || {},
|
|
13
|
-
rendererViteConfig: options.rendererViteConfig || {},
|
|
14
|
-
builderOptions: options.builderOptions || {},
|
|
15
|
-
externals: options.externals || [],
|
|
16
|
-
nodeIntegration: options.nodeIntegration === true,
|
|
17
|
-
contextIsolation: options.contextIsolation !== false,
|
|
18
|
-
preload: options.preload || null,
|
|
19
|
-
customFileProtocol: options.customFileProtocol || 'app',
|
|
20
|
-
disableMainProcessTypescript: options.disableMainProcessTypescript === true,
|
|
21
|
-
electronCliArgs: options.electronCliArgs || []
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
module.exports = { getConfig }
|
package/lib/nativeDeps.js
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const path = require('path')
|
|
4
|
-
const fs = require('fs-extra')
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Detect native (C++ addon) dependencies in the project's node_modules.
|
|
8
|
-
* Returns a list of package names that contain .node binaries.
|
|
9
|
-
*
|
|
10
|
-
* @param {string} projectRoot
|
|
11
|
-
* @returns {Promise<string[]>}
|
|
12
|
-
*/
|
|
13
|
-
async function getNativeDeps(projectRoot) {
|
|
14
|
-
const pkgJsonPath = path.join(projectRoot, 'package.json')
|
|
15
|
-
|
|
16
|
-
if (!fs.existsSync(pkgJsonPath)) {
|
|
17
|
-
return []
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const pkg = await fs.readJson(pkgJsonPath)
|
|
21
|
-
const allDeps = {
|
|
22
|
-
...pkg.dependencies,
|
|
23
|
-
...pkg.optionalDependencies
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const nativeDeps = []
|
|
27
|
-
|
|
28
|
-
for (const depName of Object.keys(allDeps)) {
|
|
29
|
-
const depDir = path.join(projectRoot, 'node_modules', depName)
|
|
30
|
-
|
|
31
|
-
if (await isNativeDep(depDir)) {
|
|
32
|
-
nativeDeps.push(depName)
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return nativeDeps
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Check if a package directory contains native bindings.
|
|
41
|
-
* @param {string} depDir
|
|
42
|
-
* @returns {Promise<boolean>}
|
|
43
|
-
*/
|
|
44
|
-
async function isNativeDep(depDir) {
|
|
45
|
-
if (!fs.existsSync(depDir)) return false
|
|
46
|
-
|
|
47
|
-
try {
|
|
48
|
-
// Check for .node files (compiled native addons)
|
|
49
|
-
const files = await walkDir(depDir)
|
|
50
|
-
return files.some(f => f.endsWith('.node'))
|
|
51
|
-
} catch {
|
|
52
|
-
return false
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Recursively list files in a directory.
|
|
58
|
-
* Skips node_modules sub-directories.
|
|
59
|
-
* @param {string} dir
|
|
60
|
-
* @returns {Promise<string[]>}
|
|
61
|
-
*/
|
|
62
|
-
async function walkDir(dir) {
|
|
63
|
-
const results = []
|
|
64
|
-
|
|
65
|
-
if (!fs.existsSync(dir)) return results
|
|
66
|
-
|
|
67
|
-
const entries = await fs.readdir(dir, { withFileTypes: true })
|
|
68
|
-
|
|
69
|
-
for (const entry of entries) {
|
|
70
|
-
if (entry.name === 'node_modules') continue
|
|
71
|
-
|
|
72
|
-
const fullPath = path.join(dir, entry.name)
|
|
73
|
-
|
|
74
|
-
if (entry.isDirectory()) {
|
|
75
|
-
const sub = await walkDir(fullPath)
|
|
76
|
-
results.push(...sub)
|
|
77
|
-
} else {
|
|
78
|
-
results.push(fullPath)
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return results
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
module.exports = { getNativeDeps, isNativeDep }
|