@witchcraft/nuxt-electron 0.0.9 → 0.1.0

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.
Files changed (58) hide show
  1. package/dist/module.d.mts +117 -2
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +364 -13
  4. package/dist/runtime/components/ElectronWindowControls.d.vue.ts +32 -0
  5. package/dist/runtime/components/ElectronWindowControls.vue +67 -0
  6. package/dist/runtime/components/ElectronWindowControls.vue.d.ts +32 -0
  7. package/dist/runtime/components/WindowControls/CloseButton.d.vue.ts +17 -0
  8. package/dist/runtime/components/WindowControls/CloseButton.vue +54 -0
  9. package/dist/runtime/components/WindowControls/CloseButton.vue.d.ts +17 -0
  10. package/dist/runtime/components/WindowControls/MaximizeButton.d.vue.ts +17 -0
  11. package/dist/runtime/components/WindowControls/MaximizeButton.vue +33 -0
  12. package/dist/runtime/components/WindowControls/MaximizeButton.vue.d.ts +17 -0
  13. package/dist/runtime/components/WindowControls/MinimizeButton.d.vue.ts +17 -0
  14. package/dist/runtime/components/WindowControls/MinimizeButton.vue +40 -0
  15. package/dist/runtime/components/WindowControls/MinimizeButton.vue.d.ts +17 -0
  16. package/dist/runtime/components/WindowControls/PinButton.d.vue.ts +28 -0
  17. package/dist/runtime/components/WindowControls/PinButton.vue +52 -0
  18. package/dist/runtime/components/WindowControls/PinButton.vue.d.ts +28 -0
  19. package/dist/runtime/electron/apiBuilder.d.ts +8 -0
  20. package/dist/runtime/electron/apiBuilder.js +9 -0
  21. package/dist/runtime/electron/createBroadcastHandlers.d.ts +4 -0
  22. package/dist/runtime/electron/createBroadcastHandlers.js +30 -0
  23. package/dist/runtime/electron/createBroadcaster.d.ts +2 -0
  24. package/dist/runtime/electron/createBroadcaster.js +7 -0
  25. package/dist/runtime/electron/createNuxtFileProtocolHandler.d.ts +14 -0
  26. package/dist/runtime/electron/createNuxtFileProtocolHandler.js +20 -0
  27. package/dist/runtime/electron/createWindowControlsApi.d.ts +19 -0
  28. package/dist/runtime/electron/createWindowControlsApi.js +6 -0
  29. package/dist/runtime/electron/createWindowControlsApiHandler.d.ts +4 -0
  30. package/dist/runtime/electron/createWindowControlsApiHandler.js +24 -0
  31. package/dist/runtime/electron/getEventWindow.d.ts +11 -0
  32. package/dist/runtime/electron/getEventWindow.js +8 -0
  33. package/dist/runtime/electron/getPaths.d.ts +27 -0
  34. package/dist/runtime/electron/getPaths.js +33 -0
  35. package/dist/runtime/electron/getPreloadMeta.d.ts +25 -0
  36. package/dist/runtime/electron/getPreloadMeta.js +7 -0
  37. package/dist/runtime/electron/index.d.ts +16 -0
  38. package/dist/runtime/electron/index.js +16 -0
  39. package/dist/runtime/electron/promisifyApi.d.ts +40 -0
  40. package/dist/runtime/electron/promisifyApi.js +41 -0
  41. package/dist/runtime/electron/promisifyReply.d.ts +8 -0
  42. package/dist/runtime/electron/promisifyReply.js +29 -0
  43. package/dist/runtime/electron/registerDevtoolsShortcuts.d.ts +2 -0
  44. package/dist/runtime/electron/registerDevtoolsShortcuts.js +10 -0
  45. package/dist/runtime/electron/static.d.ts +12 -0
  46. package/dist/runtime/electron/static.js +8 -0
  47. package/dist/runtime/electron/types.d.ts +1 -0
  48. package/dist/runtime/electron/types.js +0 -0
  49. package/dist/runtime/electron/useDevDataDir.d.ts +1 -0
  50. package/dist/runtime/electron/useDevDataDir.js +8 -0
  51. package/dist/runtime/electron/useNuxtRuntimeConfig.d.ts +2 -0
  52. package/dist/runtime/electron/useNuxtRuntimeConfig.js +4 -0
  53. package/dist/runtime/utils/isElectron.d.ts +9 -0
  54. package/dist/runtime/utils/isElectron.js +3 -0
  55. package/dist/types.d.mts +2 -12
  56. package/genDevDesktop.js +5 -0
  57. package/package.json +91 -92
  58. package/dist/module.d.cts +0 -2
