@directivegames/genesys.sdk 3.2.2
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/README.md +60 -0
- package/dist/src/asset-pack/eslint.config.js +43 -0
- package/dist/src/asset-pack/scripts/postinstall.js +64 -0
- package/dist/src/asset-pack/src/index.js +1 -0
- package/dist/src/core/cli.js +306 -0
- package/dist/src/core/common.js +324 -0
- package/dist/src/core/index.js +6 -0
- package/dist/src/core/tools/build-project.js +450 -0
- package/dist/src/core/tools/index.js +2 -0
- package/dist/src/core/tools/new-asset-pack.js +150 -0
- package/dist/src/core/tools/new-project.js +292 -0
- package/dist/src/core/types.js +1 -0
- package/dist/src/dependencies.js +82 -0
- package/dist/src/electron/IpcSerializableError.js +38 -0
- package/dist/src/electron/api.js +7 -0
- package/dist/src/electron/backend/actions.js +56 -0
- package/dist/src/electron/backend/handler.js +441 -0
- package/dist/src/electron/backend/logging.js +41 -0
- package/dist/src/electron/backend/main.js +315 -0
- package/dist/src/electron/backend/menu.js +208 -0
- package/dist/src/electron/backend/state.js +201 -0
- package/dist/src/electron/backend/tools/const.js +9 -0
- package/dist/src/electron/backend/tools/file-server.js +383 -0
- package/dist/src/electron/backend/tools/open-project.js +261 -0
- package/dist/src/electron/backend/window.js +161 -0
- package/dist/src/templates/eslint.config.js +43 -0
- package/dist/src/templates/scripts/genesys/build-project.js +42 -0
- package/dist/src/templates/scripts/genesys/calc-bounding-box.js +205 -0
- package/dist/src/templates/scripts/genesys/common.js +36 -0
- package/dist/src/templates/scripts/genesys/const.js +9 -0
- package/dist/src/templates/scripts/genesys/dev/dump-default-scene.js +8 -0
- package/dist/src/templates/scripts/genesys/dev/generate-manifest.js +116 -0
- package/dist/src/templates/scripts/genesys/dev/launcher.js +39 -0
- package/dist/src/templates/scripts/genesys/dev/storage-provider.js +188 -0
- package/dist/src/templates/scripts/genesys/dev/update-template-scenes.js +67 -0
- package/dist/src/templates/scripts/genesys/doc-server.js +12 -0
- package/dist/src/templates/scripts/genesys/genesys-mcp.js +413 -0
- package/dist/src/templates/scripts/genesys/mcp/doc-tools.js +70 -0
- package/dist/src/templates/scripts/genesys/mcp/editor-functions.js +123 -0
- package/dist/src/templates/scripts/genesys/mcp/editor-tools.js +51 -0
- package/dist/src/templates/scripts/genesys/mcp/get-scene-state.js +26 -0
- package/dist/src/templates/scripts/genesys/mcp/run-subprocess.js +23 -0
- package/dist/src/templates/scripts/genesys/mcp/search-actors.js +703 -0
- package/dist/src/templates/scripts/genesys/mcp/search-assets.js +296 -0
- package/dist/src/templates/scripts/genesys/mcp/utils.js +234 -0
- package/dist/src/templates/scripts/genesys/misc.js +32 -0
- package/dist/src/templates/scripts/genesys/mock.js +5 -0
- package/dist/src/templates/scripts/genesys/place-actors.js +112 -0
- package/dist/src/templates/scripts/genesys/post-install.js +25 -0
- package/dist/src/templates/scripts/genesys/remove-engine-comments.js +113 -0
- package/dist/src/templates/scripts/genesys/storageProvider.js +146 -0
- package/dist/src/templates/scripts/genesys/validate-prefabs.js +115 -0
- package/dist/src/templates/src/index.js +20 -0
- package/dist/src/templates/src/templates/firstPerson/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/firstPerson/src/game.js +30 -0
- package/dist/src/templates/src/templates/firstPerson/src/player.js +60 -0
- package/dist/src/templates/src/templates/fps/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/fps/src/game.js +30 -0
- package/dist/src/templates/src/templates/fps/src/player.js +64 -0
- package/dist/src/templates/src/templates/fps/src/weapon.js +62 -0
- package/dist/src/templates/src/templates/freeCamera/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/freeCamera/src/game.js +30 -0
- package/dist/src/templates/src/templates/freeCamera/src/player.js +43 -0
- package/dist/src/templates/src/templates/sideScroller/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/sideScroller/src/const.js +43 -0
- package/dist/src/templates/src/templates/sideScroller/src/game.js +103 -0
- package/dist/src/templates/src/templates/sideScroller/src/level-generator.js +249 -0
- package/dist/src/templates/src/templates/sideScroller/src/player.js +105 -0
- package/dist/src/templates/src/templates/thirdPerson/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/thirdPerson/src/game.js +30 -0
- package/dist/src/templates/src/templates/thirdPerson/src/player.js +63 -0
- package/dist/src/templates/src/templates/vehicle/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/vehicle/src/base-vehicle.js +122 -0
- package/dist/src/templates/src/templates/vehicle/src/game.js +33 -0
- package/dist/src/templates/src/templates/vehicle/src/mesh-vehicle.js +189 -0
- package/dist/src/templates/src/templates/vehicle/src/player.js +102 -0
- package/dist/src/templates/src/templates/vehicle/src/primitive-vehicle.js +259 -0
- package/dist/src/templates/src/templates/vehicle/src/ui-hints.js +100 -0
- package/dist/src/templates/src/templates/vr-game/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/vr-game/src/game.js +55 -0
- package/dist/src/templates/src/templates/vr-game/src/sample-vr-actor.js +29 -0
- package/dist/src/templates/vite.config.js +46 -0
- package/package.json +176 -0
- package/scripts/post-install.ts +143 -0
- package/src/asset-pack/.gitattributes +89 -0
- package/src/asset-pack/eslint.config.js +45 -0
- package/src/asset-pack/gitignore +11 -0
- package/src/asset-pack/scripts/postinstall.ts +81 -0
- package/src/asset-pack/src/index.ts +0 -0
- package/src/asset-pack/tsconfig.json +34 -0
- package/src/templates/.cursor/mcp.json +20 -0
- package/src/templates/.cursorignore +2 -0
- package/src/templates/.gitattributes +89 -0
- package/src/templates/.vscode/settings.json +6 -0
- package/src/templates/AGENTS.md +86 -0
- package/src/templates/CLAUDE.md +1 -0
- package/src/templates/README.md +24 -0
- package/src/templates/eslint.config.js +45 -0
- package/src/templates/gitignore +11 -0
- package/src/templates/index.html +34 -0
- package/src/templates/pnpm-lock.yaml +3676 -0
- package/src/templates/scripts/genesys/build-project.ts +51 -0
- package/src/templates/scripts/genesys/calc-bounding-box.ts +272 -0
- package/src/templates/scripts/genesys/common.ts +46 -0
- package/src/templates/scripts/genesys/const.ts +9 -0
- package/src/templates/scripts/genesys/dev/dump-default-scene.ts +11 -0
- package/src/templates/scripts/genesys/dev/generate-manifest.ts +146 -0
- package/src/templates/scripts/genesys/dev/launcher.ts +46 -0
- package/src/templates/scripts/genesys/dev/storage-provider.ts +229 -0
- package/src/templates/scripts/genesys/dev/update-template-scenes.ts +84 -0
- package/src/templates/scripts/genesys/doc-server.ts +16 -0
- package/src/templates/scripts/genesys/genesys-mcp.ts +526 -0
- package/src/templates/scripts/genesys/mcp/doc-tools.ts +86 -0
- package/src/templates/scripts/genesys/mcp/editor-functions.ts +151 -0
- package/src/templates/scripts/genesys/mcp/editor-tools.ts +73 -0
- package/src/templates/scripts/genesys/mcp/get-scene-state.ts +35 -0
- package/src/templates/scripts/genesys/mcp/run-subprocess.ts +30 -0
- package/src/templates/scripts/genesys/mcp/search-actors.ts +858 -0
- package/src/templates/scripts/genesys/mcp/search-assets.ts +380 -0
- package/src/templates/scripts/genesys/mcp/utils.ts +281 -0
- package/src/templates/scripts/genesys/misc.ts +42 -0
- package/src/templates/scripts/genesys/mock.ts +6 -0
- package/src/templates/scripts/genesys/place-actors.ts +179 -0
- package/src/templates/scripts/genesys/post-install.ts +30 -0
- package/src/templates/scripts/genesys/prefab.schema.json +85 -0
- package/src/templates/scripts/genesys/remove-engine-comments.ts +135 -0
- package/src/templates/scripts/genesys/run-mcp-inspector.bat +5 -0
- package/src/templates/scripts/genesys/storageProvider.ts +182 -0
- package/src/templates/scripts/genesys/validate-prefabs.ts +138 -0
- package/src/templates/src/index.ts +22 -0
- package/src/templates/src/templates/firstPerson/assets/default.genesys-scene +166 -0
- package/src/templates/src/templates/firstPerson/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/firstPerson/src/game.ts +39 -0
- package/src/templates/src/templates/firstPerson/src/player.ts +63 -0
- package/src/templates/src/templates/fps/assets/default.genesys-scene +9460 -0
- package/src/templates/src/templates/fps/assets/models/SM_Beam_400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_ChamferCube.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Floor_Thick_400x400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Floor_Thick_400x400_Orange.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Floor_Thin_400x400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Floor_Thin_400x400_Orange.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Ramp_400x400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Rifle.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x200.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x200_Orange.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x400_Orange.glb +0 -0
- package/src/templates/src/templates/fps/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/fps/src/game.ts +39 -0
- package/src/templates/src/templates/fps/src/player.ts +69 -0
- package/src/templates/src/templates/fps/src/weapon.ts +54 -0
- package/src/templates/src/templates/freeCamera/assets/default.genesys-scene +166 -0
- package/src/templates/src/templates/freeCamera/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/freeCamera/src/game.ts +39 -0
- package/src/templates/src/templates/freeCamera/src/player.ts +45 -0
- package/src/templates/src/templates/sideScroller/assets/default.genesys-scene +122 -0
- package/src/templates/src/templates/sideScroller/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/sideScroller/src/const.ts +46 -0
- package/src/templates/src/templates/sideScroller/src/game.ts +122 -0
- package/src/templates/src/templates/sideScroller/src/level-generator.ts +361 -0
- package/src/templates/src/templates/sideScroller/src/player.ts +125 -0
- package/src/templates/src/templates/thirdPerson/assets/default.genesys-scene +166 -0
- package/src/templates/src/templates/thirdPerson/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/thirdPerson/src/game.ts +39 -0
- package/src/templates/src/templates/thirdPerson/src/player.ts +61 -0
- package/src/templates/src/templates/vehicle/assets/default.genesys-scene +226 -0
- package/src/templates/src/templates/vehicle/assets/models/cyberTruck/chassis.glb +0 -0
- package/src/templates/src/templates/vehicle/assets/models/cyberTruck/wheel.glb +0 -0
- package/src/templates/src/templates/vehicle/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/vehicle/src/base-vehicle.ts +145 -0
- package/src/templates/src/templates/vehicle/src/game.ts +43 -0
- package/src/templates/src/templates/vehicle/src/mesh-vehicle.ts +191 -0
- package/src/templates/src/templates/vehicle/src/player.ts +109 -0
- package/src/templates/src/templates/vehicle/src/primitive-vehicle.ts +266 -0
- package/src/templates/src/templates/vehicle/src/ui-hints.ts +101 -0
- package/src/templates/src/templates/vr-game/assets/default.genesys-scene +247 -0
- package/src/templates/src/templates/vr-game/src/auto-imports.ts +1 -0
- package/src/templates/src/templates/vr-game/src/game.ts +66 -0
- package/src/templates/src/templates/vr-game/src/sample-vr-actor.ts +26 -0
- package/src/templates/tsconfig.json +35 -0
- package/src/templates/vite.config.ts +52 -0
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import pathlib from 'path';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { dialog, ipcMain, shell } from 'electron';
|
|
5
|
+
import { app } from 'electron';
|
|
6
|
+
import isDev from 'electron-is-dev';
|
|
7
|
+
import electronUpdater from 'electron-updater';
|
|
8
|
+
import upath from 'upath';
|
|
9
|
+
import { getAppVersion, getEngineVersion, getProjectFolderAndFile, IgnoredFiles, newProject, TEMPLATES } from '../../core/index.js';
|
|
10
|
+
import { buildProject } from '../../core/tools/build-project.js';
|
|
11
|
+
import { IpcSerializableError } from '../IpcSerializableError.js';
|
|
12
|
+
import { getLogPath, logger } from './logging.js';
|
|
13
|
+
import { clearPendingDeepLinkUrl, getPendingDeepLinkUrl, mainWindow } from './main.js';
|
|
14
|
+
import { appState } from './state.js';
|
|
15
|
+
import { ReleaseUrl } from './tools/const.js';
|
|
16
|
+
import { fileServer } from './tools/file-server.js';
|
|
17
|
+
import { openProject } from './tools/open-project.js';
|
|
18
|
+
const { autoUpdater } = electronUpdater;
|
|
19
|
+
export const handlers = {
|
|
20
|
+
fileServer: {
|
|
21
|
+
start: async (port, rootDir) => {
|
|
22
|
+
try {
|
|
23
|
+
await fileServer.start(port, fs.lstatSync(rootDir).isDirectory() ? rootDir : pathlib.dirname(rootDir));
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
return IpcSerializableError.serialize(error);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
stop: async () => {
|
|
31
|
+
try {
|
|
32
|
+
await fileServer.stop();
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
return IpcSerializableError.serialize(error);
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
status: async () => {
|
|
40
|
+
return {
|
|
41
|
+
isRunning: fileServer.isServerRunning(),
|
|
42
|
+
port: fileServer.getPort(),
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
os: {
|
|
47
|
+
chooseDirectory: async (title) => {
|
|
48
|
+
const { canceled, filePaths } = await dialog.showOpenDialog({
|
|
49
|
+
title,
|
|
50
|
+
properties: ['openDirectory'],
|
|
51
|
+
});
|
|
52
|
+
return canceled ? null : upath.normalize(filePaths[0]);
|
|
53
|
+
},
|
|
54
|
+
chooseGenesysProject: async (title) => {
|
|
55
|
+
const { canceled, filePaths } = await dialog.showOpenDialog({
|
|
56
|
+
title,
|
|
57
|
+
properties: ['openFile'],
|
|
58
|
+
filters: [
|
|
59
|
+
{ name: 'Genesys Project', extensions: ['genesys-project'] }
|
|
60
|
+
]
|
|
61
|
+
});
|
|
62
|
+
return canceled ? null : upath.normalize(filePaths[0]);
|
|
63
|
+
},
|
|
64
|
+
openPath: async (path) => {
|
|
65
|
+
const { folder } = getProjectFolderAndFile(path, logger);
|
|
66
|
+
await shell.openPath(folder);
|
|
67
|
+
},
|
|
68
|
+
openUrl: async (url) => {
|
|
69
|
+
await shell.openExternal(url);
|
|
70
|
+
},
|
|
71
|
+
showItemInFolder: (path) => {
|
|
72
|
+
shell.showItemInFolder(path);
|
|
73
|
+
},
|
|
74
|
+
readDirectory: async (path) => {
|
|
75
|
+
if (!fs.existsSync(path)) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
const folder = fs.lstatSync(path).isDirectory() ? path : pathlib.dirname(path);
|
|
79
|
+
return fs.readdirSync(folder).filter(file => !IgnoredFiles.includes(file));
|
|
80
|
+
},
|
|
81
|
+
exists: async (path) => {
|
|
82
|
+
return fs.existsSync(path);
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
tools: {
|
|
86
|
+
// given a folder or a file path, return the folder and the project file name
|
|
87
|
+
// if it's a directory, will try find the project file in that directory
|
|
88
|
+
// if folder is invalid or no project file is found, return empty strings
|
|
89
|
+
getProjectFolderAndFile: async (path) => {
|
|
90
|
+
return getProjectFolderAndFile(path, logger);
|
|
91
|
+
},
|
|
92
|
+
createProject: async (parentPath, projectName, templateId) => {
|
|
93
|
+
handlers.ui.showLoadingOverlay('Creating Project...');
|
|
94
|
+
const res = await newProject(parentPath, projectName, templateId, logger, handlerForCore);
|
|
95
|
+
if (res.error instanceof Error) {
|
|
96
|
+
res.error = IpcSerializableError.serialize(res.error);
|
|
97
|
+
}
|
|
98
|
+
// Track project creation time if successful
|
|
99
|
+
if (res.success && res.path) {
|
|
100
|
+
console.log(`[projects] 📝 Tracking new project: ${res.path}`);
|
|
101
|
+
appState.updateProjectLastOpened(res.path);
|
|
102
|
+
}
|
|
103
|
+
handlers.ui.hideLoadingOverlay();
|
|
104
|
+
return res;
|
|
105
|
+
},
|
|
106
|
+
openProject: async (projectPath) => {
|
|
107
|
+
const res = await openProject(projectPath, () => handlers.ui.showLoadingOverlay('Opening Project...'), () => handlers.ui.hideLoadingOverlay(), () => handlers.ui.showLoadingOverlay('Verifying Project...'), () => handlers.ui.hideLoadingOverlay(), () => handlers.ui.showLoadingOverlay('Updating Project...'), () => handlers.ui.hideLoadingOverlay());
|
|
108
|
+
if (res.error instanceof Error) {
|
|
109
|
+
res.error = IpcSerializableError.serialize(res.error);
|
|
110
|
+
}
|
|
111
|
+
// Track project open time if successful
|
|
112
|
+
if (res.success && res.path) {
|
|
113
|
+
console.log(`[projects] 📂 Tracking opened project: ${res.path}`);
|
|
114
|
+
appState.updateProjectLastOpened(res.path);
|
|
115
|
+
}
|
|
116
|
+
return res;
|
|
117
|
+
},
|
|
118
|
+
deleteProject: async (projectPath) => {
|
|
119
|
+
if (!fs.existsSync(projectPath)) {
|
|
120
|
+
return {
|
|
121
|
+
success: false,
|
|
122
|
+
message: 'Project not found',
|
|
123
|
+
path: projectPath
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
handlers.ui.showLoadingOverlay('Deleting Project...');
|
|
127
|
+
try {
|
|
128
|
+
const { folder: projectFolder } = getProjectFolderAndFile(projectPath, logger);
|
|
129
|
+
const entries = fs.readdirSync(projectFolder, { withFileTypes: true });
|
|
130
|
+
for (const entry of entries) {
|
|
131
|
+
const fullPath = pathlib.join(projectFolder, entry.name);
|
|
132
|
+
fs.rmSync(fullPath, { recursive: true, force: true });
|
|
133
|
+
}
|
|
134
|
+
// Remove the project from the projects list
|
|
135
|
+
appState.removeProject(projectPath);
|
|
136
|
+
return {
|
|
137
|
+
success: true,
|
|
138
|
+
message: `Project ${projectPath} deleted`,
|
|
139
|
+
path: projectPath
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
return {
|
|
144
|
+
success: false,
|
|
145
|
+
message: 'Failed to delete project',
|
|
146
|
+
path: projectPath,
|
|
147
|
+
error: IpcSerializableError.serialize(error),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
handlers.ui.hideLoadingOverlay();
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
buildProject: async (projectPath, runTsc) => {
|
|
155
|
+
handlers.ui.showLoadingOverlay('Building Project...');
|
|
156
|
+
const res = await buildProject(projectPath, runTsc, logger, handlerForCore);
|
|
157
|
+
if (res.error instanceof Error) {
|
|
158
|
+
res.error = IpcSerializableError.serialize(res.error);
|
|
159
|
+
}
|
|
160
|
+
handlers.ui.hideLoadingOverlay();
|
|
161
|
+
return res;
|
|
162
|
+
},
|
|
163
|
+
getProjectTemplates: async () => {
|
|
164
|
+
return TEMPLATES;
|
|
165
|
+
},
|
|
166
|
+
getProjects: async () => {
|
|
167
|
+
const projects = appState.getAllProjects();
|
|
168
|
+
return Object.entries(projects)
|
|
169
|
+
.map(([projectFilePath, lastOpened]) => {
|
|
170
|
+
// Check if the project path exists
|
|
171
|
+
const pathExists = fs.existsSync(projectFilePath);
|
|
172
|
+
let projectFileExists = false;
|
|
173
|
+
let projectFile = '';
|
|
174
|
+
let projectFolder = '';
|
|
175
|
+
if (pathExists) {
|
|
176
|
+
try {
|
|
177
|
+
// Get project folder and file info
|
|
178
|
+
const { folder, file } = getProjectFolderAndFile(projectFilePath, logger);
|
|
179
|
+
projectFolder = folder;
|
|
180
|
+
projectFile = file;
|
|
181
|
+
// Check if the project file exists
|
|
182
|
+
if (folder && file) {
|
|
183
|
+
const projectFilePath = path.join(folder, file);
|
|
184
|
+
projectFileExists = fs.existsSync(projectFilePath);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
// If getProjectFolderAndFile throws an error, consider the project as not found
|
|
189
|
+
projectFileExists = false;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
const isFound = pathExists && projectFileExists;
|
|
193
|
+
if (!isFound) {
|
|
194
|
+
[projectFolder, projectFile] = [path.dirname(projectFilePath), path.basename(projectFilePath)];
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
folder: projectFolder,
|
|
198
|
+
file: projectFile,
|
|
199
|
+
lastOpened: lastOpened,
|
|
200
|
+
isFound
|
|
201
|
+
};
|
|
202
|
+
})
|
|
203
|
+
.sort((a, b) => b.lastOpened - a.lastOpened);
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
app: {
|
|
207
|
+
getInfo: async () => {
|
|
208
|
+
return getAppInfo();
|
|
209
|
+
},
|
|
210
|
+
checkForUpdates: async (notifyWhenNoUpdates) => {
|
|
211
|
+
const result = await autoUpdater.checkForUpdates();
|
|
212
|
+
if (!result || !result.isUpdateAvailable) {
|
|
213
|
+
if (notifyWhenNoUpdates) {
|
|
214
|
+
dialog.showMessageBox(mainWindow, {
|
|
215
|
+
type: 'info',
|
|
216
|
+
buttons: ['OK'],
|
|
217
|
+
title: 'No Updates Available',
|
|
218
|
+
message: 'You are running the latest version of the application',
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
dialog.showMessageBox(mainWindow, {
|
|
225
|
+
type: 'info',
|
|
226
|
+
buttons: ['Manual Download', 'OK'],
|
|
227
|
+
title: 'Update Available',
|
|
228
|
+
message: 'An update is available and is being downloaded. You will be notified when it is ready to install.',
|
|
229
|
+
}).then(async ({ response }) => {
|
|
230
|
+
if (response === 0)
|
|
231
|
+
await shell.openExternal(ReleaseUrl);
|
|
232
|
+
});
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
getPath: (name) => {
|
|
237
|
+
return app.getPath(name);
|
|
238
|
+
},
|
|
239
|
+
getState: async (key) => {
|
|
240
|
+
return appState.getState(key);
|
|
241
|
+
},
|
|
242
|
+
setState: async (key, value) => {
|
|
243
|
+
appState.setState(key, value);
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
notifications: {
|
|
247
|
+
sendNotification: async (level, title, message) => {
|
|
248
|
+
const notification = {
|
|
249
|
+
level,
|
|
250
|
+
title,
|
|
251
|
+
message,
|
|
252
|
+
};
|
|
253
|
+
// Send notification to all renderer processes
|
|
254
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
255
|
+
mainWindow.webContents.send('notification', notification);
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
ui: {
|
|
260
|
+
reload: (force) => {
|
|
261
|
+
force ? mainWindow?.webContents.reloadIgnoringCache() : mainWindow?.reload();
|
|
262
|
+
},
|
|
263
|
+
showLoadingOverlay: async (message) => {
|
|
264
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
265
|
+
mainWindow.webContents.send('loading-overlay-show', message ?? 'Loading...');
|
|
266
|
+
mainWindow.setProgressBar(99, { mode: 'indeterminate' });
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
hideLoadingOverlay: async () => {
|
|
270
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
271
|
+
mainWindow.webContents.send('loading-overlay-hide');
|
|
272
|
+
mainWindow.setProgressBar(-1);
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
showErrorDialog: async (title, message) => {
|
|
276
|
+
dialog.showErrorBox(title, message);
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
window: {
|
|
280
|
+
minimize: () => {
|
|
281
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
282
|
+
mainWindow.minimize();
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
maximize: () => {
|
|
286
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
287
|
+
if (mainWindow.isMaximized()) {
|
|
288
|
+
mainWindow.unmaximize();
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
mainWindow.maximize();
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
unmaximize: () => {
|
|
296
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
297
|
+
mainWindow.unmaximize();
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
isMaximized: async () => {
|
|
301
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
302
|
+
return mainWindow.isMaximized();
|
|
303
|
+
}
|
|
304
|
+
return false;
|
|
305
|
+
},
|
|
306
|
+
close: () => {
|
|
307
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
308
|
+
mainWindow.close();
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
};
|
|
313
|
+
const handlerForCore = {
|
|
314
|
+
ui: handlers.ui,
|
|
315
|
+
os: handlers.os,
|
|
316
|
+
app: {
|
|
317
|
+
isPackaged: app.isPackaged,
|
|
318
|
+
resourcesPath: process.resourcesPath,
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
ipcMain.handle('fileServer.start', async (_, port, rootDir) => {
|
|
322
|
+
return handlers.fileServer.start(port, rootDir);
|
|
323
|
+
});
|
|
324
|
+
ipcMain.handle('fileServer.stop', async () => {
|
|
325
|
+
return handlers.fileServer.stop();
|
|
326
|
+
});
|
|
327
|
+
ipcMain.handle('fileServer.status', async () => {
|
|
328
|
+
return handlers.fileServer.status();
|
|
329
|
+
});
|
|
330
|
+
ipcMain.handle('os.chooseDirectory', async (_, title) => {
|
|
331
|
+
return handlers.os.chooseDirectory(title);
|
|
332
|
+
});
|
|
333
|
+
ipcMain.handle('os.chooseGenesysProject', async (_, title) => {
|
|
334
|
+
return handlers.os.chooseGenesysProject(title);
|
|
335
|
+
});
|
|
336
|
+
ipcMain.handle('os.openPath', async (_, path) => {
|
|
337
|
+
return handlers.os.openPath(path);
|
|
338
|
+
});
|
|
339
|
+
ipcMain.handle('os.openUrl', async (_, url) => {
|
|
340
|
+
return handlers.os.openUrl(url);
|
|
341
|
+
});
|
|
342
|
+
ipcMain.on('os.showItemInFolder', (_, path) => {
|
|
343
|
+
return handlers.os.showItemInFolder(path);
|
|
344
|
+
});
|
|
345
|
+
ipcMain.handle('os.readDirectory', async (_, path) => {
|
|
346
|
+
return handlers.os.readDirectory(path);
|
|
347
|
+
});
|
|
348
|
+
ipcMain.handle('os.exists', async (_, path) => {
|
|
349
|
+
return handlers.os.exists(path);
|
|
350
|
+
});
|
|
351
|
+
ipcMain.handle('os.platform', async () => {
|
|
352
|
+
return process.platform;
|
|
353
|
+
});
|
|
354
|
+
ipcMain.handle('tools.getProjectFolderAndFile', async (_, path) => {
|
|
355
|
+
return handlers.tools.getProjectFolderAndFile(path);
|
|
356
|
+
});
|
|
357
|
+
ipcMain.handle('tools.createProject', async (_, parentPath, projectName, templateId) => {
|
|
358
|
+
return handlers.tools.createProject(parentPath, projectName, templateId);
|
|
359
|
+
});
|
|
360
|
+
ipcMain.handle('tools.openProject', async (_, projectPath) => {
|
|
361
|
+
return handlers.tools.openProject(projectPath);
|
|
362
|
+
});
|
|
363
|
+
ipcMain.handle('tools.deleteProject', async (_, projectPath) => {
|
|
364
|
+
return handlers.tools.deleteProject(projectPath);
|
|
365
|
+
});
|
|
366
|
+
ipcMain.handle('tools.buildProject', async (_, projectPath, runTsc) => {
|
|
367
|
+
return handlers.tools.buildProject(projectPath, runTsc);
|
|
368
|
+
});
|
|
369
|
+
ipcMain.handle('tools.getProjectTemplates', async () => {
|
|
370
|
+
return handlers.tools.getProjectTemplates();
|
|
371
|
+
});
|
|
372
|
+
ipcMain.handle('tools.getProjects', async () => {
|
|
373
|
+
return handlers.tools.getProjects();
|
|
374
|
+
});
|
|
375
|
+
ipcMain.on('tools.toggleDevConsole', () => {
|
|
376
|
+
mainWindow && mainWindow.webContents.toggleDevTools();
|
|
377
|
+
});
|
|
378
|
+
ipcMain.handle('app.getInfo', async () => {
|
|
379
|
+
return handlers.app.getInfo();
|
|
380
|
+
});
|
|
381
|
+
ipcMain.handle('app.getPath', async (_, name) => {
|
|
382
|
+
return handlers.app.getPath(name);
|
|
383
|
+
});
|
|
384
|
+
ipcMain.handle('app.checkForUpdates', async (_, notifyWhenNoUpdates) => {
|
|
385
|
+
return handlers.app.checkForUpdates(notifyWhenNoUpdates);
|
|
386
|
+
});
|
|
387
|
+
ipcMain.handle('app.getState', async (_, key) => {
|
|
388
|
+
return handlers.app.getState(key);
|
|
389
|
+
});
|
|
390
|
+
ipcMain.handle('app.setState', async (_, key, value) => {
|
|
391
|
+
return handlers.app.setState(key, value);
|
|
392
|
+
});
|
|
393
|
+
ipcMain.handle('notifications.sendNotification', async (_, level, title, message) => {
|
|
394
|
+
return handlers.notifications.sendNotification(level, title, message);
|
|
395
|
+
});
|
|
396
|
+
ipcMain.on('ui.reload', (_, force) => {
|
|
397
|
+
handlers.ui.reload(force);
|
|
398
|
+
});
|
|
399
|
+
ipcMain.handle('ui.showLoadingOverlay', async (_, message) => {
|
|
400
|
+
return handlers.ui.showLoadingOverlay(message);
|
|
401
|
+
});
|
|
402
|
+
ipcMain.handle('ui.hideLoadingOverlay', async () => {
|
|
403
|
+
return handlers.ui.hideLoadingOverlay();
|
|
404
|
+
});
|
|
405
|
+
ipcMain.on('dev.loadUrl', (_, url) => {
|
|
406
|
+
isDev && mainWindow?.loadURL(url);
|
|
407
|
+
});
|
|
408
|
+
ipcMain.on('window.minimize', () => {
|
|
409
|
+
handlers.window.minimize();
|
|
410
|
+
});
|
|
411
|
+
ipcMain.on('window.maximize', () => {
|
|
412
|
+
handlers.window.maximize();
|
|
413
|
+
});
|
|
414
|
+
ipcMain.on('window.unmaximize', () => {
|
|
415
|
+
handlers.window.unmaximize();
|
|
416
|
+
});
|
|
417
|
+
ipcMain.handle('window.isMaximized', async () => {
|
|
418
|
+
return handlers.window.isMaximized();
|
|
419
|
+
});
|
|
420
|
+
ipcMain.on('window.close', () => {
|
|
421
|
+
handlers.window.close();
|
|
422
|
+
});
|
|
423
|
+
ipcMain.on('register-deep-link', () => {
|
|
424
|
+
console.log('🔗 [deep-link] Renderer registered for deep links');
|
|
425
|
+
// Check if there's a pending deep link URL
|
|
426
|
+
const pendingUrl = getPendingDeepLinkUrl();
|
|
427
|
+
if (pendingUrl && mainWindow && !mainWindow.isDestroyed()) {
|
|
428
|
+
console.log('🔗 [deep-link] Sending pending deep link to renderer:', pendingUrl);
|
|
429
|
+
mainWindow.webContents.send('deep-link', pendingUrl);
|
|
430
|
+
clearPendingDeepLinkUrl();
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
export function getAppInfo() {
|
|
434
|
+
return {
|
|
435
|
+
isDev: isDev,
|
|
436
|
+
engineVersion: getEngineVersion(),
|
|
437
|
+
appVersion: getAppVersion(),
|
|
438
|
+
appName: app.getName(),
|
|
439
|
+
logPath: getLogPath(),
|
|
440
|
+
};
|
|
441
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { app, BrowserWindow } from 'electron';
|
|
4
|
+
import log from 'electron-log';
|
|
5
|
+
class BackendLogger {
|
|
6
|
+
/** Logs normally but without forwarding to frontend windows */
|
|
7
|
+
verbose(...params) {
|
|
8
|
+
console.log(...params);
|
|
9
|
+
}
|
|
10
|
+
log(...params) {
|
|
11
|
+
console.log(...params);
|
|
12
|
+
BrowserWindow.getAllWindows().forEach(window => {
|
|
13
|
+
window.webContents.send('log', ...params);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
error(...params) {
|
|
17
|
+
console.error(...params);
|
|
18
|
+
BrowserWindow.getAllWindows().forEach(window => {
|
|
19
|
+
window.webContents.send('error', ...params);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
warn(...params) {
|
|
23
|
+
console.warn(...params);
|
|
24
|
+
BrowserWindow.getAllWindows().forEach(window => {
|
|
25
|
+
window.webContents.send('warn', ...params);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function getLogPath() {
|
|
30
|
+
return path.join(app.getPath('userData'), 'logs', `${app.getName()}.log`);
|
|
31
|
+
}
|
|
32
|
+
export function configureLogging() {
|
|
33
|
+
const logPath = getLogPath();
|
|
34
|
+
fs.mkdirSync(path.dirname(logPath), { recursive: true });
|
|
35
|
+
log.transports.file.resolvePathFn = () => logPath;
|
|
36
|
+
log.initialize();
|
|
37
|
+
console.log = log.log;
|
|
38
|
+
console.error = log.error;
|
|
39
|
+
console.warn = log.warn;
|
|
40
|
+
}
|
|
41
|
+
export const logger = new BackendLogger();
|