refactor: restructure to monorepo with apps and packages directories - Move companion app to apps/companion with electron-vite - Move domain/application/infrastructure to packages/ - Fix ELECTRON_RUN_AS_NODE env var issue for VS Code terminal - Remove legacy esbuild bundler (replaced by electron-vite) - Update workspace scripts in root package.json

This commit is contained in:
2025-11-22 00:25:06 +01:00
parent d20554df55
commit 7eae6e3bd4
39 changed files with 515 additions and 1939 deletions

View File

@@ -0,0 +1,67 @@
import { defineConfig } from 'electron-vite';
import react from '@vitejs/plugin-react';
import { resolve } from 'path';
export default defineConfig({
main: {
build: {
outDir: 'dist/main',
lib: {
entry: resolve(__dirname, 'main/index.ts'),
formats: ['cjs'],
},
rollupOptions: {
external: [
'@nut-tree-fork/nut-js',
'@nut-tree-fork/libnut',
'@nut-tree-fork/libnut-darwin',
'@nut-tree-fork/libnut-linux',
'@nut-tree-fork/libnut-win32',
'@nut-tree-fork/node-mac-permissions',
'@nut-tree-fork/default-clipboard-provider',
'@nut-tree-fork/provider-interfaces',
'@nut-tree-fork/shared',
'bufferutil',
'utf-8-validate',
],
output: {
entryFileNames: 'main.cjs',
},
},
},
resolve: {
alias: {
'@': resolve(__dirname, '../../'),
},
},
},
preload: {
build: {
outDir: 'dist/preload',
lib: {
entry: resolve(__dirname, 'main/preload.ts'),
formats: ['cjs'],
},
rollupOptions: {
output: {
entryFileNames: 'preload.js',
},
},
},
},
renderer: {
root: resolve(__dirname, 'renderer'),
build: {
outDir: resolve(__dirname, 'dist/renderer'),
rollupOptions: {
input: resolve(__dirname, 'renderer/index.html'),
},
},
resolve: {
alias: {
'@': resolve(__dirname, '../../'),
},
},
plugins: [react()],
},
});

View File

