@witchcraft/nuxt-electron 0.0.9 → 0.0.11
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/dist/module.d.mts +117 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +364 -13
- package/dist/runtime/components/ElectronWindowControls.d.vue.ts +32 -0
- package/dist/runtime/components/ElectronWindowControls.vue +67 -0
- package/dist/runtime/components/ElectronWindowControls.vue.d.ts +32 -0
- package/dist/runtime/components/WindowControls/CloseButton.d.vue.ts +17 -0
- package/dist/runtime/components/WindowControls/CloseButton.vue +54 -0
- package/dist/runtime/components/WindowControls/CloseButton.vue.d.ts +17 -0
- package/dist/runtime/components/WindowControls/MaximizeButton.d.vue.ts +17 -0
- package/dist/runtime/components/WindowControls/MaximizeButton.vue +33 -0
- package/dist/runtime/components/WindowControls/MaximizeButton.vue.d.ts +17 -0
- package/dist/runtime/components/WindowControls/MinimizeButton.d.vue.ts +17 -0
- package/dist/runtime/components/WindowControls/MinimizeButton.vue +40 -0
- package/dist/runtime/components/WindowControls/MinimizeButton.vue.d.ts +17 -0
- package/dist/runtime/components/WindowControls/PinButton.d.vue.ts +28 -0
- package/dist/runtime/components/WindowControls/PinButton.vue +52 -0
- package/dist/runtime/components/WindowControls/PinButton.vue.d.ts +28 -0
- package/dist/runtime/electron/apiBuilder.d.ts +8 -0
- package/dist/runtime/electron/apiBuilder.js +9 -0
- package/dist/runtime/electron/createBroadcastHandlers.d.ts +4 -0
- package/dist/runtime/electron/createBroadcastHandlers.js +30 -0
- package/dist/runtime/electron/createBroadcaster.d.ts +2 -0
- package/dist/runtime/electron/createBroadcaster.js +7 -0
- package/dist/runtime/electron/createNuxtFileProtocolHandler.d.ts +14 -0
- package/dist/runtime/electron/createNuxtFileProtocolHandler.js +20 -0
- package/dist/runtime/electron/createWindowControlsApi.d.ts +19 -0
- package/dist/runtime/electron/createWindowControlsApi.js +6 -0
- package/dist/runtime/electron/createWindowControlsApiHandler.d.ts +4 -0
- package/dist/runtime/electron/createWindowControlsApiHandler.js +24 -0
- package/dist/runtime/electron/getEventWindow.d.ts +11 -0
- package/dist/runtime/electron/getEventWindow.js +8 -0
- package/dist/runtime/electron/getPaths.d.ts +27 -0
- package/dist/runtime/electron/getPaths.js +33 -0
- package/dist/runtime/electron/getPreloadMeta.d.ts +25 -0
- package/dist/runtime/electron/getPreloadMeta.js +7 -0
- package/dist/runtime/electron/index.d.ts +16 -0
- package/dist/runtime/electron/index.js +16 -0
- package/dist/runtime/electron/promisifyApi.d.ts +40 -0
- package/dist/runtime/electron/promisifyApi.js +41 -0
- package/dist/runtime/electron/promisifyReply.d.ts +8 -0
- package/dist/runtime/electron/promisifyReply.js +29 -0
- package/dist/runtime/electron/registerDevtoolsShortcuts.d.ts +2 -0
- package/dist/runtime/electron/registerDevtoolsShortcuts.js +10 -0
- package/dist/runtime/electron/static.d.ts +12 -0
- package/dist/runtime/electron/static.js +8 -0
- package/dist/runtime/electron/types.d.ts +1 -0
- package/dist/runtime/electron/types.js +0 -0
- package/dist/runtime/electron/useDevDataDir.d.ts +1 -0
- package/dist/runtime/electron/useDevDataDir.js +8 -0
- package/dist/runtime/electron/useNuxtRuntimeConfig.d.ts +2 -0
- package/dist/runtime/electron/useNuxtRuntimeConfig.js +4 -0
- package/dist/runtime/utils/isElectron.d.ts +9 -0
- package/dist/runtime/utils/isElectron.js +3 -0
- package/dist/types.d.mts +2 -12
- package/genDevDesktop.js +5 -0
- package/package.json +91 -92
- package/dist/module.d.cts +0 -2
package/dist/module.d.mts
CHANGED
|
@@ -1,2 +1,117 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
import { ElectronOptions } from 'vite-plugin-electron';
|
|
3
|
+
import { notBundle } from 'vite-plugin-electron/plugin';
|
|
4
|
+
|
|
5
|
+
interface ModuleOptions {
|
|
6
|
+
srcDir: string;
|
|
7
|
+
/**
|
|
8
|
+
* The dir for building for electron. `.output` and `build` will be put in here, and also release (but that's left up to your electron packing configuration).
|
|
9
|
+
*
|
|
10
|
+
* @default ".dist/electron/"
|
|
11
|
+
*/
|
|
12
|
+
electronBuildDir: string;
|
|
13
|
+
/**
|
|
14
|
+
* The nuxt output dir when not building electron.
|
|
15
|
+
*
|
|
16
|
+
* @default ".dist/web/.output"
|
|
17
|
+
*/
|
|
18
|
+
nonElectronNuxtBuildDir: string;
|
|
19
|
+
/**
|
|
20
|
+
* The main route of the electron app. Electron will be pointed to this route.
|
|
21
|
+
*
|
|
22
|
+
* @default "/app"
|
|
23
|
+
*/
|
|
24
|
+
electronRoute: string;
|
|
25
|
+
/**
|
|
26
|
+
* Additional routes to include in the electron build. Note that "/" is always included as not including it was causing issues.
|
|
27
|
+
*/
|
|
28
|
+
additionalRoutes: string[];
|
|
29
|
+
/** Extra cli arguments to launch electron with in dev mode */
|
|
30
|
+
extraCliArgs: string[];
|
|
31
|
+
/**
|
|
32
|
+
* If set, adds `--dev-user-data-dir ${devUserDataDir}` to the cli arguments in development mode.
|
|
33
|
+
*
|
|
34
|
+
* You will then need to parse this in main.ts, a `useDevDataDir` function is provided for this. This does not do any advanced parsing, just takes the next argument after `--dev-user-data-dir` so the path must not contain spaces.
|
|
35
|
+
* ```ts
|
|
36
|
+
* const userDataDir = useDevDataDir() ?? app.getPath("userData")
|
|
37
|
+
*
|
|
38
|
+
* @default "~~/.user-data-dir"
|
|
39
|
+
*/
|
|
40
|
+
devUserDataDir: string | null;
|
|
41
|
+
/**
|
|
42
|
+
* The script to run to build/pack the electron app.
|
|
43
|
+
*
|
|
44
|
+
* @default "npm run build:electron:pack"
|
|
45
|
+
*/
|
|
46
|
+
electronBuildPackScript: string;
|
|
47
|
+
/** Whether to enable the module. */
|
|
48
|
+
enable: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Whether to auto-open electron. If undefined, is controlled by the AUTO_OPEN env variable instead (it should include the word `electron` to enable autoOpen).
|
|
51
|
+
*
|
|
52
|
+
* This only works in dev mode.
|
|
53
|
+
*
|
|
54
|
+
* @default undefined
|
|
55
|
+
*/
|
|
56
|
+
autoOpen: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Pass public runtime config options only for electron.
|
|
59
|
+
*/
|
|
60
|
+
electronOnlyRuntimeConfig: Record<string, any>;
|
|
61
|
+
/**
|
|
62
|
+
* Whether you're using a preload script.
|
|
63
|
+
*
|
|
64
|
+
* @default true
|
|
65
|
+
*/
|
|
66
|
+
usePreloadScript: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Pass custom vite options to the electron vite builder (e.g. wasm()) as they are not copied over from nuxt's vite config.
|
|
69
|
+
*
|
|
70
|
+
* Note that `build.emptyOutDir` cannot be changed, it must be false for the reloading to work.
|
|
71
|
+
*/
|
|
72
|
+
electronViteOptions: ElectronOptions["vite"];
|
|
73
|
+
notBundleOptions: Parameters<typeof notBundle>[0];
|
|
74
|
+
/**
|
|
75
|
+
* Additional variables to "bake" into the electron build. Note these must be quoted if they are strings.
|
|
76
|
+
*
|
|
77
|
+
* You can set these as properties of STATIC, to make it clearer what they are.
|
|
78
|
+
*
|
|
79
|
+
* ```ts
|
|
80
|
+
* import { STATIC } from "@witchcraft/nuxt-electron/electron"
|
|
81
|
+
*
|
|
82
|
+
* // assuming electron.additionalElectronVariables.someVariable = `"some-var"`
|
|
83
|
+
*
|
|
84
|
+
* STATIC.SOME_VARIABLE = process.env.SOME_VARIABLE
|
|
85
|
+
*
|
|
86
|
+
* // becomes
|
|
87
|
+
* STATIC.SOME_VARIABLE = "some-var"
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
additionalElectronVariables: Record<string, string>;
|
|
91
|
+
/**
|
|
92
|
+
* Additional vite defines to copy from the resolved vite config.
|
|
93
|
+
*
|
|
94
|
+
* The module copies the following defines from nuxt's vite config for the electron vite config:
|
|
95
|
+
*
|
|
96
|
+
* ```
|
|
97
|
+
* __NUXT_VERSION__
|
|
98
|
+
* process.dev
|
|
99
|
+
* import.meta.dev
|
|
100
|
+
* process.test
|
|
101
|
+
* import.meta.test
|
|
102
|
+
*```
|
|
103
|
+
* And the following are also added:
|
|
104
|
+
* ```
|
|
105
|
+
* import.meta.electron (true from main, false elsewhere)
|
|
106
|
+
* process.electron (true from main, false elsewhere)
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* They will only be true for files that might be imported by main only. For renderer/client side use `isElectron()` instead. We cannot define them on the client side because during dev they would be wrong (electorn is always pointing to the same page as the server).
|
|
110
|
+
*
|
|
111
|
+
*/
|
|
112
|
+
additionalViteDefinesToCopy: string[];
|
|
113
|
+
}
|
|
114
|
+
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
115
|
+
|
|
116
|
+
export { _default as default };
|
|
117
|
+
export type { ModuleOptions };
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,18 +1,369 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { crop } from '@alanscodelog/utils/crop';
|
|
2
|
+
import { run } from '@alanscodelog/utils/run';
|
|
3
|
+
import { defineNuxtModule, useLogger, createResolver, addComponentsDir, addTemplate, extendRouteRules, addImportsDir } from '@nuxt/kit';
|
|
4
|
+
import { nuxtRemoveUneededPages, nuxtFileBasedRouting, nuxtRerouteOutputTo, createConstantCaseVariables } from '@witchcraft/nuxt-utils/utils';
|
|
5
|
+
import { defu } from 'defu';
|
|
6
|
+
import fs from 'node:fs/promises';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { startup, build } from 'vite-plugin-electron';
|
|
9
|
+
import { notBundle } from 'vite-plugin-electron/plugin';
|
|
10
|
+
import { externalizeDeps } from 'vite-plugin-externalize-deps';
|
|
2
11
|
|
|
3
|
-
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
|
|
12
|
+
startup.exit = async () => {
|
|
13
|
+
if ("electronApp" in process) {
|
|
14
|
+
try {
|
|
15
|
+
const app = process.electronApp;
|
|
16
|
+
app.removeAllListeners();
|
|
17
|
+
process.kill(app.pid);
|
|
18
|
+
} catch (e) {
|
|
19
|
+
console.error("Could not kill electron instance/s.");
|
|
20
|
+
console.error(e);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const module = defineNuxtModule({
|
|
25
|
+
meta: {
|
|
26
|
+
name: "electron",
|
|
27
|
+
configKey: "electron"
|
|
28
|
+
},
|
|
29
|
+
// Default configuration options of the Nuxt module
|
|
30
|
+
defaults: {
|
|
31
|
+
srcDir: "~~/app-electron",
|
|
32
|
+
electronBuildDir: "~~/.dist/electron",
|
|
33
|
+
nonElectronNuxtBuildDir: "~~/.dist/web/.output",
|
|
34
|
+
devUserDataDir: void 0,
|
|
35
|
+
electronRoute: "/app",
|
|
36
|
+
autoOpen: process.env.AUTO_OPEN?.includes("electron"),
|
|
37
|
+
electronBuildPackScript: "npm run build:electron:pack",
|
|
38
|
+
additionalRoutes: [],
|
|
39
|
+
extraCliArgs: [],
|
|
40
|
+
enable: true,
|
|
41
|
+
electronOnlyRuntimeConfig: {},
|
|
42
|
+
usePreloadScript: true,
|
|
43
|
+
electronViteOptions: {},
|
|
44
|
+
additionalElectronVariables: {},
|
|
45
|
+
additionalViteDefinesToCopy: [],
|
|
46
|
+
notBundleOptions: {}
|
|
7
47
|
},
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
"
|
|
48
|
+
moduleDependencies: {
|
|
49
|
+
"@witchcraft/ui/nuxt": {
|
|
50
|
+
version: "^0.3.2"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
async setup(options, nuxt) {
|
|
54
|
+
if (options.devUserDataDir === void 0) {
|
|
55
|
+
options.devUserDataDir = "~~/.user-data-dir";
|
|
56
|
+
}
|
|
57
|
+
if (!options.enable) {
|
|
58
|
+
return;
|
|
11
59
|
}
|
|
60
|
+
const moduleName = "@witchcraft/nuxt-electron";
|
|
61
|
+
const logger = useLogger(moduleName);
|
|
62
|
+
const { resolvePath, resolve } = createResolver(import.meta.url);
|
|
63
|
+
addComponentsDir({
|
|
64
|
+
global: true,
|
|
65
|
+
path: resolve("runtime/components")
|
|
66
|
+
});
|
|
67
|
+
addTemplate({
|
|
68
|
+
filename: "witchcraft-electron.css",
|
|
69
|
+
write: true,
|
|
70
|
+
getContents: () => crop`
|
|
71
|
+
@source "${resolve("runtime/components")}";
|
|
72
|
+
`
|
|
73
|
+
});
|
|
74
|
+
const isDev = nuxt.options.dev;
|
|
75
|
+
const srcDir = await resolvePath(options.srcDir, nuxt.options.alias);
|
|
76
|
+
const nonElectronNuxtBuildDir = await resolvePath(options.nonElectronNuxtBuildDir, nuxt.options.alias);
|
|
77
|
+
const electronRootBuildDir = await resolvePath(options.electronBuildDir, nuxt.options.alias);
|
|
78
|
+
const relativeElectronDir = path.relative(nuxt.options.rootDir, electronRootBuildDir);
|
|
79
|
+
const electronNuxtDir = path.join(relativeElectronDir, ".output");
|
|
80
|
+
const electronBuildDir = path.join(relativeElectronDir, "build");
|
|
81
|
+
const electronProdUrl = `${options.electronRoute}/index.html`;
|
|
82
|
+
const electronRoute = options.electronRoute;
|
|
83
|
+
const electronNuxtPublicDir = path.join(electronNuxtDir, "public");
|
|
84
|
+
const mainScriptPath = path.join(srcDir, "main.ts");
|
|
85
|
+
const preloadScriptPath = path.join(srcDir, "preload.ts");
|
|
86
|
+
const hasMainScript = await fs.stat(mainScriptPath).then(() => true).catch(() => false);
|
|
87
|
+
const hasPreloadScript = !options.usePreloadScript || await fs.stat(preloadScriptPath).then(() => true).catch(() => false);
|
|
88
|
+
const hasScripts = hasMainScript && hasPreloadScript;
|
|
89
|
+
if (!hasScripts) {
|
|
90
|
+
logger.warn(`Missing electron scripts: ${[hasMainScript ? "" : "main.ts", hasPreloadScript ? "" : "preload.ts"].join(", ")}. Skipping electron build.`);
|
|
91
|
+
}
|
|
92
|
+
const isElectronBuild = process.env.BUILD_ELECTRON === "true" && hasScripts;
|
|
93
|
+
const skipElectronPack = process.env.SKIP_ELECTRON_PACK === "true";
|
|
94
|
+
const autoOpen = !!(options.autoOpen && hasScripts && isDev);
|
|
95
|
+
const useWatch = nuxt.options.dev;
|
|
96
|
+
const devUserDataDir = options.devUserDataDir && await resolvePath(options.devUserDataDir, nuxt.options.alias);
|
|
97
|
+
if (devUserDataDir) {
|
|
98
|
+
if (!await fs.stat(devUserDataDir).then(() => true).catch(() => false)) {
|
|
99
|
+
await fs.mkdir(devUserDataDir, {
|
|
100
|
+
recursive: true
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
logger.debug({
|
|
105
|
+
isDev,
|
|
106
|
+
useWatch,
|
|
107
|
+
srcDir,
|
|
108
|
+
prodNonElectronNuxtDir: nonElectronNuxtBuildDir,
|
|
109
|
+
electronRootBuildDir,
|
|
110
|
+
relativeElectronDir,
|
|
111
|
+
electronNuxtDir,
|
|
112
|
+
electronBuildDir,
|
|
113
|
+
electronProdUrl,
|
|
114
|
+
electronRoute,
|
|
115
|
+
electronNuxtPublicDir,
|
|
116
|
+
mainScriptPath,
|
|
117
|
+
preloadScriptPath,
|
|
118
|
+
isElectronBuild,
|
|
119
|
+
skipElectronPack,
|
|
120
|
+
autoOpen,
|
|
121
|
+
devUserDataDir
|
|
122
|
+
});
|
|
123
|
+
let resolveGetViteServer;
|
|
124
|
+
const viteServerPromise = new Promise((resolve2) => {
|
|
125
|
+
resolveGetViteServer = resolve2;
|
|
126
|
+
});
|
|
127
|
+
nuxt.hook("vite:serverCreated", (server) => {
|
|
128
|
+
logger.info(`Resolved vite server.`);
|
|
129
|
+
resolveGetViteServer(server);
|
|
130
|
+
});
|
|
131
|
+
const viteServerUrl = new Promise((resolve2) => {
|
|
132
|
+
nuxt.hook("build:before", () => {
|
|
133
|
+
resolve2(void 0);
|
|
134
|
+
});
|
|
135
|
+
nuxt.hook("listen", (_server, listener) => {
|
|
136
|
+
logger.info(`Resolved server url.`, listener.url);
|
|
137
|
+
resolve2(listener.url);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
const viteConfigPromise = new Promise((resolve2) => {
|
|
141
|
+
nuxt.hook("vite:configResolved", (config) => {
|
|
142
|
+
resolve2(config);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
let maybeWatchers;
|
|
146
|
+
let started = false;
|
|
147
|
+
nuxt.hook("vite:extendConfig", (config) => {
|
|
148
|
+
config.define ??= {};
|
|
149
|
+
config.define["import.meta.electron"] = "false";
|
|
150
|
+
config.define["process.electron"] = "false";
|
|
151
|
+
});
|
|
152
|
+
const buildElectron = async () => {
|
|
153
|
+
if (maybeWatchers || started) return;
|
|
154
|
+
started = true;
|
|
155
|
+
const viteConfig = await viteConfigPromise;
|
|
156
|
+
const electronRuntimeConfig = defu(
|
|
157
|
+
options.electronOnlyRuntimeConfig,
|
|
158
|
+
nuxt.options.runtimeConfig.public
|
|
159
|
+
);
|
|
160
|
+
const additionalElectronVariables = defu(
|
|
161
|
+
options.additionalElectronVariables,
|
|
162
|
+
nuxt.options.electron.additionalElectronVariables
|
|
163
|
+
);
|
|
164
|
+
const additionalViteDefinesToCopy = [
|
|
165
|
+
...options.additionalViteDefinesToCopy,
|
|
166
|
+
...nuxt.options.electron.additionalViteDefinesToCopy ?? []
|
|
167
|
+
];
|
|
168
|
+
const copyFromVite = [
|
|
169
|
+
"__NUXT_VERSION__",
|
|
170
|
+
"process.dev",
|
|
171
|
+
"import.meta.dev",
|
|
172
|
+
"process.test",
|
|
173
|
+
"import.meta.test",
|
|
174
|
+
...additionalViteDefinesToCopy
|
|
175
|
+
];
|
|
176
|
+
const electronVariables = {
|
|
177
|
+
"process.electron": true,
|
|
178
|
+
"import.meta.electron": true,
|
|
179
|
+
...Object.fromEntries(
|
|
180
|
+
copyFromVite.map((v) => [v, viteConfig.define[v]])
|
|
181
|
+
),
|
|
182
|
+
...createConstantCaseVariables({
|
|
183
|
+
electronRoute,
|
|
184
|
+
electronProdUrl,
|
|
185
|
+
electronNuxtDir,
|
|
186
|
+
electronNuxtPublicDir,
|
|
187
|
+
electronBuildDir,
|
|
188
|
+
// ...options.additionalElectronVariables,
|
|
189
|
+
// nuxt's runtimeConfig cannot be used in electron's main since it's built seperately
|
|
190
|
+
// also we must stringify ourselves since escaped double quotes are not preserved in the final output :/
|
|
191
|
+
electronRuntimeConfig: JSON.stringify(electronRuntimeConfig).replaceAll("\\", "\\\\")
|
|
192
|
+
}, "process.env."),
|
|
193
|
+
// wut am having issue with just using STATIC. directly ???
|
|
194
|
+
...createConstantCaseVariables(
|
|
195
|
+
additionalElectronVariables,
|
|
196
|
+
"process.env.",
|
|
197
|
+
{ autoquote: false }
|
|
198
|
+
)
|
|
199
|
+
};
|
|
200
|
+
const electronViteOptions = defu(
|
|
201
|
+
{
|
|
202
|
+
build: {
|
|
203
|
+
// must be false or preload can get deleted when vite rebuilds
|
|
204
|
+
emptyOutDir: false
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
options.electronViteOptions,
|
|
208
|
+
{
|
|
209
|
+
build: {
|
|
210
|
+
outDir: electronBuildDir,
|
|
211
|
+
minify: false
|
|
212
|
+
},
|
|
213
|
+
define: electronVariables,
|
|
214
|
+
resolve: {
|
|
215
|
+
alias: nuxt.options.alias,
|
|
216
|
+
extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"]
|
|
217
|
+
},
|
|
218
|
+
plugins: [externalizeDeps()]
|
|
219
|
+
}
|
|
220
|
+
);
|
|
221
|
+
const electronCliArgs = [
|
|
222
|
+
".",
|
|
223
|
+
...process.env.NODE_ENV !== "production" && devUserDataDir ? [
|
|
224
|
+
"--dev-user-data-dir",
|
|
225
|
+
devUserDataDir
|
|
226
|
+
] : [],
|
|
227
|
+
...options.extraCliArgs ?? []
|
|
228
|
+
];
|
|
229
|
+
const builds = [
|
|
230
|
+
{
|
|
231
|
+
entry: mainScriptPath,
|
|
232
|
+
onStart: autoOpen ? async () => {
|
|
233
|
+
await startup([...electronCliArgs]);
|
|
234
|
+
} : void 0
|
|
235
|
+
},
|
|
236
|
+
...options.usePreloadScript ? [{
|
|
237
|
+
entry: preloadScriptPath,
|
|
238
|
+
onStart: async () => {
|
|
239
|
+
(await viteServerPromise).hot.send({ type: "full-reload" });
|
|
240
|
+
},
|
|
241
|
+
build: {
|
|
242
|
+
rollupOptions: {
|
|
243
|
+
output: {
|
|
244
|
+
inlineDynamicImports: true
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}] : []
|
|
249
|
+
].map((entry) => ({
|
|
250
|
+
vite: {
|
|
251
|
+
mode: process.env.NODE_ENV,
|
|
252
|
+
...electronViteOptions,
|
|
253
|
+
build: {
|
|
254
|
+
watch: useWatch ? {
|
|
255
|
+
include: [`${srcDir}/**/*`]
|
|
256
|
+
} : null,
|
|
257
|
+
lib: {
|
|
258
|
+
entry: entry.entry,
|
|
259
|
+
formats: entry.entry.includes("preload") ? ["cjs"] : ["es"],
|
|
260
|
+
fileName: () => entry.entry.includes("preload") ? "[name].cjs" : "[name].mjs"
|
|
261
|
+
},
|
|
262
|
+
...electronViteOptions.build
|
|
263
|
+
},
|
|
264
|
+
plugins: [
|
|
265
|
+
autoOpen ? {
|
|
266
|
+
name: "plugin-start-electron",
|
|
267
|
+
async closeBundle() {
|
|
268
|
+
void entry.onStart?.();
|
|
269
|
+
}
|
|
270
|
+
} : void 0,
|
|
271
|
+
// not bundle breaks preload because it tries to required from node_modules
|
|
272
|
+
// and sandboxed windows can't do that
|
|
273
|
+
...!isElectronBuild && !entry.entry.includes("preload") ? [notBundle(options.notBundleOptions)] : [],
|
|
274
|
+
...electronViteOptions.plugins ?? []
|
|
275
|
+
]
|
|
276
|
+
}
|
|
277
|
+
}));
|
|
278
|
+
logger.debug(builds);
|
|
279
|
+
const devUrl = await viteServerUrl;
|
|
280
|
+
if (devUrl) {
|
|
281
|
+
Object.assign(process.env, {
|
|
282
|
+
VITE_DEV_SERVER_URL: devUrl.slice(0, -1)
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
logger.debug({
|
|
286
|
+
electronViteOptions,
|
|
287
|
+
prodNonElectronNuxtDir: nonElectronNuxtBuildDir,
|
|
288
|
+
electronVariables,
|
|
289
|
+
electronRuntimeConfig,
|
|
290
|
+
electronCliArgs,
|
|
291
|
+
devUrl
|
|
292
|
+
});
|
|
293
|
+
maybeWatchers = await Promise.all(builds.map(
|
|
294
|
+
async (config) => build(config).then((res) => {
|
|
295
|
+
logger.info(`Build done.`);
|
|
296
|
+
return res;
|
|
297
|
+
}).catch((err) => {
|
|
298
|
+
logger.error(`Build failed.`, err);
|
|
299
|
+
process.exit(1);
|
|
300
|
+
})
|
|
301
|
+
));
|
|
302
|
+
if (useWatch) {
|
|
303
|
+
for (const maybeWatcher of maybeWatchers) {
|
|
304
|
+
if (maybeWatcher && "on" in maybeWatcher) {
|
|
305
|
+
maybeWatcher.on("change", (e) => {
|
|
306
|
+
logger.info(`Detected change in: ${e}`);
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
if (autoOpen) {
|
|
313
|
+
nuxt.hook("close", async () => {
|
|
314
|
+
logger.info(`Killing`);
|
|
315
|
+
await startup?.exit();
|
|
316
|
+
});
|
|
317
|
+
nuxt.hook("restart", async () => {
|
|
318
|
+
logger.info(`Killing and Restarting`);
|
|
319
|
+
await startup?.exit();
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
logger.info(`Building Electron: ${isElectronBuild}`);
|
|
323
|
+
if (isElectronBuild) {
|
|
324
|
+
nuxt.hook("build:manifest", (manifest) => {
|
|
325
|
+
for (const key of Object.keys(manifest)) {
|
|
326
|
+
manifest[key].dynamicImports = [];
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
nuxtRemoveUneededPages(nuxt, ["/", electronRoute, ...options.additionalRoutes]);
|
|
330
|
+
extendRouteRules(electronRoute, { ssr: false, prerender: true }, { override: true });
|
|
331
|
+
nuxt.options.router = defu(
|
|
332
|
+
nuxtFileBasedRouting().router,
|
|
333
|
+
nuxt.options.router ?? {}
|
|
334
|
+
);
|
|
335
|
+
nuxtRerouteOutputTo(nuxt, electronNuxtDir);
|
|
336
|
+
nuxt.hook("close", async () => {
|
|
337
|
+
logger.info(`Building Electron`);
|
|
338
|
+
await buildElectron();
|
|
339
|
+
if (!skipElectronPack) {
|
|
340
|
+
logger.info(`Packing Electron`);
|
|
341
|
+
const buildCommand = run(options.electronBuildPackScript, {
|
|
342
|
+
stdio: "inherit"
|
|
343
|
+
});
|
|
344
|
+
await buildCommand.promise.catch((err) => {
|
|
345
|
+
logger.error("Error building electron.", err);
|
|
346
|
+
process.exit(1);
|
|
347
|
+
});
|
|
348
|
+
} else {
|
|
349
|
+
logger.info(`Skipping Electron Pack`);
|
|
350
|
+
}
|
|
351
|
+
logger.info(`Done Building Electron`);
|
|
352
|
+
});
|
|
353
|
+
} else {
|
|
354
|
+
if (isDev) {
|
|
355
|
+
nuxt.hook("ready", async () => {
|
|
356
|
+
logger.info("electron - ready");
|
|
357
|
+
void buildElectron();
|
|
358
|
+
});
|
|
359
|
+
logger.info(`Watching Electron`);
|
|
360
|
+
} else {
|
|
361
|
+
logger.info(`Skipping Electron Build`);
|
|
362
|
+
}
|
|
363
|
+
nuxtRerouteOutputTo(nuxt, nonElectronNuxtBuildDir);
|
|
364
|
+
}
|
|
365
|
+
addImportsDir(resolve("runtime/utils"));
|
|
12
366
|
}
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
/** @type {import("/home/runner/work/nuxt-electron/nuxt-electron/src/module.js")} */
|
|
16
|
-
const _module = await jiti.import("/home/runner/work/nuxt-electron/nuxt-electron/src/module.ts");
|
|
367
|
+
});
|
|
17
368
|
|
|
18
|
-
export
|
|
369
|
+
export { module as default };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type Component } from "vue";
|
|
2
|
+
import type { WindowControlsApi } from "../electron/types.js";
|
|
3
|
+
type __VLS_Props = {
|
|
4
|
+
borderWidth?: string;
|
|
5
|
+
buttonSize?: string;
|
|
6
|
+
borderRadius?: string;
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* Replace any of the default buttons with your own components.
|
|
10
|
+
*
|
|
11
|
+
* Note that you can get the existing button components (import from `/components/WIndowControls/[name]`) and pass a slot to change the icon then pass your new component here.
|
|
12
|
+
*
|
|
13
|
+
* If using a completely custom component, it must emit an `action` event with the action name as the value.
|
|
14
|
+
*
|
|
15
|
+
* This wrapper component sets the following css variables if you need them:
|
|
16
|
+
* `--electron-wc-size`
|
|
17
|
+
* `--electron-wc-border`
|
|
18
|
+
* `--electron-wc-rounded`
|
|
19
|
+
* `--electron-wc-diagonal` (useful for creating the close cross)
|
|
20
|
+
*/
|
|
21
|
+
components?: Partial<Record<"CloseButton" | "MinimizeButton" | "MaximizeButton" | "PinButton", Component>>;
|
|
22
|
+
buttonsOrder?: ("CloseButton" | "MinimizeButton" | "MaximizeButton" | "PinButton")[];
|
|
23
|
+
handler?: WindowControlsApi;
|
|
24
|
+
};
|
|
25
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
26
|
+
borderWidth: string;
|
|
27
|
+
buttonSize: string;
|
|
28
|
+
borderRadius: string;
|
|
29
|
+
buttonsOrder: ("CloseButton" | "MinimizeButton" | "MaximizeButton" | "PinButton")[];
|
|
30
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
31
|
+
declare const _default: typeof __VLS_export;
|
|
32
|
+
export default _default;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<ClientOnly>
|
|
3
|
+
<div
|
|
4
|
+
v-if="isElectron()"
|
|
5
|
+
:class="twMerge(`
|
|
6
|
+
flex
|
|
7
|
+
items-center
|
|
8
|
+
gap-2
|
|
9
|
+
`, $attrs.class)"
|
|
10
|
+
v-bind="{ ...$attrs, class: void 0 }"
|
|
11
|
+
:style="`
|
|
12
|
+
--electron-wc-size:${props.buttonSize};
|
|
13
|
+
--electron-wc-border:${props.borderWidth};
|
|
14
|
+
--electron-wc-rounded:${props.borderRadius};
|
|
15
|
+
--electron-wc-diagonal:calc((var(--electron-wc-size) - var(--electron-wc-border)/2)*sqrt(2));
|
|
16
|
+
`"
|
|
17
|
+
>
|
|
18
|
+
<template
|
|
19
|
+
v-for="button in buttonsOrder"
|
|
20
|
+
:key="button"
|
|
21
|
+
>
|
|
22
|
+
<component
|
|
23
|
+
:is="componentsMap[button]"
|
|
24
|
+
@action="actionHandler($event)"
|
|
25
|
+
/>
|
|
26
|
+
</template>
|
|
27
|
+
</div>
|
|
28
|
+
</ClientOnly>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script setup>
|
|
32
|
+
import { computed, useAttrs } from "vue";
|
|
33
|
+
import CloseButton from "./WindowControls/CloseButton.vue";
|
|
34
|
+
import MaximizeButton from "./WindowControls/MaximizeButton.vue";
|
|
35
|
+
import MinimizeButton from "./WindowControls/MinimizeButton.vue";
|
|
36
|
+
import PinButton from "./WindowControls/PinButton.vue";
|
|
37
|
+
import { twMerge } from "#imports";
|
|
38
|
+
import { isElectron } from "../utils/isElectron.js";
|
|
39
|
+
const $attrs = useAttrs();
|
|
40
|
+
const props = defineProps({
|
|
41
|
+
borderWidth: { type: String, required: false, default: "2px" },
|
|
42
|
+
buttonSize: { type: String, required: false, default: "15px" },
|
|
43
|
+
borderRadius: { type: String, required: false, default: "1.5px" },
|
|
44
|
+
components: { type: Object, required: false },
|
|
45
|
+
buttonsOrder: { type: Array, required: false, default: () => ["PinButton", "MinimizeButton", "MaximizeButton", "CloseButton"] },
|
|
46
|
+
handler: { type: Function, required: false }
|
|
47
|
+
});
|
|
48
|
+
const componentsMap = computed(() => ({
|
|
49
|
+
CloseButton,
|
|
50
|
+
MinimizeButton,
|
|
51
|
+
MaximizeButton,
|
|
52
|
+
PinButton,
|
|
53
|
+
...props.components
|
|
54
|
+
}));
|
|
55
|
+
const actionHandler = computed(() => {
|
|
56
|
+
if (!isElectron()) return void 0;
|
|
57
|
+
if (!props.handler) {
|
|
58
|
+
const defaultHandlerPath = window.electron?.api?.ui?.windowAction;
|
|
59
|
+
if (defaultHandlerPath) {
|
|
60
|
+
return defaultHandlerPath;
|
|
61
|
+
} else {
|
|
62
|
+
console.warn("No ElectronWindowControls handler specified and could not find default handler at `window.electron.api.ui.windowAction`");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return props.handler;
|
|
66
|
+
});
|
|
67
|
+
</script>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type Component } from "vue";
|
|
2
|
+
import type { WindowControlsApi } from "../electron/types.js";
|
|
3
|
+
type __VLS_Props = {
|
|
4
|
+
borderWidth?: string;
|
|
5
|
+
buttonSize?: string;
|
|
6
|
+
borderRadius?: string;
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* Replace any of the default buttons with your own components.
|
|
10
|
+
*
|
|
11
|
+
* Note that you can get the existing button components (import from `/components/WIndowControls/[name]`) and pass a slot to change the icon then pass your new component here.
|
|
12
|
+
*
|
|
13
|
+
* If using a completely custom component, it must emit an `action` event with the action name as the value.
|
|
14
|
+
*
|
|
15
|
+
* This wrapper component sets the following css variables if you need them:
|
|
16
|
+
* `--electron-wc-size`
|
|
17
|
+
* `--electron-wc-border`
|
|
18
|
+
* `--electron-wc-rounded`
|
|
19
|
+
* `--electron-wc-diagonal` (useful for creating the close cross)
|
|
20
|
+
*/
|
|
21
|
+
components?: Partial<Record<"CloseButton" | "MinimizeButton" | "MaximizeButton" | "PinButton", Component>>;
|
|
22
|
+
buttonsOrder?: ("CloseButton" | "MinimizeButton" | "MaximizeButton" | "PinButton")[];
|
|
23
|
+
handler?: WindowControlsApi;
|
|
24
|
+
};
|
|
25
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
26
|
+
borderWidth: string;
|
|
27
|
+
buttonSize: string;
|
|
28
|
+
borderRadius: string;
|
|
29
|
+
buttonsOrder: ("CloseButton" | "MinimizeButton" | "MaximizeButton" | "PinButton")[];
|
|
30
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
31
|
+
declare const _default: typeof __VLS_export;
|
|
32
|
+
export default _default;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
declare var __VLS_10: {};
|
|
2
|
+
type __VLS_Slots = {} & {
|
|
3
|
+
default?: (props: typeof __VLS_10) => any;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
6
|
+
action: (action: "close") => any;
|
|
7
|
+
}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{
|
|
8
|
+
onAction?: ((action: "close") => any) | undefined;
|
|
9
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
10
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
11
|
+
declare const _default: typeof __VLS_export;
|
|
12
|
+
export default _default;
|
|
13
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
14
|
+
new (): {
|
|
15
|
+
$slots: S;
|
|
16
|
+
};
|
|
17
|
+
};
|