@@ -0,0 +1,40 @@
1
+ import type { IpcRenderer } from "electron";
2
+ /**
3
+ * Promisify an electron api and make it type safe so it can be awaited client side. Note that promisifyReply will throw if it can't find a window.
4
+ *
5
+ * ```ts[type.st]
6
+ * export type ElectronApi = {
7
+ * api: {
8
+ * someApi: (apiParam: string, apiParam2: number) => Promise<void>
9
+ * }
10
+ * }
11
+ * ```
12
+ * ```ts [preload.ts]
13
+ * contextBridge.exposeInMainWorld("electron", {
14
+ * api: {
15
+ * ...promisifyApi<"someApi", ElectronApi["api"]["someApi"]>(ipcRenderer, "someApi", MESSAGE.UNIQUE_KEY),
16
+ * },
17
+ * })
18
+ * ```
19
+ *
20
+ * ```ts [main.ts]
21
+ * import { promisifyReply } from "@witchcraft/nuxt-electron/runtime/electron"
22
+ * promisifyReply<
23
+ * ElectronApi["api"]["someApi"]
24
+ * >(ipcRenderer, MESSAGE.UNIQUE_KEY, (win, apiParam, apiParam2) => {
25
+ * // this doesn't have to be async, though on the client side,
26
+ * // it will always be async
27
+ * return electronSideOfApi(apiParam, apiParam2)
28
+ * })
29
+ * ```
30
+ *
31
+ * ```ts [renderer.ts]
32
+ * const result = await electron.api.someApi(apiParam, apiParam2)
33
+ * ```
34
+ *
35
+ * By default, calls will timeout and reject after 10 seconds. This can be changed by changing the timeout option.
36
+ */
37
+ export declare function promisifyApi<TKey extends string, TFunction extends (...args: any) => Promise<any>, TArgs extends Parameters<TFunction> = Parameters<TFunction>>(ipcRenderer: IpcRenderer, key: TKey, messageKey: string, modifyArgs?: (args: TArgs) => any, { debug, timeout }?: {
38
+ debug?: boolean;
39
+ timeout?: number;
40
+ }): Record<TKey, TFunction>;
@@ -0,0 +1,41 @@
1
+ const promiseResolveMap = /* @__PURE__ */ new Map();
2
+ export function promisifyApi(ipcRenderer, key, messageKey, modifyArgs, { debug, timeout } = { debug: true, timeout: 1e4 }) {
3
+ return {
4
+ [key]: async (...args) => new Promise((resolve, reject) => {
5
+ const promiseId = crypto.randomUUID();
6
+ promiseResolveMap.set(promiseId, { resolve, reject });
7
+ if (modifyArgs) {
8
+ args = modifyArgs(args);
9
+ }
10
+ if (debug) {
11
+ console.log("promisifyApi:sent", messageKey, promiseId, args);
12
+ }
13
+ const timer = setTimeout(() => {
14
+ const resolver = promiseResolveMap.get(promiseId);
15
+ if (resolver) {
16
+ promiseResolveMap.delete(promiseId);
17
+ ipcRenderer.off(messageKey, listener);
18
+ resolver.reject(new Error(`promisifyApi: Timeout for ${messageKey}`));
19
+ }
20
+ }, timeout);
21
+ function listener(_event, resPromiseId, res, info) {
22
+ if (debug) {
23
+ console.log("promiseApi:received", resPromiseId, res);
24
+ }
25
+ const resolver = promiseResolveMap.get(resPromiseId);
26
+ if (resolver) {
27
+ clearTimeout(timer);
28
+ promiseResolveMap.delete(resPromiseId);
29
+ ipcRenderer.off(messageKey, listener);
30
+ if (info?.isError) {
31
+ resolver.reject(res);
32
+ } else {
33
+ resolver.resolve(res);
34
+ }
35
+ }
36
+ }
37
+ ipcRenderer.on(messageKey, listener);
38
+ ipcRenderer.send(messageKey, promiseId, ...args);
39
+ })
40
+ };
41
+ }
@@ -0,0 +1,8 @@
1
+ import { type BrowserWindow } from "electron";
2
+ /** See {@link promisifyApi} for more info. */
3
+ export declare function promisifyReply<TFunction extends ((...args: any[]) => any), TKey extends string = string, TArgs extends Parameters<TFunction> = Parameters<TFunction>, TReturn extends ReturnType<TFunction> = ReturnType<TFunction>>(key: TKey, cb: (win?: BrowserWindow, ...args: TArgs) => Promise<TReturn> | TReturn,
4
+ /** See {@link getEventWindow}. */
5
+ { defaultToFocused, debug }?: {
6
+ defaultToFocused?: boolean;
7
+ debug?: boolean;
8
+ }): void;
@@ -0,0 +1,29 @@
1
+ import { ipcMain } from "electron";
2
+ import { getEventWindow } from "./getEventWindow.js";
3
+ export function promisifyReply(key, cb, {
4
+ defaultToFocused = true,
5
+ debug = false
6
+ } = {}) {
7
+ ipcMain.on(key, (e, promiseId, ...args) => {
8
+ const win = getEventWindow(e, { defaultToFocused });
9
+ if (!win) {
10
+ const err = new Error("No window to send reply to.");
11
+ console.error(err, { key, promiseId, args });
12
+ throw err;
13
+ }
14
+ if (debug) {
15
+ console.log({ key, promiseId, args });
16
+ }
17
+ const res = cb(win, ...args);
18
+ if (res instanceof Promise) {
19
+ res.then((innerRes) => {
20
+ win.webContents.send(key, promiseId, innerRes);
21
+ }).catch((err) => {
22
+ console.error(err, { key, promiseId, args });
23
+ win.webContents.send(key, promiseId, err, { isError: true });
24
+ });
25
+ } else {
26
+ win.webContents.send(key, promiseId, res);
27
+ }
28
+ });
29
+ }
@@ -0,0 +1,2 @@
1
+ /** Registers F12 and Ctrl+Shift+I as shortcuts to open the devtools. */
2
+ export declare function registerDevtoolsShortcuts(win: Electron.BrowserWindow): void;
@@ -0,0 +1,10 @@
1
+ export function registerDevtoolsShortcuts(win) {
2
+ win.webContents.on("before-input-event", (event, input) => {
3
+ if (input.type === "keyDown") {
4
+ if (input.shift && input.control && input.key.toLowerCase() === "i" || input.key === "F12") {
5
+ win.webContents.openDevTools();
6
+ event.preventDefault();
7
+ }
8
+ }
9
+ });
10
+ }
@@ -0,0 +1,12 @@
1
+ import type { PublicRuntimeConfig } from "nuxt/schema";
2
+ /**
3
+ * Group of the module's vite's injected variables.
4
+ */
5
+ export declare const STATIC: {
6
+ ELECTRON_ROUTE: string;
7
+ ELECTRON_PROD_URL: string;
8
+ ELECTRON_NUXT_DIR: string;
9
+ ELECTRON_NUXT_PUBLIC_DIR: string;
10
+ ELECTRON_BUILD_DIR: string;
11
+ ELECTRON_RUNTIME_CONFIG: PublicRuntimeConfig;
12
+ };
@@ -0,0 +1,8 @@
1
+ export const STATIC = {
2
+ ELECTRON_ROUTE: process.env.ELECTRON_ROUTE,
3
+ ELECTRON_PROD_URL: process.env.ELECTRON_PROD_URL,
4
+ ELECTRON_NUXT_DIR: process.env.ELECTRON_NUXT_DIR,
5
+ ELECTRON_NUXT_PUBLIC_DIR: process.env.ELECTRON_NUXT_PUBLIC_DIR,
6
+ ELECTRON_BUILD_DIR: process.env.ELECTRON_BUILD_DIR,
7
+ ELECTRON_RUNTIME_CONFIG: process.env.ELECTRON_RUNTIME_CONFIG ? JSON.parse(process.env.ELECTRON_RUNTIME_CONFIG) : void 0
8
+ };
@@ -0,0 +1 @@
1
+ export type WindowControlsApi = (action: "close" | "minimize" | "toggleMaximize" | "togglePin") => Promise<void>;
File without changes
@@ -0,0 +1 @@
1
+ export declare function useDevDataDir(): string | undefined;
@@ -0,0 +1,8 @@
1
+ export function useDevDataDir() {
2
+ if (import.meta.dev) {
3
+ const index = process.argv.findIndex((arg) => arg.startsWith("--dev-user-data-dir"));
4
+ if (index === -1) return void 0;
5
+ return process.argv[index + 1];
6
+ }
7
+ return void 0;
8
+ }
@@ -0,0 +1,2 @@
1
+ import type { PublicRuntimeConfig } from "nuxt/schema";
2
+ export declare function useNuxtRuntimeConfig(): PublicRuntimeConfig;
@@ -0,0 +1,4 @@
1
+ import { STATIC } from "./static.js";
2
+ export function useNuxtRuntimeConfig() {
3
+ return STATIC.ELECTRON_RUNTIME_CONFIG;
4
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * This requires electron's preload script set the `electron` property on the window:
3
+ *
4
+ * ```ts
5
+ * // preload.ts
6
+ * contextBridge.exposeInMainWorld("electron", { })
7
+ * ```
8
+ */
9
+ export declare function isElectron(): boolean;
@@ -0,0 +1,3 @@
1
+ export function isElectron() {
2
+ return typeof window !== "undefined" && "electron" in window && typeof window.electron !== "undefined";
3
+ }
package/dist/types.d.mts CHANGED
@@ -1,13 +1,3 @@
1
- import type { ModuleHooks, ModuleRuntimeHooks, ModuleRuntimeConfig, ModulePublicRuntimeConfig } from './module.mjs'
1
+ export { default } from './module.mjs'
2
2
 
3
- declare module '#app' {
4
- interface RuntimeNuxtHooks extends ModuleRuntimeHooks {}
5
- }
6
-
7
- declare module '@nuxt/schema' {
8
- interface NuxtHooks extends ModuleHooks {}
9
- interface RuntimeConfig extends ModuleRuntimeConfig {}
10
- interface PublicRuntimeConfig extends ModulePublicRuntimeConfig {}
11
- }
12
-
13
- export * from "./module.mjs"
3
+ export { type ModuleOptions } from './module.mjs'
package/genDevDesktop.js CHANGED
@@ -3,6 +3,11 @@ import JSON5 from "json5"
3
3
  import fs from "node:fs/promises"
4
4
  import path from "node:path"
5
5
 
6
+ if (process.env.CI) {
7
+ console.log("Skipping desktop file generation in CI.")
8
+ process.exit(0)
9
+ }
10
+
6
11
  if (["darwin", "linux"].includes(process.platform)) {
7
12
  // eslint-disable-next-line no-console
8
13
  console.log("Generating dev desktop file.")
package/package.json CHANGED
@@ -1,93 +1,92 @@
1
1
  {
2
- "name": "@witchcraft/nuxt-electron",
3
- "version": "0.0.9",
4
- "description": "Nuxt module for working with electron.",
5
- "repository": "witchcraftjs/nuxt-electron",
6
- "license": "MIT",
7
- "type": "module",
8
- "sideEffects": false,
9
- "exports": {
10
- ".": {
11
- "types": "./dist/types.d.mts",
12
- "import": "./dist/module.mjs"
13
- },
14
- "./electron": {
15
- "types": "./dist/runtime/electron/index.d.ts",
16
- "import": "./dist/runtime/electron/index.js"
17
- },
18
- "./genDevDesktop": {
19
- "import": "./genDevDesktop.js"
20
- }
21
- },
22
- "files": [
23
- "src",
24
- "dist",
25
- "genDevDesktop.js"
26
- ],
27
- "scripts": {
28
- "prepare": "husky && pnpm dev:prepare",
29
- "build": "nuxt-module-build prepare && nuxt-module-build build && nuxi build playground",
30
- "build:only": "nuxt-module-build build",
31
- "dev": "nuxi dev playground",
32
- "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
33
- "lint": "eslint \"{src,test,playground/app}/**/*.{ts,vue}\" \"*.{js,cjs,mjs,ts}\"",
34
- "lint:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
35
- "test": "vitest run",
36
- "test:watch": "vitest watch"
37
- },
38
- "dependencies": {
39
- "@alanscodelog/utils": "catalog:",
40
- "@nuxt/kit": "catalog:",
41
- "@witchcraft/nuxt-utils": "catalog:",
42
- "@witchcraft/ui": "catalog:",
43
- "defu": "catalog:",
44
- "es-toolkit": "catalog:",
45
- "vite-plugin-electron": "catalog:",
46
- "vite-plugin-externalize-deps": "catalog:"
47
- },
48
- "peerDependencies": {
49
- "@witchcraft/ui": "catalog:",
50
- "unplugin-icons": "catalog:"
51
- },
52
- "peerDependenciesMeta": {
53
- "unplugin-icons": {
54
- "optional": true
55
- },
56
- "@witchcraft/ui": {
57
- "optional": true
58
- }
59
- },
60
- "devDependencies": {
61
- "@alanscodelog/eslint-config": "catalog:",
62
- "@alanscodelog/semantic-release-config": "catalog:",
63
- "@alanscodelog/tsconfigs": "catalog:",
64
- "@nuxt/eslint-config": "catalog:",
65
- "@nuxt/module-builder": "catalog:",
66
- "@nuxt/schema": "catalog:",
67
- "@nuxt/test-utils": "catalog:",
68
- "@types/node": "latest",
69
- "changelogen": "catalog:",
70
- "electron": "^38.0.0",
71
- "eslint": "catalog:",
72
- "husky": "catalog:",
73
- "json5": "catalog:",
74
- "nuxt": "catalog:",
75
- "typescript": "catalog:",
76
- "unplugin-icons": "catalog:",
77
- "vitest": "catalog:",
78
- "vue-tsc": "catalog:"
79
- },
80
- "release": {
81
- "extends": [
82
- "@alanscodelog/semantic-release-config"
83
- ]
84
- },
85
- "commitlint": {
86
- "extends": [
87
- "@alanscodelog"
88
- ]
89
- },
90
- "publishConfig": {
91
- "access": "public"
92
- }
93
- }
2
+ "name": "@witchcraft/nuxt-electron",
3
+ "version": "0.1.0",
4
+ "description": "Nuxt module for working with electron.",
5
+ "repository": "witchcraftjs/nuxt-electron",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "sideEffects": false,
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/types.d.mts",
12
+ "import": "./dist/module.mjs"
13
+ },
14
+ "./electron": {
15
+ "types": "./dist/runtime/electron/index.d.ts",
16
+ "import": "./dist/runtime/electron/index.js"
17
+ },
18
+ "./genDevDesktop": {
19
+ "import": "./genDevDesktop.js"
20
+ }
21
+ },
22
+ "files": [
23
+ "src",
24
+ "dist",
25
+ "genDevDesktop.js"
26
+ ],
27
+ "dependencies": {
28
+ "@alanscodelog/utils": "^6.0.2",
29
+ "@nuxt/kit": "^4.0.3",
30
+ "@witchcraft/nuxt-utils": "^0.3.6",
31
+ "@witchcraft/ui": "^0.3.7",
32
+ "defu": "^6.1.4",
33
+ "es-toolkit": "^1.39.10",
34
+ "vite-plugin-electron": "^0.29.0",
35
+ "vite-plugin-externalize-deps": "^0.9.0"
36
+ },
37
+ "peerDependencies": {
38
+ "@witchcraft/ui": "^0.3.7",
39
+ "unplugin-icons": "^22.3.0"
40
+ },
41
+ "peerDependenciesMeta": {
42
+ "unplugin-icons": {
43
+ "optional": true
44
+ },
45
+ "@witchcraft/ui": {
46
+ "optional": true
47
+ }
48
+ },
49
+ "devDependencies": {
50
+ "@alanscodelog/eslint-config": "^6.3.1",
51
+ "@alanscodelog/semantic-release-config": "^6.0.0",
52
+ "@alanscodelog/tsconfigs": "^6.2.0",
53
+ "@nuxt/eslint-config": "^1.9.0",
54
+ "@nuxt/module-builder": "^1.0.2",
55
+ "@nuxt/schema": "^4.0.3",
56
+ "@nuxt/test-utils": "^3.19.2",
57
+ "@types/node": "latest",
58
+ "changelogen": "^0.6.2",
59
+ "electron": "^38.0.0",
60
+ "eslint": "^9.34.0",
61
+ "husky": "^9.1.7",
62
+ "json5": "^2.2.3",
63
+ "nuxt": "^4.0.3",
64
+ "typescript": "^5.8.3",
65
+ "unplugin-icons": "^22.3.0",
66
+ "vitest": "^3.2.4",
67
+ "vue-tsc": "^3.0.6"
68
+ },
69
+ "release": {
70
+ "extends": [
71
+ "@alanscodelog/semantic-release-config"
72
+ ]
73
+ },
74
+ "commitlint": {
75
+ "extends": [
76
+ "@alanscodelog"
77
+ ]
78
+ },
79
+ "publishConfig": {
80
+ "access": "public"
81
+ },
82
+ "scripts": {
83
+ "build": "nuxt-module-build prepare && nuxt-module-build build && nuxi build playground",
84
+ "build:only": "nuxt-module-build build",
85
+ "dev": "nuxi dev playground",
86
+ "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
87
+ "lint": "eslint \"{src,test,playground/app}/**/*.{ts,vue}\" \"*.{js,cjs,mjs,ts}\"",
88
+ "lint:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
89
+ "test": "vitest run",
90
+ "test:watch": "vitest watch"
91
+ }
92
+ }
package/dist/module.d.cts DELETED
@@ -1,2 +0,0 @@
1
- export * from "/home/runner/work/nuxt-electron/nuxt-electron/src/module.js";
2
- export { default } from "/home/runner/work/nuxt-electron/nuxt-electron/src/module.js";