@gnsx/genesys.sdk 4.2.9
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 +58 -0
- package/dist/src/asset-pack/scripts/post-install.js +64 -0
- package/dist/src/asset-pack/src/index.js +1 -0
- package/dist/src/core/cli.js +303 -0
- package/dist/src/core/common.js +325 -0
- package/dist/src/core/index.js +6 -0
- package/dist/src/core/tools/build-project.js +456 -0
- package/dist/src/core/tools/index.js +2 -0
- package/dist/src/core/tools/new-asset-pack.js +153 -0
- package/dist/src/core/tools/new-project.js +293 -0
- package/dist/src/core/types.js +1 -0
- package/dist/src/dependencies.js +84 -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 +452 -0
- package/dist/src/electron/backend/logging.js +41 -0
- package/dist/src/electron/backend/main.js +369 -0
- package/dist/src/electron/backend/menu.js +196 -0
- package/dist/src/electron/backend/state.js +201 -0
- package/dist/src/electron/backend/telemetry.js +9 -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 +249 -0
- package/dist/src/electron/backend/window.js +161 -0
- package/dist/src/templates/eslint.config.js +58 -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/migrate-scenes-and-prefabs.js +252 -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 +33 -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 +55 -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 +60 -0
- package/dist/src/templates/src/templates/fps/src/weapon.js +54 -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 +38 -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 +102 -0
- package/dist/src/templates/src/templates/sideScroller/src/level-generator.js +249 -0
- package/dist/src/templates/src/templates/sideScroller/src/player.js +100 -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 +58 -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 +188 -0
- package/dist/src/templates/src/templates/vehicle/src/player.js +97 -0
- package/dist/src/templates/src/templates/vehicle/src/primitive-vehicle.js +258 -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 +181 -0
- package/scripts/post-install.ts +143 -0
- package/src/asset-pack/.gitattributes +89 -0
- package/src/asset-pack/.github/workflows/publish.yml +90 -0
- package/src/asset-pack/eslint.config.js +59 -0
- package/src/asset-pack/gitignore +11 -0
- package/src/asset-pack/scripts/post-install.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 +104 -0
- package/src/templates/CLAUDE.md +1 -0
- package/src/templates/README.md +24 -0
- package/src/templates/eslint.config.js +60 -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/migrate-scenes-and-prefabs.ts +301 -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 +39 -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 +59 -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 +66 -0
- package/src/templates/src/templates/fps/src/weapon.ts +47 -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 +40 -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 +121 -0
- package/src/templates/src/templates/sideScroller/src/level-generator.ts +361 -0
- package/src/templates/src/templates/sideScroller/src/player.ts +123 -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 +58 -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 +189 -0
- package/src/templates/src/templates/vehicle/src/player.ts +106 -0
- package/src/templates/src/templates/vehicle/src/primitive-vehicle.ts +264 -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,452 @@
|
|
|
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
|
+
try {
|
|
120
|
+
await fs.promises.access(projectPath);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return {
|
|
124
|
+
success: false,
|
|
125
|
+
message: 'Project not found',
|
|
126
|
+
path: projectPath
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
handlers.ui.showLoadingOverlay('Deleting Project...');
|
|
130
|
+
try {
|
|
131
|
+
const { folder: projectFolder } = getProjectFolderAndFile(projectPath, logger);
|
|
132
|
+
await fs.promises.rm(projectFolder, { recursive: true, force: true });
|
|
133
|
+
// Remove the project from the projects list
|
|
134
|
+
appState.removeProject(projectPath);
|
|
135
|
+
return {
|
|
136
|
+
success: true,
|
|
137
|
+
message: `Project ${projectPath} deleted`,
|
|
138
|
+
path: projectPath
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
return {
|
|
143
|
+
success: false,
|
|
144
|
+
message: 'Failed to delete project',
|
|
145
|
+
path: projectPath,
|
|
146
|
+
error: IpcSerializableError.serialize(error),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
handlers.ui.hideLoadingOverlay();
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
buildProject: async (projectPath, runTsc) => {
|
|
154
|
+
handlers.ui.showLoadingOverlay('Building Project...');
|
|
155
|
+
const res = await buildProject(projectPath, runTsc, logger, handlerForCore);
|
|
156
|
+
if (res.error instanceof Error) {
|
|
157
|
+
res.error = IpcSerializableError.serialize(res.error);
|
|
158
|
+
}
|
|
159
|
+
handlers.ui.hideLoadingOverlay();
|
|
160
|
+
return res;
|
|
161
|
+
},
|
|
162
|
+
getProjectTemplates: async () => {
|
|
163
|
+
return TEMPLATES;
|
|
164
|
+
},
|
|
165
|
+
getProjects: async () => {
|
|
166
|
+
const projects = appState.getAllProjects();
|
|
167
|
+
return Object.entries(projects)
|
|
168
|
+
.map(([projectFilePath, lastOpened]) => {
|
|
169
|
+
// Check if the project path exists
|
|
170
|
+
const pathExists = fs.existsSync(projectFilePath);
|
|
171
|
+
let projectFileExists = false;
|
|
172
|
+
let projectFile = '';
|
|
173
|
+
let projectFolder = '';
|
|
174
|
+
if (pathExists) {
|
|
175
|
+
try {
|
|
176
|
+
// Get project folder and file info
|
|
177
|
+
const { folder, file } = getProjectFolderAndFile(projectFilePath, logger);
|
|
178
|
+
projectFolder = folder;
|
|
179
|
+
projectFile = file;
|
|
180
|
+
// Check if the project file exists
|
|
181
|
+
if (folder && file) {
|
|
182
|
+
const projectFilePath = path.join(folder, file);
|
|
183
|
+
projectFileExists = fs.existsSync(projectFilePath);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
// If getProjectFolderAndFile throws an error, consider the project as not found
|
|
188
|
+
projectFileExists = false;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const isFound = pathExists && projectFileExists;
|
|
192
|
+
if (!isFound) {
|
|
193
|
+
[projectFolder, projectFile] = [path.dirname(projectFilePath), path.basename(projectFilePath)];
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
folder: projectFolder,
|
|
197
|
+
file: projectFile,
|
|
198
|
+
lastOpened: lastOpened,
|
|
199
|
+
isFound
|
|
200
|
+
};
|
|
201
|
+
})
|
|
202
|
+
.sort((a, b) => b.lastOpened - a.lastOpened);
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
app: {
|
|
206
|
+
getInfo: async () => {
|
|
207
|
+
return getAppInfo();
|
|
208
|
+
},
|
|
209
|
+
checkForUpdates: async (notifyWhenNoUpdates) => {
|
|
210
|
+
// Check for GH_TOKEN environment variable
|
|
211
|
+
if (!process.env.GH_TOKEN) {
|
|
212
|
+
logger.warn('GH_TOKEN environment variable is missing - update check will be skipped');
|
|
213
|
+
dialog.showMessageBox(mainWindow, {
|
|
214
|
+
type: 'warning',
|
|
215
|
+
buttons: ['OK'],
|
|
216
|
+
title: 'Update Check Warning',
|
|
217
|
+
message: 'GitHub Token Missing',
|
|
218
|
+
detail: 'The GH_TOKEN environment variable is not set.\n\nUpdate checks require a GitHub token to access private releases.\n\nPlease set the GH_TOKEN environment variable and restart the application to enable automatic updates.',
|
|
219
|
+
});
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const result = await autoUpdater.checkForUpdates();
|
|
223
|
+
if (!result || !result.isUpdateAvailable) {
|
|
224
|
+
if (notifyWhenNoUpdates) {
|
|
225
|
+
dialog.showMessageBox(mainWindow, {
|
|
226
|
+
type: 'info',
|
|
227
|
+
buttons: ['OK'],
|
|
228
|
+
title: 'No Updates Available',
|
|
229
|
+
message: 'You are running the latest version of the application',
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
dialog.showMessageBox(mainWindow, {
|
|
236
|
+
type: 'info',
|
|
237
|
+
buttons: ['Manual Download', 'OK'],
|
|
238
|
+
title: 'Update Available',
|
|
239
|
+
message: 'An update is available and is being downloaded. You will be notified when it is ready to install.',
|
|
240
|
+
}).then(async ({ response }) => {
|
|
241
|
+
if (response === 0)
|
|
242
|
+
await shell.openExternal(ReleaseUrl);
|
|
243
|
+
});
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
getPath: (name) => {
|
|
248
|
+
return app.getPath(name);
|
|
249
|
+
},
|
|
250
|
+
getState: async (key) => {
|
|
251
|
+
return appState.getState(key);
|
|
252
|
+
},
|
|
253
|
+
setState: async (key, value) => {
|
|
254
|
+
appState.setState(key, value);
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
notifications: {
|
|
258
|
+
sendNotification: async (level, title, message) => {
|
|
259
|
+
const notification = {
|
|
260
|
+
level,
|
|
261
|
+
title,
|
|
262
|
+
message,
|
|
263
|
+
};
|
|
264
|
+
// Send notification to all renderer processes
|
|
265
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
266
|
+
mainWindow.webContents.send('notification', notification);
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
ui: {
|
|
271
|
+
reload: (force) => {
|
|
272
|
+
force ? mainWindow?.webContents.reloadIgnoringCache() : mainWindow?.reload();
|
|
273
|
+
},
|
|
274
|
+
showLoadingOverlay: async (message) => {
|
|
275
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
276
|
+
mainWindow.webContents.send('loading-overlay-show', message ?? 'Loading...');
|
|
277
|
+
mainWindow.setProgressBar(99, { mode: 'indeterminate' });
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
hideLoadingOverlay: async () => {
|
|
281
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
282
|
+
mainWindow.webContents.send('loading-overlay-hide');
|
|
283
|
+
mainWindow.setProgressBar(-1);
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
showErrorDialog: async (title, message) => {
|
|
287
|
+
dialog.showErrorBox(title, message);
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
window: {
|
|
291
|
+
minimize: () => {
|
|
292
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
293
|
+
mainWindow.minimize();
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
maximize: () => {
|
|
297
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
298
|
+
if (mainWindow.isMaximized()) {
|
|
299
|
+
mainWindow.unmaximize();
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
mainWindow.maximize();
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
},
|
|
306
|
+
unmaximize: () => {
|
|
307
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
308
|
+
mainWindow.unmaximize();
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
isMaximized: async () => {
|
|
312
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
313
|
+
return mainWindow.isMaximized();
|
|
314
|
+
}
|
|
315
|
+
return false;
|
|
316
|
+
},
|
|
317
|
+
close: () => {
|
|
318
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
319
|
+
mainWindow.close();
|
|
320
|
+
}
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
};
|
|
324
|
+
const handlerForCore = {
|
|
325
|
+
ui: handlers.ui,
|
|
326
|
+
os: handlers.os,
|
|
327
|
+
app: {
|
|
328
|
+
isPackaged: app.isPackaged,
|
|
329
|
+
resourcesPath: process.resourcesPath,
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
ipcMain.handle('fileServer.start', async (_, port, rootDir) => {
|
|
333
|
+
return handlers.fileServer.start(port, rootDir);
|
|
334
|
+
});
|
|
335
|
+
ipcMain.handle('fileServer.stop', async () => {
|
|
336
|
+
return handlers.fileServer.stop();
|
|
337
|
+
});
|
|
338
|
+
ipcMain.handle('fileServer.status', async () => {
|
|
339
|
+
return handlers.fileServer.status();
|
|
340
|
+
});
|
|
341
|
+
ipcMain.handle('os.chooseDirectory', async (_, title) => {
|
|
342
|
+
return handlers.os.chooseDirectory(title);
|
|
343
|
+
});
|
|
344
|
+
ipcMain.handle('os.chooseGenesysProject', async (_, title) => {
|
|
345
|
+
return handlers.os.chooseGenesysProject(title);
|
|
346
|
+
});
|
|
347
|
+
ipcMain.handle('os.openPath', async (_, path) => {
|
|
348
|
+
return handlers.os.openPath(path);
|
|
349
|
+
});
|
|
350
|
+
ipcMain.handle('os.openUrl', async (_, url) => {
|
|
351
|
+
return handlers.os.openUrl(url);
|
|
352
|
+
});
|
|
353
|
+
ipcMain.on('os.showItemInFolder', (_, path) => {
|
|
354
|
+
return handlers.os.showItemInFolder(path);
|
|
355
|
+
});
|
|
356
|
+
ipcMain.handle('os.readDirectory', async (_, path) => {
|
|
357
|
+
return handlers.os.readDirectory(path);
|
|
358
|
+
});
|
|
359
|
+
ipcMain.handle('os.exists', async (_, path) => {
|
|
360
|
+
return handlers.os.exists(path);
|
|
361
|
+
});
|
|
362
|
+
ipcMain.handle('os.platform', async () => {
|
|
363
|
+
return process.platform;
|
|
364
|
+
});
|
|
365
|
+
ipcMain.handle('tools.getProjectFolderAndFile', async (_, path) => {
|
|
366
|
+
return handlers.tools.getProjectFolderAndFile(path);
|
|
367
|
+
});
|
|
368
|
+
ipcMain.handle('tools.createProject', async (_, parentPath, projectName, templateId) => {
|
|
369
|
+
return handlers.tools.createProject(parentPath, projectName, templateId);
|
|
370
|
+
});
|
|
371
|
+
ipcMain.handle('tools.openProject', async (_, projectPath) => {
|
|
372
|
+
return handlers.tools.openProject(projectPath);
|
|
373
|
+
});
|
|
374
|
+
ipcMain.handle('tools.deleteProject', async (_, projectPath) => {
|
|
375
|
+
return handlers.tools.deleteProject(projectPath);
|
|
376
|
+
});
|
|
377
|
+
ipcMain.handle('tools.buildProject', async (_, projectPath, runTsc) => {
|
|
378
|
+
return handlers.tools.buildProject(projectPath, runTsc);
|
|
379
|
+
});
|
|
380
|
+
ipcMain.handle('tools.getProjectTemplates', async () => {
|
|
381
|
+
return handlers.tools.getProjectTemplates();
|
|
382
|
+
});
|
|
383
|
+
ipcMain.handle('tools.getProjects', async () => {
|
|
384
|
+
return handlers.tools.getProjects();
|
|
385
|
+
});
|
|
386
|
+
ipcMain.on('tools.toggleDevConsole', () => {
|
|
387
|
+
mainWindow && mainWindow.webContents.toggleDevTools();
|
|
388
|
+
});
|
|
389
|
+
ipcMain.handle('app.getInfo', async () => {
|
|
390
|
+
return handlers.app.getInfo();
|
|
391
|
+
});
|
|
392
|
+
ipcMain.handle('app.getPath', async (_, name) => {
|
|
393
|
+
return handlers.app.getPath(name);
|
|
394
|
+
});
|
|
395
|
+
ipcMain.handle('app.checkForUpdates', async (_, notifyWhenNoUpdates) => {
|
|
396
|
+
return handlers.app.checkForUpdates(notifyWhenNoUpdates);
|
|
397
|
+
});
|
|
398
|
+
ipcMain.handle('app.getState', async (_, key) => {
|
|
399
|
+
return handlers.app.getState(key);
|
|
400
|
+
});
|
|
401
|
+
ipcMain.handle('app.setState', async (_, key, value) => {
|
|
402
|
+
return handlers.app.setState(key, value);
|
|
403
|
+
});
|
|
404
|
+
ipcMain.handle('notifications.sendNotification', async (_, level, title, message) => {
|
|
405
|
+
return handlers.notifications.sendNotification(level, title, message);
|
|
406
|
+
});
|
|
407
|
+
ipcMain.on('ui.reload', (_, force) => {
|
|
408
|
+
handlers.ui.reload(force);
|
|
409
|
+
});
|
|
410
|
+
ipcMain.handle('ui.showLoadingOverlay', async (_, message) => {
|
|
411
|
+
return handlers.ui.showLoadingOverlay(message);
|
|
412
|
+
});
|
|
413
|
+
ipcMain.handle('ui.hideLoadingOverlay', async () => {
|
|
414
|
+
return handlers.ui.hideLoadingOverlay();
|
|
415
|
+
});
|
|
416
|
+
ipcMain.on('dev.loadUrl', (_, url) => {
|
|
417
|
+
isDev && mainWindow?.loadURL(url);
|
|
418
|
+
});
|
|
419
|
+
ipcMain.on('window.minimize', () => {
|
|
420
|
+
handlers.window.minimize();
|
|
421
|
+
});
|
|
422
|
+
ipcMain.on('window.maximize', () => {
|
|
423
|
+
handlers.window.maximize();
|
|
424
|
+
});
|
|
425
|
+
ipcMain.on('window.unmaximize', () => {
|
|
426
|
+
handlers.window.unmaximize();
|
|
427
|
+
});
|
|
428
|
+
ipcMain.handle('window.isMaximized', async () => {
|
|
429
|
+
return handlers.window.isMaximized();
|
|
430
|
+
});
|
|
431
|
+
ipcMain.on('window.close', () => {
|
|
432
|
+
handlers.window.close();
|
|
433
|
+
});
|
|
434
|
+
ipcMain.on('register-deep-link', () => {
|
|
435
|
+
console.log('🔗 [deep-link] Renderer registered for deep links');
|
|
436
|
+
// Check if there's a pending deep link URL
|
|
437
|
+
const pendingUrl = getPendingDeepLinkUrl();
|
|
438
|
+
if (pendingUrl && mainWindow && !mainWindow.isDestroyed()) {
|
|
439
|
+
console.log('🔗 [deep-link] Sending pending deep link to renderer:', pendingUrl);
|
|
440
|
+
mainWindow.webContents.send('deep-link', pendingUrl);
|
|
441
|
+
clearPendingDeepLinkUrl();
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
export function getAppInfo() {
|
|
445
|
+
return {
|
|
446
|
+
isDev: isDev,
|
|
447
|
+
engineVersion: getEngineVersion(),
|
|
448
|
+
appVersion: getAppVersion(),
|
|
449
|
+
appName: app.getName(),
|
|
450
|
+
logPath: getLogPath(),
|
|
451
|
+
};
|
|
452
|
+
}
|
|
@@ -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();
|