projax 3.3.40 → 3.3.41
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/api/database.d.ts +12 -1
- package/dist/api/database.d.ts.map +1 -1
- package/dist/api/database.js +139 -1
- package/dist/api/database.js.map +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +8 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/routes/backup.d.ts +3 -0
- package/dist/api/routes/backup.d.ts.map +1 -0
- package/dist/api/routes/backup.js +51 -0
- package/dist/api/routes/backup.js.map +1 -0
- package/dist/api/routes/index.d.ts.map +1 -1
- package/dist/api/routes/index.js +4 -0
- package/dist/api/routes/index.js.map +1 -1
- package/dist/api/routes/mcp.d.ts +3 -0
- package/dist/api/routes/mcp.d.ts.map +1 -0
- package/dist/api/routes/mcp.js +147 -0
- package/dist/api/routes/mcp.js.map +1 -0
- package/dist/api/routes/projects.d.ts.map +1 -1
- package/dist/api/routes/projects.js +20 -0
- package/dist/api/routes/projects.js.map +1 -1
- package/dist/api/routes/settings.d.ts.map +1 -1
- package/dist/api/routes/settings.js +64 -11
- package/dist/api/routes/settings.js.map +1 -1
- package/dist/api/routes/workspaces.d.ts +3 -0
- package/dist/api/routes/workspaces.d.ts.map +1 -0
- package/dist/api/routes/workspaces.js +429 -0
- package/dist/api/routes/workspaces.js.map +1 -0
- package/dist/api/types.d.ts +26 -0
- package/dist/api/types.d.ts.map +1 -1
- package/dist/core/backup-utils.d.ts +17 -0
- package/dist/core/backup-utils.js +166 -0
- package/dist/core/database.d.ts +1 -0
- package/dist/core/git-utils.d.ts +12 -0
- package/dist/core/git-utils.js +96 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +3 -0
- package/dist/core/workspace-utils.d.ts +37 -0
- package/dist/core/workspace-utils.js +152 -0
- package/dist/electron/core/backup-utils.d.ts +17 -0
- package/dist/electron/core/backup-utils.js +166 -0
- package/dist/electron/core/database.d.ts +1 -0
- package/dist/electron/core/git-utils.d.ts +12 -0
- package/dist/electron/core/git-utils.js +96 -0
- package/dist/electron/core/index.d.ts +3 -0
- package/dist/electron/core/index.js +3 -0
- package/dist/electron/core/workspace-utils.d.ts +37 -0
- package/dist/electron/core/workspace-utils.js +152 -0
- package/dist/electron/main.js +324 -9
- package/dist/electron/preload.d.ts +14 -0
- package/dist/electron/preload.js +9 -0
- package/dist/electron/renderer/assets/index-B-etDnj2.js +64 -0
- package/dist/electron/renderer/assets/index-Bx18Cyic.js +64 -0
- package/dist/electron/renderer/assets/index-C8f5yNYe.js +64 -0
- package/dist/electron/renderer/assets/index-CIZ3Wl6c.css +1 -0
- package/dist/electron/renderer/assets/index-CJbsU9y8.css +1 -0
- package/dist/electron/renderer/assets/index-CWxXs5M7.css +1 -0
- package/dist/electron/renderer/assets/index-CopVNRnR.js +64 -0
- package/dist/electron/renderer/assets/index-CtXtIMer.js +64 -0
- package/dist/electron/renderer/assets/index-DUvcepWm.js +64 -0
- package/dist/electron/renderer/assets/index-DWe2TQFv.css +1 -0
- package/dist/electron/renderer/assets/index-DZzB20Xf.css +1 -0
- package/dist/electron/renderer/assets/index-DknLdADV.js +63 -0
- package/dist/electron/renderer/assets/index-DocuD8Lk.js +64 -0
- package/dist/electron/renderer/assets/index-DyU-xfd8.css +1 -0
- package/dist/electron/renderer/assets/index-GwC-JVUy.css +1 -0
- package/dist/electron/renderer/assets/index-fehviker.js +63 -0
- package/dist/electron/renderer/index.html +2 -2
- package/dist/index.js +281 -4
- package/package.json +1 -1
package/dist/electron/main.js
CHANGED
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
const electron_1 = require("electron");
|
|
37
37
|
const path = __importStar(require("path"));
|
|
38
38
|
const fs = __importStar(require("fs"));
|
|
39
|
+
const http = __importStar(require("http"));
|
|
39
40
|
const child_process_1 = require("child_process");
|
|
40
41
|
const tail_1 = require("tail");
|
|
41
42
|
const core_1 = require("./core");
|
|
@@ -73,12 +74,47 @@ else {
|
|
|
73
74
|
preload: path.join(__dirname, 'preload.js'),
|
|
74
75
|
nodeIntegration: false,
|
|
75
76
|
contextIsolation: true,
|
|
77
|
+
webSecurity: true,
|
|
76
78
|
},
|
|
79
|
+
show: false, // Don't show until ready
|
|
80
|
+
});
|
|
81
|
+
// Show window when ready to prevent white screen flash
|
|
82
|
+
mainWindow.once('ready-to-show', () => {
|
|
83
|
+
mainWindow?.show();
|
|
77
84
|
});
|
|
78
85
|
// Load the app
|
|
79
86
|
if (isDev) {
|
|
80
|
-
|
|
81
|
-
|
|
87
|
+
// Wait for Vite dev server to be ready before loading
|
|
88
|
+
const checkServerAndLoad = (retries = 10) => {
|
|
89
|
+
const req = http.get('http://localhost:7898', (res) => {
|
|
90
|
+
console.log('Vite dev server is ready!');
|
|
91
|
+
mainWindow?.loadURL('http://localhost:7898');
|
|
92
|
+
mainWindow?.webContents.openDevTools();
|
|
93
|
+
});
|
|
94
|
+
req.on('error', (error) => {
|
|
95
|
+
if (retries > 0) {
|
|
96
|
+
console.log(`Vite dev server not ready (${retries} retries left), retrying in 1 second...`);
|
|
97
|
+
setTimeout(() => checkServerAndLoad(retries - 1), 1000);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
console.error('Failed to connect to Vite dev server after multiple retries');
|
|
101
|
+
console.error('Make sure Vite is running on port 7898');
|
|
102
|
+
mainWindow?.loadURL('http://localhost:7898'); // Try anyway
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
req.setTimeout(2000, () => {
|
|
106
|
+
req.destroy();
|
|
107
|
+
if (retries > 0) {
|
|
108
|
+
console.log(`Vite dev server timeout (${retries} retries left), retrying...`);
|
|
109
|
+
setTimeout(() => checkServerAndLoad(retries - 1), 1000);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
console.error('Failed to connect to Vite dev server - timeout');
|
|
113
|
+
mainWindow?.loadURL('http://localhost:7898'); // Try anyway
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
};
|
|
117
|
+
checkServerAndLoad();
|
|
82
118
|
}
|
|
83
119
|
else {
|
|
84
120
|
// Try bundled renderer path first (when bundled in CLI: dist/electron/renderer/index.html)
|
|
@@ -113,6 +149,49 @@ else {
|
|
|
113
149
|
mainWindow.on('closed', () => {
|
|
114
150
|
mainWindow = null;
|
|
115
151
|
});
|
|
152
|
+
// Handle page load errors
|
|
153
|
+
mainWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription, validatedURL) => {
|
|
154
|
+
console.error('Failed to load:', validatedURL, errorCode, errorDescription);
|
|
155
|
+
if (isDev && validatedURL === 'http://localhost:7898/') {
|
|
156
|
+
console.log('Retrying to load Vite dev server...');
|
|
157
|
+
setTimeout(() => {
|
|
158
|
+
mainWindow?.loadURL('http://localhost:7898');
|
|
159
|
+
}, 2000);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
// Log when page finishes loading
|
|
163
|
+
mainWindow.webContents.on('did-finish-load', () => {
|
|
164
|
+
console.log('Page loaded successfully');
|
|
165
|
+
});
|
|
166
|
+
// Log console messages from renderer
|
|
167
|
+
mainWindow.webContents.on('console-message', (event, level, message, line, sourceId) => {
|
|
168
|
+
console.log(`[Renderer ${level}]:`, message, sourceId ? `(${sourceId}:${line})` : '');
|
|
169
|
+
});
|
|
170
|
+
// Log all console output from renderer
|
|
171
|
+
mainWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription, validatedURL, isMainFrame) => {
|
|
172
|
+
if (isMainFrame) {
|
|
173
|
+
console.error('Main frame failed to load:', {
|
|
174
|
+
errorCode,
|
|
175
|
+
errorDescription,
|
|
176
|
+
validatedURL,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
// Add keyboard shortcut to reload in dev mode
|
|
181
|
+
if (isDev) {
|
|
182
|
+
mainWindow.webContents.on('before-input-event', (event, input) => {
|
|
183
|
+
// Cmd+R or Ctrl+R to reload
|
|
184
|
+
if ((input.control || input.meta) && input.key.toLowerCase() === 'r') {
|
|
185
|
+
event.preventDefault();
|
|
186
|
+
mainWindow?.reload();
|
|
187
|
+
}
|
|
188
|
+
// Cmd+Shift+R or Ctrl+Shift+R to hard reload
|
|
189
|
+
if ((input.control || input.meta) && input.shift && input.key.toLowerCase() === 'r') {
|
|
190
|
+
event.preventDefault();
|
|
191
|
+
mainWindow?.webContents.reloadIgnoringCache();
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}
|
|
116
195
|
}
|
|
117
196
|
// Start API server
|
|
118
197
|
function startAPIServer() {
|
|
@@ -134,11 +213,18 @@ else {
|
|
|
134
213
|
console.warn('API server not found. Some features may not work.');
|
|
135
214
|
return;
|
|
136
215
|
}
|
|
137
|
-
console.log('Starting API server
|
|
216
|
+
console.log('Starting API server from:', apiPath);
|
|
217
|
+
// Kill any existing API server on the same port first
|
|
218
|
+
if (apiProcess) {
|
|
219
|
+
console.log('Killing existing API server...');
|
|
220
|
+
apiProcess.kill();
|
|
221
|
+
apiProcess = null;
|
|
222
|
+
}
|
|
138
223
|
apiProcess = (0, child_process_1.spawn)('node', [apiPath], {
|
|
139
224
|
detached: false,
|
|
140
225
|
stdio: 'pipe',
|
|
141
226
|
env: { ...process.env },
|
|
227
|
+
cwd: path.dirname(apiPath),
|
|
142
228
|
});
|
|
143
229
|
apiProcess.stdout?.on('data', (data) => {
|
|
144
230
|
console.log(`[API] ${data.toString().trim()}`);
|
|
@@ -149,6 +235,13 @@ else {
|
|
|
149
235
|
apiProcess.on('exit', (code) => {
|
|
150
236
|
console.log(`API server exited with code ${code}`);
|
|
151
237
|
apiProcess = null;
|
|
238
|
+
// Restart API server if it crashes (wait 2 seconds)
|
|
239
|
+
if (code !== 0) {
|
|
240
|
+
console.log('API server crashed, restarting in 2 seconds...');
|
|
241
|
+
setTimeout(() => {
|
|
242
|
+
startAPIServer();
|
|
243
|
+
}, 2000);
|
|
244
|
+
}
|
|
152
245
|
});
|
|
153
246
|
}
|
|
154
247
|
catch (error) {
|
|
@@ -540,8 +633,8 @@ electron_1.ipcMain.handle('open-url', async (_, url) => {
|
|
|
540
633
|
electron_1.ipcMain.handle('open-in-editor', async (_, projectPath) => {
|
|
541
634
|
// Try bundled path first (when bundled in CLI: dist/electron/main.js -> dist/core/settings)
|
|
542
635
|
// Then try local dev path (packages/desktop/dist/main.js -> packages/core/dist/settings)
|
|
543
|
-
const bundledSettingsPath = path.join(__dirname, '
|
|
544
|
-
const localSettingsPath = path.join(__dirname, '..', '..', '
|
|
636
|
+
const bundledSettingsPath = path.join(__dirname, 'core', 'settings');
|
|
637
|
+
const localSettingsPath = path.join(__dirname, '..', '..', 'core', 'dist', 'settings');
|
|
545
638
|
let settingsPath;
|
|
546
639
|
if (fs.existsSync(bundledSettingsPath + '.js')) {
|
|
547
640
|
settingsPath = bundledSettingsPath;
|
|
@@ -580,6 +673,96 @@ electron_1.ipcMain.handle('open-in-editor', async (_, projectPath) => {
|
|
|
580
673
|
stdio: 'ignore',
|
|
581
674
|
}).unref();
|
|
582
675
|
});
|
|
676
|
+
// Open workspace in editor
|
|
677
|
+
electron_1.ipcMain.handle('open-workspace', async (_, workspaceId) => {
|
|
678
|
+
try {
|
|
679
|
+
// Get workspace file path from API (ensures file exists)
|
|
680
|
+
const ports = [38124, 38125, 38126, 38127, 38128, 3001];
|
|
681
|
+
let apiBaseUrl = '';
|
|
682
|
+
for (const port of ports) {
|
|
683
|
+
try {
|
|
684
|
+
const response = await fetch(`http://localhost:${port}/health`, { signal: AbortSignal.timeout(500) });
|
|
685
|
+
if (response.ok) {
|
|
686
|
+
apiBaseUrl = `http://localhost:${port}/api`;
|
|
687
|
+
break;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
catch {
|
|
691
|
+
continue;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
if (!apiBaseUrl) {
|
|
695
|
+
throw new Error('API server not found');
|
|
696
|
+
}
|
|
697
|
+
// Get workspace file path (this will generate it if needed)
|
|
698
|
+
const response = await fetch(`${apiBaseUrl}/workspaces/${workspaceId}/file-path`);
|
|
699
|
+
if (!response.ok) {
|
|
700
|
+
throw new Error('Failed to get workspace file path');
|
|
701
|
+
}
|
|
702
|
+
const data = await response.json();
|
|
703
|
+
const workspace_file_path = data.workspace_file_path;
|
|
704
|
+
if (!fs.existsSync(workspace_file_path)) {
|
|
705
|
+
throw new Error('Workspace file does not exist');
|
|
706
|
+
}
|
|
707
|
+
// Open workspace file in editor (workspace files are opened with the workspace flag)
|
|
708
|
+
const bundledSettingsPath = path.join(__dirname, 'core', 'settings');
|
|
709
|
+
const localSettingsPath = path.join(__dirname, '..', '..', 'core', 'dist', 'settings');
|
|
710
|
+
let settingsPath;
|
|
711
|
+
if (fs.existsSync(bundledSettingsPath + '.js')) {
|
|
712
|
+
settingsPath = bundledSettingsPath;
|
|
713
|
+
}
|
|
714
|
+
else {
|
|
715
|
+
settingsPath = localSettingsPath;
|
|
716
|
+
}
|
|
717
|
+
const { getEditorSettings } = require(settingsPath);
|
|
718
|
+
const editorSettings = getEditorSettings();
|
|
719
|
+
let command;
|
|
720
|
+
let args = [];
|
|
721
|
+
if (editorSettings.type === 'custom' && editorSettings.customPath) {
|
|
722
|
+
command = editorSettings.customPath;
|
|
723
|
+
// For custom editors, try workspace file as argument
|
|
724
|
+
args = [workspace_file_path];
|
|
725
|
+
}
|
|
726
|
+
else {
|
|
727
|
+
switch (editorSettings.type) {
|
|
728
|
+
case 'vscode':
|
|
729
|
+
case 'cursor':
|
|
730
|
+
case 'windsurf':
|
|
731
|
+
// VS Code, Cursor, and Windsurf support opening workspace files directly
|
|
732
|
+
command = editorSettings.type === 'vscode' ? 'code' : editorSettings.type === 'cursor' ? 'cursor' : 'windsurf';
|
|
733
|
+
args = [workspace_file_path];
|
|
734
|
+
break;
|
|
735
|
+
case 'zed':
|
|
736
|
+
// Zed doesn't support workspace files, open the first project folder instead
|
|
737
|
+
const workspaceContent = JSON.parse(fs.readFileSync(workspace_file_path, 'utf-8'));
|
|
738
|
+
if (workspaceContent.folders && workspaceContent.folders.length > 0) {
|
|
739
|
+
const firstFolder = workspaceContent.folders[0];
|
|
740
|
+
const folderPath = path.isAbsolute(firstFolder.path)
|
|
741
|
+
? firstFolder.path
|
|
742
|
+
: path.resolve(path.dirname(workspace_file_path), firstFolder.path);
|
|
743
|
+
command = 'zed';
|
|
744
|
+
args = [folderPath];
|
|
745
|
+
}
|
|
746
|
+
else {
|
|
747
|
+
throw new Error('Workspace has no folders to open');
|
|
748
|
+
}
|
|
749
|
+
break;
|
|
750
|
+
default:
|
|
751
|
+
command = 'code';
|
|
752
|
+
args = [workspace_file_path];
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
const { spawn } = require('child_process');
|
|
756
|
+
spawn(command, args, {
|
|
757
|
+
detached: true,
|
|
758
|
+
stdio: 'ignore',
|
|
759
|
+
}).unref();
|
|
760
|
+
}
|
|
761
|
+
catch (error) {
|
|
762
|
+
console.error('Error opening workspace:', error);
|
|
763
|
+
throw error;
|
|
764
|
+
}
|
|
765
|
+
});
|
|
583
766
|
// Open project directory in file manager
|
|
584
767
|
electron_1.ipcMain.handle('open-in-files', async (_, projectPath) => {
|
|
585
768
|
try {
|
|
@@ -594,8 +777,8 @@ electron_1.ipcMain.handle('open-in-files', async (_, projectPath) => {
|
|
|
594
777
|
electron_1.ipcMain.handle('get-settings', async () => {
|
|
595
778
|
try {
|
|
596
779
|
// Load settings module directly
|
|
597
|
-
const bundledSettingsPath = path.join(__dirname, '
|
|
598
|
-
const localSettingsPath = path.join(__dirname, '..', '..', '
|
|
780
|
+
const bundledSettingsPath = path.join(__dirname, 'core', 'settings');
|
|
781
|
+
const localSettingsPath = path.join(__dirname, '..', '..', 'core', 'dist', 'settings');
|
|
599
782
|
let settingsPath;
|
|
600
783
|
if (fs.existsSync(bundledSettingsPath + '.js')) {
|
|
601
784
|
settingsPath = bundledSettingsPath;
|
|
@@ -615,8 +798,8 @@ electron_1.ipcMain.handle('get-settings', async () => {
|
|
|
615
798
|
electron_1.ipcMain.handle('save-settings', async (_, settings) => {
|
|
616
799
|
try {
|
|
617
800
|
// Load settings module directly
|
|
618
|
-
const bundledSettingsPath = path.join(__dirname, '
|
|
619
|
-
const localSettingsPath = path.join(__dirname, '..', '..', '
|
|
801
|
+
const bundledSettingsPath = path.join(__dirname, 'core', 'settings');
|
|
802
|
+
const localSettingsPath = path.join(__dirname, '..', '..', 'core', 'dist', 'settings');
|
|
620
803
|
let settingsPath;
|
|
621
804
|
if (fs.existsSync(bundledSettingsPath + '.js')) {
|
|
622
805
|
settingsPath = bundledSettingsPath;
|
|
@@ -722,3 +905,135 @@ electron_1.ipcMain.handle('unwatch-process-output', async (_, pid) => {
|
|
|
722
905
|
}
|
|
723
906
|
return { success: false };
|
|
724
907
|
});
|
|
908
|
+
// Workspace handlers
|
|
909
|
+
electron_1.ipcMain.handle('get-workspaces', async () => {
|
|
910
|
+
try {
|
|
911
|
+
const response = await fetch('http://localhost:3001/api/workspaces');
|
|
912
|
+
if (!response.ok)
|
|
913
|
+
throw new Error('Failed to fetch workspaces');
|
|
914
|
+
return await response.json();
|
|
915
|
+
}
|
|
916
|
+
catch (error) {
|
|
917
|
+
console.error('Error getting workspaces:', error);
|
|
918
|
+
throw error;
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
electron_1.ipcMain.handle('add-workspace', async (_, workspace) => {
|
|
922
|
+
try {
|
|
923
|
+
const response = await fetch('http://localhost:3001/api/workspaces', {
|
|
924
|
+
method: 'POST',
|
|
925
|
+
headers: { 'Content-Type': 'application/json' },
|
|
926
|
+
body: JSON.stringify(workspace),
|
|
927
|
+
});
|
|
928
|
+
if (!response.ok) {
|
|
929
|
+
const errorData = await response.json();
|
|
930
|
+
throw new Error(errorData.error || 'Failed to add workspace');
|
|
931
|
+
}
|
|
932
|
+
return await response.json();
|
|
933
|
+
}
|
|
934
|
+
catch (error) {
|
|
935
|
+
console.error('Error adding workspace:', error);
|
|
936
|
+
throw error;
|
|
937
|
+
}
|
|
938
|
+
});
|
|
939
|
+
electron_1.ipcMain.handle('remove-workspace', async (_, workspaceId) => {
|
|
940
|
+
try {
|
|
941
|
+
const response = await fetch(`http://localhost:3001/api/workspaces/${workspaceId}`, {
|
|
942
|
+
method: 'DELETE',
|
|
943
|
+
});
|
|
944
|
+
if (!response.ok)
|
|
945
|
+
throw new Error('Failed to remove workspace');
|
|
946
|
+
}
|
|
947
|
+
catch (error) {
|
|
948
|
+
console.error('Error removing workspace:', error);
|
|
949
|
+
throw error;
|
|
950
|
+
}
|
|
951
|
+
});
|
|
952
|
+
// Backup handlers
|
|
953
|
+
electron_1.ipcMain.handle('create-backup', async (_, outputPath) => {
|
|
954
|
+
try {
|
|
955
|
+
// Try to load from dist first, then src
|
|
956
|
+
const backupUtilsPath = path.join(__dirname, '..', '..', 'core', 'dist', 'backup-utils.js');
|
|
957
|
+
const backupUtilsSrcPath = path.join(__dirname, '..', '..', 'core', 'src', 'backup-utils.ts');
|
|
958
|
+
let backupUtils;
|
|
959
|
+
if (fs.existsSync(backupUtilsPath)) {
|
|
960
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
961
|
+
backupUtils = require(backupUtilsPath);
|
|
962
|
+
}
|
|
963
|
+
else if (fs.existsSync(backupUtilsSrcPath.replace('.ts', '.js'))) {
|
|
964
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
965
|
+
backupUtils = require(backupUtilsSrcPath.replace('.ts', '.js'));
|
|
966
|
+
}
|
|
967
|
+
else {
|
|
968
|
+
throw new Error('Backup utils not found');
|
|
969
|
+
}
|
|
970
|
+
const { createBackup } = backupUtils;
|
|
971
|
+
const backupPath = await createBackup(outputPath);
|
|
972
|
+
return { success: true, backup_path: backupPath };
|
|
973
|
+
}
|
|
974
|
+
catch (error) {
|
|
975
|
+
console.error('Error creating backup:', error);
|
|
976
|
+
throw error;
|
|
977
|
+
}
|
|
978
|
+
});
|
|
979
|
+
electron_1.ipcMain.handle('restore-backup', async (_, backupPath) => {
|
|
980
|
+
try {
|
|
981
|
+
// Try to load from dist first, then src
|
|
982
|
+
const backupUtilsPath = path.join(__dirname, '..', '..', 'core', 'dist', 'backup-utils.js');
|
|
983
|
+
const backupUtilsSrcPath = path.join(__dirname, '..', '..', 'core', 'src', 'backup-utils.ts');
|
|
984
|
+
let backupUtils;
|
|
985
|
+
if (fs.existsSync(backupUtilsPath)) {
|
|
986
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
987
|
+
backupUtils = require(backupUtilsPath);
|
|
988
|
+
}
|
|
989
|
+
else if (fs.existsSync(backupUtilsSrcPath.replace('.ts', '.js'))) {
|
|
990
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
991
|
+
backupUtils = require(backupUtilsSrcPath.replace('.ts', '.js'));
|
|
992
|
+
}
|
|
993
|
+
else {
|
|
994
|
+
throw new Error('Backup utils not found');
|
|
995
|
+
}
|
|
996
|
+
const { restoreBackup } = backupUtils;
|
|
997
|
+
await restoreBackup(backupPath);
|
|
998
|
+
return { success: true };
|
|
999
|
+
}
|
|
1000
|
+
catch (error) {
|
|
1001
|
+
console.error('Error restoring backup:', error);
|
|
1002
|
+
throw error;
|
|
1003
|
+
}
|
|
1004
|
+
});
|
|
1005
|
+
// File dialog handlers
|
|
1006
|
+
electron_1.ipcMain.handle('show-save-dialog', async (_, options) => {
|
|
1007
|
+
if (!mainWindow)
|
|
1008
|
+
return { canceled: true };
|
|
1009
|
+
const result = await electron_1.dialog.showSaveDialog(mainWindow, {
|
|
1010
|
+
title: options.title || 'Save File',
|
|
1011
|
+
defaultPath: options.defaultPath,
|
|
1012
|
+
filters: options.filters || [{ name: 'All Files', extensions: ['*'] }],
|
|
1013
|
+
});
|
|
1014
|
+
return result;
|
|
1015
|
+
});
|
|
1016
|
+
electron_1.ipcMain.handle('show-open-dialog', async (_, options) => {
|
|
1017
|
+
if (!mainWindow)
|
|
1018
|
+
return { canceled: true };
|
|
1019
|
+
const result = await electron_1.dialog.showOpenDialog(mainWindow, {
|
|
1020
|
+
title: options.title || 'Open File',
|
|
1021
|
+
defaultPath: options.defaultPath,
|
|
1022
|
+
filters: options.filters || [{ name: 'All Files', extensions: ['*'] }],
|
|
1023
|
+
properties: options.properties || ['openFile'],
|
|
1024
|
+
});
|
|
1025
|
+
return result;
|
|
1026
|
+
});
|
|
1027
|
+
electron_1.ipcMain.handle('select-file', async (_, options) => {
|
|
1028
|
+
if (!mainWindow)
|
|
1029
|
+
return null;
|
|
1030
|
+
const result = await electron_1.dialog.showOpenDialog(mainWindow, {
|
|
1031
|
+
title: options.title || 'Select File',
|
|
1032
|
+
defaultPath: options.defaultPath,
|
|
1033
|
+
filters: options.filters || [{ name: 'All Files', extensions: ['*'] }],
|
|
1034
|
+
properties: ['openFile'],
|
|
1035
|
+
});
|
|
1036
|
+
if (result.canceled || result.filePaths.length === 0)
|
|
1037
|
+
return null;
|
|
1038
|
+
return result.filePaths[0];
|
|
1039
|
+
});
|
|
@@ -115,4 +115,18 @@ export interface ElectronAPI {
|
|
|
115
115
|
}) => void) => void;
|
|
116
116
|
getAppVersion: () => Promise<string>;
|
|
117
117
|
getLatestTestResult: (projectId: number) => Promise<any | null>;
|
|
118
|
+
getWorkspaces: () => Promise<any[]>;
|
|
119
|
+
addWorkspace: (workspace: any) => Promise<any>;
|
|
120
|
+
removeWorkspace: (workspaceId: number) => Promise<void>;
|
|
121
|
+
createBackup: (outputPath: string) => Promise<{
|
|
122
|
+
success: boolean;
|
|
123
|
+
backup_path: string;
|
|
124
|
+
}>;
|
|
125
|
+
restoreBackup: (backupPath: string) => Promise<{
|
|
126
|
+
success: boolean;
|
|
127
|
+
}>;
|
|
128
|
+
showSaveDialog: (options: any) => Promise<any>;
|
|
129
|
+
showOpenDialog: (options: any) => Promise<any>;
|
|
130
|
+
selectFile: (options: any) => Promise<string | null>;
|
|
131
|
+
openWorkspace: (workspaceId: number) => Promise<void>;
|
|
118
132
|
}
|
package/dist/electron/preload.js
CHANGED
|
@@ -36,4 +36,13 @@ electron_1.contextBridge.exposeInMainWorld('electronAPI', {
|
|
|
36
36
|
removeProcessExitListener: (callback) => electron_1.ipcRenderer.removeListener('process-exit', callback),
|
|
37
37
|
getAppVersion: () => electron_1.ipcRenderer.invoke('get-app-version'),
|
|
38
38
|
getLatestTestResult: (projectId) => electron_1.ipcRenderer.invoke('get-latest-test-result', projectId),
|
|
39
|
+
getWorkspaces: () => electron_1.ipcRenderer.invoke('get-workspaces'),
|
|
40
|
+
addWorkspace: (workspace) => electron_1.ipcRenderer.invoke('add-workspace', workspace),
|
|
41
|
+
removeWorkspace: (workspaceId) => electron_1.ipcRenderer.invoke('remove-workspace', workspaceId),
|
|
42
|
+
createBackup: (outputPath) => electron_1.ipcRenderer.invoke('create-backup', outputPath),
|
|
43
|
+
restoreBackup: (backupPath) => electron_1.ipcRenderer.invoke('restore-backup', backupPath),
|
|
44
|
+
showSaveDialog: (options) => electron_1.ipcRenderer.invoke('show-save-dialog', options),
|
|
45
|
+
showOpenDialog: (options) => electron_1.ipcRenderer.invoke('show-open-dialog', options),
|
|
46
|
+
selectFile: (options) => electron_1.ipcRenderer.invoke('select-file', options),
|
|
47
|
+
openWorkspace: (workspaceId) => electron_1.ipcRenderer.invoke('open-workspace', workspaceId),
|
|
39
48
|
});
|