@@ -1,13 +1,13 @@
import { InMemorySessionRepository } from '../../../infrastructure/repositories/InMemorySessionRepository';
import { MockBrowserAutomationAdapter } from '../../../infrastructure/adapters/automation/MockBrowserAutomationAdapter';
import { BrowserDevToolsAdapter } from '../../../infrastructure/adapters/automation/BrowserDevToolsAdapter';
import { NutJsAutomationAdapter } from '../../../infrastructure/adapters/automation/NutJsAutomationAdapter';
import { MockAutomationEngineAdapter } from '../../../infrastructure/adapters/automation/MockAutomationEngineAdapter';
import { StartAutomationSessionUseCase } from '../../../packages/application/use-cases/StartAutomationSessionUseCase';
import { loadAutomationConfig, AutomationMode } from '../../../infrastructure/config';
import type { ISessionRepository } from '../../../packages/application/ports/ISessionRepository';
import type { IBrowserAutomation } from '../../../packages/application/ports/IBrowserAutomation';
import type { IAutomationEngine } from '../../../packages/application/ports/IAutomationEngine';
import { InMemorySessionRepository } from '@/packages/infrastructure/repositories/InMemorySessionRepository';
import { MockBrowserAutomationAdapter } from '@/packages/infrastructure/adapters/automation/MockBrowserAutomationAdapter';
import { BrowserDevToolsAdapter } from '@/packages/infrastructure/adapters/automation/BrowserDevToolsAdapter';
import { NutJsAutomationAdapter } from '@/packages/infrastructure/adapters/automation/NutJsAutomationAdapter';
import { MockAutomationEngineAdapter } from '@/packages/infrastructure/adapters/automation/MockAutomationEngineAdapter';
import { StartAutomationSessionUseCase } from '@/packages/application/use-cases/StartAutomationSessionUseCase';
import { loadAutomationConfig, AutomationMode } from '@/packages/infrastructure/config';
import type { ISessionRepository } from '@/packages/application/ports/ISessionRepository';
import type { IBrowserAutomation } from '@/packages/application/ports/IBrowserAutomation';
import type { IAutomationEngine } from '@/packages/application/ports/IAutomationEngine';
export interface BrowserConnectionResult {
success: boolean;

View File

@@ -17,8 +17,8 @@ function createWindow() {
mainWindow.loadURL('http://localhost:5173');
mainWindow.webContents.openDevTools();
} else {
// Path from dist/main/apps/companion/main to dist/renderer/src/apps/companion/renderer/index.html
mainWindow.loadFile(path.join(__dirname, '../../../../renderer/src/apps/companion/renderer/index.html'));
// Path from dist/main to dist/renderer
mainWindow.loadFile(path.join(__dirname, '../renderer/index.html'));
}
setupIpcHandlers(mainWindow);

View File

@@ -1,9 +1,9 @@
import { ipcMain } from 'electron';
import type { BrowserWindow, IpcMainInvokeEvent } from 'electron';
import { DIContainer } from './di-container';
import type { HostedSessionConfig } from '../../../packages/domain/entities/HostedSessionConfig';
import { StepId } from '../../../packages/domain/value-objects/StepId';
import { MockAutomationEngineAdapter } from '../../../infrastructure/adapters/automation/MockAutomationEngineAdapter';
import type { HostedSessionConfig } from '@/packages/domain/entities/HostedSessionConfig';
import { StepId } from '@/packages/domain/value-objects/StepId';
import { MockAutomationEngineAdapter } from '@/packages/infrastructure/adapters/automation/MockAutomationEngineAdapter';
export function setupIpcHandlers(mainWindow: BrowserWindow): void {
const container = DIContainer.getInstance();

View File

@@ -0,0 +1,29 @@
{
"name": "@gridpilot/companion",
"version": "0.1.0",
"description": "GridPilot Companion - Electron app for iRacing automation",
"main": "dist/main/main.cjs",
"type": "module",
"scripts": {
"dev": "unset ELECTRON_RUN_AS_NODE && electron-vite dev",
"build": "electron-vite build",
"preview": "unset ELECTRON_RUN_AS_NODE && electron-vite preview",
"start": "unset ELECTRON_RUN_AS_NODE && electron ."
},
"devDependencies": {
"@types/node": "^22.10.2",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"@vitejs/plugin-react": "^4.2.0",
"electron": "^28.3.3",
"electron-vite": "^2.3.0",
"typescript": "^5.7.2",
"vite": "^5.4.21"
},
"dependencies": {
"@nut-tree-fork/nut-js": "^4.2.6",
"puppeteer-core": "^24.31.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}

View File

@@ -7,6 +7,6 @@
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/apps/companion/renderer/main.tsx"></script>
<script type="module" src="./main.tsx"></script>
</body>
</html>

View File

@@ -1,41 +0,0 @@
const esbuild = require('esbuild');
const path = require('path');
async function build() {
try {
console.log('Building main process with esbuild...');
// Build main process
await esbuild.build({
entryPoints: ['src/apps/companion/main/index.ts'],
bundle: true,
platform: 'node',
target: 'node20',
format: 'cjs',
outfile: 'dist/main/apps/companion/main/index.js',
external: ['electron'],
sourcemap: true,
logLevel: 'info',
});
// Build preload script
await esbuild.build({
entryPoints: ['src/apps/companion/main/preload.ts'],
bundle: true,
platform: 'node',
target: 'node20',
format: 'cjs',
outfile: 'dist/main/apps/companion/main/preload.js',
external: ['electron'],
sourcemap: true,
logLevel: 'info',
});
console.log('✓ Main process and preload script built successfully');
} catch (error) {
console.error('✗ Build failed:', error);
process.exit(1);
}
}
build();

2231
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -7,8 +7,8 @@
"node": ">=20.0.0"
},
"workspaces": [
"src/packages/*",
"src/apps/*"
"packages/*",
"apps/*"
],
"scripts": {
"dev": "echo 'Development server placeholder - to be configured'",
@@ -19,33 +19,17 @@
"test:e2e": "vitest run tests/e2e",
"test:watch": "vitest watch",
"typecheck": "tsc --noEmit",
"companion": "npm run companion:build && electron .",
"companion:dev": "npm run companion:build && (node build-main.config.js --watch & vite build --config vite.config.electron.ts --watch & electron .)",
"companion:build": "node build-main.config.js && vite build --config vite.config.electron.ts",
"companion:start": "electron .",
"companion:mock": "AUTOMATION_MODE=mock npm run companion:start",
"companion:devtools": "AUTOMATION_MODE=dev npm run companion:start",
"companion:production": "AUTOMATION_MODE=production npm run companion:start",
"companion": "npm run companion:build --workspace=@gridpilot/companion && npm run start --workspace=@gridpilot/companion",
"companion:dev": "npm run dev --workspace=@gridpilot/companion",
"companion:build": "npm run build --workspace=@gridpilot/companion",
"companion:start": "npm run start --workspace=@gridpilot/companion",
"chrome:debug": "open -a 'Google Chrome' --args --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug"
},
"devDependencies": {
"@cucumber/cucumber": "^11.0.1",
"@types/node": "^22.10.2",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"@vitejs/plugin-react": "^4.2.0",
"@vitest/ui": "^2.1.8",
"electron": "^39.2.3",
"esbuild": "^0.27.0",
"typescript": "^5.7.2",
"vite": "^6.0.3",
"vitest": "^2.1.8"
},
"dependencies": {
"@nut-tree-fork/nut-js": "^4.2.6",
"puppeteer-core": "^24.31.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"main": "dist/main/apps/companion/main/index.js"
"dependencies": {}
}

View File

@@ -13,12 +13,13 @@
"noEmit": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
"@/*": ["./*"]
},
"types": ["vitest/globals"]
},
"include": [
"src/**/*",
"packages/**/*",
"apps/**/*",
"tests/**/*"
],
"exclude": [

View File

@@ -1,19 +0,0 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { resolve } from 'path';
export default defineConfig({
plugins: [react()],
base: './',
root: '.',
build: {
outDir: 'dist/renderer',
emptyOutDir: true,
rollupOptions: {
input: resolve(__dirname, 'src/apps/companion/renderer/index.html')
}
},
server: {
port: 5173
}
});