Skip to content

Commit eee4fe1

Browse files
[feat 🍿] fixed bridge issue for api calling 🖥
1 parent 2d3f6ec commit eee4fe1

File tree

18 files changed

+154
-92
lines changed

18 files changed

+154
-92
lines changed

changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,5 @@
3434
- [feat] ShadcnUI added to our desktop application
3535
- [feat] Monaco editor setup with electron js
3636
- [feat] Code highlight & inte. is supported
37+
- [fix] electron main process api calling issues
38+
- [feat] api calling bridge for secure our application

desktop/electron.vite.config.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,29 @@ import tailwindcss from "@tailwindcss/vite";
66

77
export default defineConfig({
88
main: {
9-
plugins: [externalizeDepsPlugin()]
9+
plugins: [externalizeDepsPlugin()],
10+
resolve: {
11+
alias: {
12+
"@/lib": resolve("src/main/lib"),
13+
"@shared": resolve("src/shared")
14+
}
15+
}
1016
},
1117
preload: {
1218
plugins: [externalizeDepsPlugin()]
1319
},
1420
renderer: {
1521
resolve: {
1622
alias: {
17-
"@renderer": resolve("src/renderer/src")
23+
"@renderer": resolve("src/renderer/src"),
24+
"@shared": resolve("src/shared"),
25+
"@/hooks": resolve("src/renderer/src/hooks"),
26+
"@/assets": resolve("src/renderer/src/assets"),
27+
"@/store": resolve("src/renderer/src/store"),
28+
"@/components": resolve("src/renderer/src/components"),
29+
"@/mocks": resolve("src/renderer/src/mocks"),
30+
"@/lib": resolve("src/renderer/src/lib"),
31+
"@/types": resolve("src/renderer/src/@types")
1832
}
1933
},
2034
plugins: [react(), tailwindcss()]

desktop/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"axios": "^1.10.0",
3535
"class-variance-authority": "^0.7.1",
3636
"clsx": "^2.1.1",
37+
"dotenv": "^17.0.1",
3738
"electron-updater": "^6.3.9",
3839
"lucide-react": "^0.525.0",
3940
"monaco-editor": "^0.52.2",

desktop/pnpm-lock.yaml

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

desktop/src/main/index.ts

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import { join } from "path";
33
import { electronApp, optimizer, is } from "@electron-toolkit/utils";
44
import icon from "../../resources/icon.png?asset";
55
import { existsSync, readFileSync } from "fs";
6+
import dotenv from "dotenv";
7+
import { handleExecuteCode } from "./lib/execute-code";
8+
dotenv.config();
69

710
function createWindow(): void {
811
// Create the browser window.
@@ -34,8 +37,6 @@ function createWindow(): void {
3437
return { action: "deny" };
3538
});
3639

37-
// HMR for renderer base on electron-vite cli.
38-
// Load the remote URL for development or the local html file for production.
3940
if (is.dev && process.env["ELECTRON_RENDERER_URL"]) {
4041
mainWindow.webContents.openDevTools();
4142
mainWindow.loadURL(process.env["ELECTRON_RENDERER_URL"]);
@@ -44,51 +45,33 @@ function createWindow(): void {
4445
}
4546
}
4647

47-
// This method will be called when Electron has finished
48-
// initialization and is ready to create browser windows.
49-
// Some APIs can only be used after this event occurs.
5048
app.whenReady().then(() => {
5149
is.dev && app.commandLine.appendSwitch("ignore-certificate-errors");
52-
5350
// Register the custom protocol to serve Monaco Editor worker files locally
51+
ipcMain.handle("executecode:post", handleExecuteCode);
5452
protocol.handle("monaco-editor", (request) => {
5553
const url = request.url.substr("monaco-editor://".length);
5654

5755
let monacoBasePath;
5856
if (is.dev) {
59-
// Adjust this path based on your dev setup relative to dist-electron/main/index.js
6057
monacoBasePath = join(__dirname, "../../node_modules/monaco-editor/min");
6158
} else {
62-
// Adjust this path based on where 'monaco-editor/min' is copied in your packaged app.
63-
// Common paths:
64-
// If monaco-editor/min is copied to the root of your packaged app:
6559
monacoBasePath = join(app.getAppPath(), "node_modules/monaco-editor/min");
66-
// If it's copied to a specific asset folder like 'assets/monaco':
67-
// monacoBasePath = join(app.getAppPath(), 'assets', 'monaco');
6860
}
69-
7061
const filePath = join(monacoBasePath, url);
71-
console.log("Serving monaco-editor:// file:", filePath); // Keep this for debugging!
72-
7362
if (existsSync(filePath)) {
7463
return new Response(readFileSync(filePath));
7564
} else {
7665
console.error("Monaco Editor file not found:", filePath);
77-
// It's crucial to return a proper 404 or an empty response for missing files.
78-
// Returning a null or undefined can cause issues.
7966
return new Response("File not found", { status: 404 });
8067
}
8168
});
82-
// Set app user model id for windows
83-
electronApp.setAppUserModelId("com.executeme");
8469

70+
electronApp.setAppUserModelId("com.executeme");
8571
app.on("browser-window-created", (_, window) => {
8672
optimizer.watchWindowShortcuts(window);
8773
});
8874

89-
// IPC test
90-
ipcMain.on("ping", () => console.log("pong"));
91-
9275
createWindow();
9376

9477
app.on("activate", function () {
@@ -101,6 +84,3 @@ app.on("window-all-closed", () => {
10184
app.quit();
10285
}
10386
});
104-
105-
// In this file you can include the rest of your app's specific main process
106-
// code. You can also put them in separate files and require them here.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const handleCodeEditor = (_, payload) => {
2+
console.log(payload);
3+
};
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { Input } from "@shared/types";
2+
import { IpcMainInvokeEvent } from "electron";
3+
import https from "https";
4+
import axios from "axios";
5+
import { is } from "@electron-toolkit/utils";
6+
7+
export const handleExecuteCode = async (_: IpcMainInvokeEvent, payload: Input) => {
8+
const agent = new https.Agent({
9+
rejectUnauthorized: false
10+
});
11+
const axiosInstance = axios.create({
12+
httpsAgent: agent
13+
});
14+
const baseAPI = is.dev
15+
? process.env.RENDERER_VITE_SERVER_BASE_URL
16+
: process.env.RENDERER_VITE_SERVER_BASE_URL;
17+
const start = performance.now();
18+
try {
19+
const { data } = await axiosInstance.post(`${baseAPI}/run`, payload);
20+
const end = performance.now();
21+
return {
22+
output: data.output,
23+
responseTime: Math.round(end - start)
24+
};
25+
} catch (error: any) {
26+
const end = performance.now();
27+
28+
const output = error?.response?.data?.details || error?.message || "Unknown error occurred";
29+
30+
return {
31+
output,
32+
responseTime: Math.round(end - start)
33+
};
34+
}
35+
};

desktop/src/preload/index.d.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1-
import { ElectronAPI } from '@electron-toolkit/preload'
1+
// import { electronAPI } from "@electron-toolkit/preload";
2+
import { Input, Output } from "@shared/types";
3+
4+
export interface ApplicationInterface {
5+
// electron: typeof electronAPI;
6+
7+
api: {
8+
getMonacoBasePath: () => string;
9+
executeCode: (payload: Input) => Promise<Output>;
10+
};
11+
}
212

313
declare global {
414
interface Window {
5-
electron: ElectronAPI
6-
api: unknown
15+
applicationApi: ApplicationInterface;
716
}
817
}

desktop/src/preload/index.ts

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,23 @@
11
import { contextBridge, ipcRenderer } from "electron";
2+
// import { electronAPI } from "@electron-toolkit/preload";
3+
import { Input } from "@shared/types";
4+
import { ApplicationInterface } from "./preload";
25

3-
// Expose a function to the renderer to get Monaco's base path
4-
// This is crucial for @monaco-editor/react to know where to load its *main* scripts from
5-
contextBridge.exposeInMainWorld("monacoConfig", {
6-
getMonacoBasePath: () => {
7-
// This is correct. The renderer will ask for 'monaco-editor://vs'
8-
// and your main process protocol handler will resolve it to the local path.
9-
return `monaco-editor://vs`;
6+
const applicationApi: ApplicationInterface = {
7+
// electron: electronAPI,
8+
9+
api: {
10+
getMonacoBasePath: () => "monaco-editor://vs",
11+
executeCode: (payload: Input) => ipcRenderer.invoke("executecode:post", payload)
1012
}
11-
});
13+
};
1214

1315
if (process.contextIsolated) {
1416
try {
15-
contextBridge.exposeInMainWorld("electron", {
16-
ipcRenderer: {
17-
send: (channel: string, args?: any[]) => ipcRenderer.send(channel, args),
18-
on: (channel: string, listener: (...args: any[]) => void) => {
19-
ipcRenderer.on(channel, listener);
20-
return () => ipcRenderer.removeListener(channel, listener);
21-
}
22-
}
23-
});
17+
contextBridge.exposeInMainWorld("applicationApi", applicationApi);
2418
} catch (error) {
25-
console.error(error);
19+
console.error("Failed to expose API:", error);
2620
}
2721
} else {
28-
// @ts-ignore (define in dts)
29-
window.electron = {
30-
ipcRenderer: {
31-
send: (channel, args) => ipcRenderer.send(channel, args),
32-
on: (channel, listener) => ipcRenderer.on(channel, listener)
33-
}
34-
};
22+
window.applicationApi = applicationApi;
3523
}

desktop/src/preload/preload.d.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// import { electronAPI } from "@electron-toolkit/preload";
2+
import { Input, Output } from "@shared/types";
3+
4+
export interface ApplicationInterface {
5+
// electron: typeof electronAPI;
6+
7+
api: {
8+
getMonacoBasePath: () => string;
9+
executeCode: (payload: Input) => Promise<Output>;
10+
};
11+
}
12+
13+
declare global {
14+
interface Window {
15+
applicationApi: ApplicationInterface;
16+
}
17+
}

0 commit comments

Comments
 (0)