diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml deleted file mode 100644 index 1ecba69..0000000 --- a/.github/workflows/claude-code-review.yml +++ /dev/null @@ -1,44 +0,0 @@ -# name: Claude Code Review - -# on: -# pull_request: -# types: [opened, synchronize, ready_for_review, reopened] -# # Optional: Only run on specific file changes -# # paths: -# # - "src/**/*.ts" -# # - "src/**/*.tsx" -# # - "src/**/*.js" -# # - "src/**/*.jsx" - -# jobs: -# claude-review: -# # Optional: Filter by PR author -# # if: | -# # github.event.pull_request.user.login == 'external-contributor' || -# # github.event.pull_request.user.login == 'new-developer' || -# # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' - -# runs-on: ubuntu-latest -# permissions: -# contents: read -# pull-requests: read -# issues: read -# id-token: write - -# steps: -# - name: Checkout repository -# uses: actions/checkout@v4 -# with: -# fetch-depth: 1 - -# - name: Run Claude Code Review -# id: claude-review -# uses: anthropics/claude-code-action@v1 -# with: -# claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} -# plugin_marketplaces: 'https://github.com/anthropics/claude-code.git' -# plugins: 'code-review@claude-code-plugins' -# prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}' -# # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md -# # or https://code.claude.com/docs/en/cli-reference for available options - diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml deleted file mode 100644 index 812b1d5..0000000 --- a/.github/workflows/claude.yml +++ /dev/null @@ -1,50 +0,0 @@ -# name: Claude Code - -# on: -# issue_comment: -# types: [created] -# pull_request_review_comment: -# types: [created] -# issues: -# types: [opened, assigned] -# pull_request_review: -# types: [submitted] - -# jobs: -# claude: -# if: | -# (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || -# (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || -# (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || -# (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) -# runs-on: ubuntu-latest -# permissions: -# contents: read -# pull-requests: read -# issues: read -# id-token: write -# actions: read # Required for Claude to read CI results on PRs -# steps: -# - name: Checkout repository -# uses: actions/checkout@v4 -# with: -# fetch-depth: 1 - -# - name: Run Claude Code -# id: claude -# uses: anthropics/claude-code-action@v1 -# with: -# claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} - -# # This is an optional setting that allows Claude to read CI results on PRs -# additional_permissions: | -# actions: read - -# # Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it. -# # prompt: 'Update the pull request description to include a summary of changes.' - -# # Optional: Add claude_args to customize behavior and configuration -# # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md -# # or https://code.claude.com/docs/en/cli-reference for available options -# # claude_args: '--allowed-tools Bash(gh pr *)' - diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index f967348..02d625b 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -11,6 +11,7 @@ permissions: jobs: e2e: runs-on: ubuntu-latest + timeout-minutes: 20 steps: - uses: actions/checkout@v5 @@ -22,9 +23,11 @@ jobs: - run: npm ci - - name: Install Playwright browsers - run: npx playwright install chromium --with-deps + - name: Install Playwright system dependencies + run: DEBIAN_FRONTEND=noninteractive npx playwright install-deps chromium working-directory: app/packages/web + timeout-minutes: 5 + - run: npm run app:test:e2e diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index fcf2118..9c35992 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -11,6 +11,7 @@ permissions: jobs: integration: runs-on: ubuntu-latest + timeout-minutes: 20 steps: - uses: actions/checkout@v5 @@ -22,9 +23,11 @@ jobs: - run: npm ci - - name: Install Playwright browsers - run: npx playwright install chromium --with-deps + - name: Install Playwright system dependencies + run: DEBIAN_FRONTEND=noninteractive npx playwright install-deps chromium working-directory: app/packages/web + timeout-minutes: 5 + - run: npm run app:test:integration diff --git a/CLAUDE.md b/CLAUDE.md index 6d45e22..b20fb93 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -14,11 +14,18 @@ The repo uses a single **npm-workspaces** tree rooted at the repo root. Workspac # Install all workspaces in one go (run from repo root) npm install -# Run the dev servers (Nest on 3001, Vite on 5173 with /api proxy) -npm run app:dev - -# Production build (shared → server → web) -npm run app:build && npm run app:start # http://localhost:3001 +# Launch the Electron desktop app in dev mode (HMR on renderer saves, auto-restarts main+preload) +npm run app:dev # delegates to desktop:dev — equivalent to: npm run desktop:dev + +# Production build then launch +npm run app:build # compiles shared → desktop-main → web TypeScript (not the Electron bundle) +npm run desktop:build # electron-vite build → produces out/main, out/preload, out/renderer +npm run app:start # starts the built Electron app (requires desktop:build to have run first) + +# Electron desktop app — electron-vite drives three pipelines (main/preload/renderer) +# configured in electron.vite.config.ts; outputs land in out/main, out/preload, out/renderer +npm run desktop:dev # electron-vite dev: HMR on renderer saves, auto-restarts main+preload +npm run desktop:build # electron-vite build: produces out/main, out/preload, out/renderer # Build all Lambda bundles (required before `terraform apply`) npm run app:build:lambdas diff --git a/app/eslint.config.js b/app/eslint.config.js index be61b18..98bafb5 100644 --- a/app/eslint.config.js +++ b/app/eslint.config.js @@ -10,6 +10,7 @@ export default tseslint.config( { ignores: [ '**/dist/**', + '**/out/**', '**/node_modules/**', '**/*.d.ts', 'packages/web/vite.config.ts', diff --git a/app/package.json b/app/package.json index 1cff71a..02c7292 100644 --- a/app/package.json +++ b/app/package.json @@ -5,11 +5,11 @@ "type": "module", "scripts": { "predev": "node scripts/embed-tfstate.mjs", - "dev": "echo 'app:dev requires the Electron launcher from Epic A (#136). Run npm run dev -w @hyveon/web for the web-only dev server.' && exit 1", + "dev": "electron-vite dev --config ../electron.vite.config.ts", "prebuild": "node scripts/embed-tfstate.mjs", "build": "npm run build -w @hyveon/shared && npm run build -w @hyveon/desktop-main && npm run build -w @hyveon/web", "build:lambdas": "npm run build -w @hyveon/shared && npm run build -w @hyveon/lambda-interactions -w @hyveon/lambda-followup -w @hyveon/lambda-update-dns -w @hyveon/lambda-watchdog -w @hyveon/lambda-efs-seeder", - "start": "echo 'app:start requires the Electron launcher from Epic A (#136).' && exit 1", + "start": "electron ../out/main/index.js", "test": "vitest run", "test:coverage": "vitest run --coverage", "test:watch": "vitest", diff --git a/app/packages/desktop-main/package.json b/app/packages/desktop-main/package.json index 2ec8c49..d6dce2a 100644 --- a/app/packages/desktop-main/package.json +++ b/app/packages/desktop-main/package.json @@ -5,9 +5,9 @@ "type": "module", "main": "./dist/main.js", "scripts": { - "dev": "echo 'desktop-main now runs as an Electron IPC microservice. The Electron launcher is wired in Epic A (#136).' && exit 1", + "dev": "electron-vite dev --config ../../../electron.vite.config.ts", "build": "tsc -b", - "start": "echo 'desktop-main now runs as an Electron IPC microservice. The Electron launcher is wired in Epic A (#136).' && exit 1" + "start": "electron ../../../out/main/index.js" }, "dependencies": { "@aws-sdk/client-cloudwatch-logs": "^3.600.0", diff --git a/app/packages/desktop-main/src/electron-entry.test.ts b/app/packages/desktop-main/src/electron-entry.test.ts new file mode 100644 index 0000000..a222338 --- /dev/null +++ b/app/packages/desktop-main/src/electron-entry.test.ts @@ -0,0 +1,257 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; + +/* + * Spy variables must be hoisted before vi.mock() factories run, because + * vi.mock() calls are lifted to the top of the compiled output above regular + * declarations. + */ +const { + mockLoadURL, + mockLoadFile, + mockQuit, + mockOn, + mockWhenReady, + MockBrowserWindow, + mockGetAllWindows, + bootstrapMock, + whenReadyCallbacks, + onCallbacks, +} = vi.hoisted(() => { + const mockLoadURL = vi.fn().mockResolvedValue(undefined); + const mockLoadFile = vi.fn().mockResolvedValue(undefined); + const mockQuit = vi.fn(); + const mockGetAllWindows = vi.fn().mockReturnValue([]); + + /** + * Collects every callback passed to `app.whenReady().then(cb)`. + * Tests can fire them on demand by calling `whenReadyCallbacks[n]()`. + */ + const whenReadyCallbacks: Array<() => void> = []; + + /** + * Collects every callback registered via `app.on(event, cb)` keyed by + * event name, so tests can trigger lifecycle events synchronously. + */ + const onCallbacks: Record void> = {}; + + const mockOn = vi.fn((event: string, cb: () => void) => { + onCallbacks[event] = cb; + }); + + /** + * Returns a thenable that stores the `.then()` callback instead of + * resolving it, giving tests full control over when the ready handler fires. + */ + const mockWhenReady = vi.fn(() => ({ + then: (cb: () => void) => { + whenReadyCallbacks.push(cb); + return { then: vi.fn() }; + }, + })); + + /** Spy BrowserWindow constructor whose instances expose controlled load fns. */ + const MockBrowserWindow = vi.fn().mockImplementation(() => ({ + loadURL: mockLoadURL, + loadFile: mockLoadFile, + })); + + /** `BrowserWindow.getAllWindows()` static method used by the activate handler. */ + MockBrowserWindow.getAllWindows = mockGetAllWindows; + + /** Spy for `bootstrap` imported from `./main.js`. */ + const bootstrapMock = vi.fn().mockResolvedValue(undefined); + + return { + mockLoadURL, + mockLoadFile, + mockQuit, + mockOn, + mockWhenReady, + MockBrowserWindow, + mockGetAllWindows, + bootstrapMock, + whenReadyCallbacks, + onCallbacks, + }; +}); + +vi.mock('electron', () => ({ + app: { + whenReady: mockWhenReady, + on: mockOn, + quit: mockQuit, + }, + BrowserWindow: MockBrowserWindow, +})); + +vi.mock('./main.js', () => ({ + bootstrap: bootstrapMock, +})); + +/** Flush the micro-task / timer queue so async chains fully settle. */ +async function flushPromises(): Promise { + await new Promise((resolve) => setTimeout(resolve, 0)); +} + +describe('electron-entry', () => { + beforeEach(() => { + mockLoadURL.mockResolvedValue(undefined); + mockLoadFile.mockResolvedValue(undefined); + mockQuit.mockImplementation(() => undefined); + bootstrapMock.mockResolvedValue(undefined); + mockGetAllWindows.mockReturnValue([]); + + // Re-apply the BrowserWindow constructor implementation in case clearMocks + // cleared it between tests (clearMocks resets call history and return value + // queues; mockImplementation persists, but we re-set to be defensive). + MockBrowserWindow.mockImplementation(() => ({ + loadURL: mockLoadURL, + loadFile: mockLoadFile, + })); + + // Re-apply mockOn and mockWhenReady implementations so callback capturing + // works correctly after clearMocks resets the call history. + mockOn.mockImplementation((event: string, cb: () => void) => { + onCallbacks[event] = cb; + }); + mockWhenReady.mockImplementation(() => ({ + then: (cb: () => void) => { + whenReadyCallbacks.push(cb); + return { then: vi.fn() }; + }, + })); + + // Reset the callback queues so each test starts clean. + whenReadyCallbacks.length = 0; + for (const key of Object.keys(onCallbacks)) { + delete onCallbacks[key]; + } + }); + + afterEach(() => { + vi.unstubAllEnvs(); + }); + + it('should call bootstrap() inside the app.whenReady() callback', async () => { + vi.resetModules(); + delete process.env['ELECTRON_RENDERER_URL']; + + await import('./electron-entry.js'); + await flushPromises(); + + // Fire the whenReady callback that the module registered at import time. + expect(whenReadyCallbacks).toHaveLength(1); + whenReadyCallbacks[0]!(); + await flushPromises(); + + expect(bootstrapMock).toHaveBeenCalledOnce(); + }); + + it('should call win.loadURL() with the dev server URL when ELECTRON_RENDERER_URL is set', async () => { + vi.resetModules(); + process.env['ELECTRON_RENDERER_URL'] = 'http://localhost:5173'; + + await import('./electron-entry.js'); + await flushPromises(); + + expect(whenReadyCallbacks).toHaveLength(1); + whenReadyCallbacks[0]!(); + await flushPromises(); + + expect(mockLoadURL).toHaveBeenCalledOnce(); + expect(mockLoadURL).toHaveBeenCalledWith('http://localhost:5173'); + expect(mockLoadFile).not.toHaveBeenCalled(); + }); + + it('should call win.loadFile() with the production renderer path when ELECTRON_RENDERER_URL is not set', async () => { + vi.resetModules(); + delete process.env['ELECTRON_RENDERER_URL']; + + await import('./electron-entry.js'); + await flushPromises(); + + expect(whenReadyCallbacks).toHaveLength(1); + whenReadyCallbacks[0]!(); + await flushPromises(); + + expect(mockLoadFile).toHaveBeenCalledOnce(); + expect(mockLoadURL).not.toHaveBeenCalled(); + + // The path must end with the standard electron-vite renderer bundle location. + const calledPath = mockLoadFile.mock.calls[0]?.[0] as string; + expect(calledPath).toMatch(/renderer[/\\]index\.html$/); + }); + + it('should call app.quit() on window-all-closed for non-macOS platforms', async () => { + vi.resetModules(); + delete process.env['ELECTRON_RENDERER_URL']; + + await import('./electron-entry.js'); + await flushPromises(); + + const handler = onCallbacks['window-all-closed']; + expect(handler).toBeDefined(); + + const originalPlatform = process.platform; + Object.defineProperty(process, 'platform', { value: 'linux', configurable: true }); + + handler!(); + + expect(mockQuit).toHaveBeenCalledOnce(); + + Object.defineProperty(process, 'platform', { value: originalPlatform, configurable: true }); + }); + + it('should NOT call app.quit() on window-all-closed on macOS', async () => { + vi.resetModules(); + delete process.env['ELECTRON_RENDERER_URL']; + + await import('./electron-entry.js'); + await flushPromises(); + + const handler = onCallbacks['window-all-closed']; + expect(handler).toBeDefined(); + + const originalPlatform = process.platform; + Object.defineProperty(process, 'platform', { value: 'darwin', configurable: true }); + + handler!(); + + expect(mockQuit).not.toHaveBeenCalled(); + + Object.defineProperty(process, 'platform', { value: originalPlatform, configurable: true }); + }); + + it('should call app.quit() when the renderer fails to load', async () => { + vi.resetModules(); + delete process.env['ELECTRON_RENDERER_URL']; + + mockLoadFile.mockRejectedValueOnce(new Error('renderer bundle missing')); + + await import('./electron-entry.js'); + await flushPromises(); + + expect(whenReadyCallbacks).toHaveLength(1); + whenReadyCallbacks[0]!(); + await flushPromises(); + + expect(mockQuit).toHaveBeenCalledOnce(); + }); + + it('should call app.quit() and not open a window when bootstrap() rejects', async () => { + vi.resetModules(); + delete process.env['ELECTRON_RENDERER_URL']; + + bootstrapMock.mockRejectedValueOnce(new Error('IPC init failure')); + + await import('./electron-entry.js'); + await flushPromises(); + + expect(whenReadyCallbacks).toHaveLength(1); + whenReadyCallbacks[0]!(); + await flushPromises(); + + expect(mockQuit).toHaveBeenCalledOnce(); + expect(MockBrowserWindow).not.toHaveBeenCalled(); + }); +}); diff --git a/app/packages/desktop-main/src/electron-entry.ts b/app/packages/desktop-main/src/electron-entry.ts new file mode 100644 index 0000000..019563f --- /dev/null +++ b/app/packages/desktop-main/src/electron-entry.ts @@ -0,0 +1,58 @@ +import { app, BrowserWindow } from 'electron'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { bootstrap } from './main.js'; + +// electron-vite injects __dirname for main-process entries, but we also +// compute it explicitly via import.meta.url so the file is valid plain ESM. +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +/** + * Creates the main application window with the preload script wired in and + * loads either the dev server URL or the production renderer bundle. + */ +function createWindow(): void { + const win = new BrowserWindow({ + width: 1200, + height: 800, + webPreferences: { + // electron-vite outputs the preload bundle to out/preload/index.js by + // default. __dirname here resolves to out/main, so we go one level up. + preload: path.join(__dirname, '../preload/index.js'), + contextIsolation: true, + sandbox: true, + }, + }); + + const load = process.env.ELECTRON_RENDERER_URL + ? win.loadURL(process.env.ELECTRON_RENDERER_URL) + : win.loadFile(path.join(__dirname, '../renderer/index.html')); + + load.catch((err: unknown) => { + console.error('[desktop-main] Renderer failed to load — quitting:', err); + app.quit(); + }); +} + +app.whenReady().then(() => { + bootstrap() + .then(() => { + createWindow(); + + // On macOS re-create the window when the dock icon is clicked and there + // are no other windows open (standard macOS behaviour). + app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) createWindow(); + }); + }) + .catch((err: unknown) => { + console.error('[desktop-main] NestJS IPC bootstrap failed — quitting:', err); + app.quit(); + }); +}); + +// Quit the app when all windows are closed, except on macOS where the app and +// its menu bar conventionally stay active until the user explicitly quits. +app.on('window-all-closed', () => { + if (process.platform !== 'darwin') app.quit(); +}); diff --git a/app/packages/desktop-main/src/main.test.ts b/app/packages/desktop-main/src/main.test.ts index 594e05d..f4f5e35 100644 --- a/app/packages/desktop-main/src/main.test.ts +++ b/app/packages/desktop-main/src/main.test.ts @@ -88,7 +88,8 @@ describe('main bootstrap', () => { * all stubs remain active. */ vi.resetModules(); - await import('./main.js'); + const { bootstrap } = await import('./main.js'); + await bootstrap(); // Flush the event loop so the async bootstrap chain fully resolves. await new Promise((resolve) => setTimeout(resolve, 0)); @@ -114,9 +115,10 @@ describe('main bootstrap', () => { expect(fakeApp.listen).toHaveBeenCalledOnce(); }); - it('should call applyFixPath during bootstrap', async () => { + it('should call applyFixPath on module initialisation', async () => { vi.resetModules(); - await import('./main.js'); + const { bootstrap } = await import('./main.js'); + await bootstrap(); // Flush the event loop so the async bootstrap chain fully resolves. await new Promise((resolve) => setTimeout(resolve, 0)); @@ -125,9 +127,10 @@ describe('main bootstrap', () => { expect(applyFixPathMock).toHaveBeenCalledTimes(1); }); - it('should resolve userData path and initialise the file logger before bootstrap', async () => { + it('should resolve userData path and initialise the file logger on module initialisation', async () => { vi.resetModules(); - await import('./main.js'); + const { bootstrap } = await import('./main.js'); + await bootstrap(); // Flush the event loop so the async bootstrap chain fully resolves. await new Promise((resolve) => setTimeout(resolve, 0)); diff --git a/app/packages/desktop-main/src/main.ts b/app/packages/desktop-main/src/main.ts index 052aba0..d6c7ed6 100644 --- a/app/packages/desktop-main/src/main.ts +++ b/app/packages/desktop-main/src/main.ts @@ -23,12 +23,16 @@ if (!process.versions['electron']) { const { app } = await import('electron') as unknown as { app: { getPath(name: string): string } }; createLogger(path.join(app.getPath('userData'), 'logs')); -async function bootstrap(): Promise { +/** + * Bootstraps the NestJS IPC microservice. + * + * Called from `electron-entry.ts` after `app.whenReady()` so that + * `ipcMain` is available before the transport is initialised. + */ +export async function bootstrap(): Promise { const app = await NestFactory.createMicroservice(AppModule, { strategy: new ElectronIPCTransport(), }); await app.listen(); } - -void bootstrap(); diff --git a/app/packages/desktop-main/src/services/ElectronStoreService.ts b/app/packages/desktop-main/src/services/ElectronStoreService.ts index 77c16e5..68c06a9 100644 --- a/app/packages/desktop-main/src/services/ElectronStoreService.ts +++ b/app/packages/desktop-main/src/services/ElectronStoreService.ts @@ -1,8 +1,16 @@ import { Injectable } from '@nestjs/common'; -import Store from 'electron-store'; +import type Store from 'electron-store'; import { logger } from '../logger.js'; import { SafeStorageService } from './SafeStorageService.js'; +// electron-store@11 is ESM-only — require() would throw ERR_REQUIRE_ESM. +// Load via dynamic import, but only inside Electron; in plain-Node test +// environments process.versions.electron is undefined so this stays undefined +// and createStore() (which is only called inside Electron) is never reached. +const ElectronStoreModule = process.versions['electron'] + ? await import('electron-store') + : undefined; + /** * Typed schema for the application's persistent electron-store. * @@ -147,7 +155,10 @@ export class ElectronStoreService { * directory. */ protected createStore(): Store { - return new Store({ name: 'electron-store' }); + // ElectronStoreModule is always defined here: the constructor calls + // createStore() only when readIsElectron() is true. + const StoreClass = ElectronStoreModule!.default; + return new StoreClass({ name: 'electron-store' }); } /** diff --git a/app/packages/web/playwright.config.ts b/app/packages/web/playwright.config.ts index a1f8b9d..fcb32cc 100644 --- a/app/packages/web/playwright.config.ts +++ b/app/packages/web/playwright.config.ts @@ -12,10 +12,18 @@ export default defineConfig({ use: { baseURL: 'http://localhost:4173', trace: 'retain-on-failure', - video: 'retain-on-failure', + // Video requires ffmpeg which hangs on install in CI; traces are sufficient + video: process.env.CI ? 'off' : 'retain-on-failure', }, projects: [ - { name: 'chromium', use: { ...devices['Desktop Chrome'] } }, + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + // In CI use the pre-installed system Chrome to avoid downloading Chromium + ...(process.env.CI ? { channel: 'chrome' } : {}), + }, + }, ], webServer: { command: 'npm run build && npm run preview', diff --git a/app/packages/web/playwright.integration.config.ts b/app/packages/web/playwright.integration.config.ts index 112a850..d3f254d 100644 --- a/app/packages/web/playwright.integration.config.ts +++ b/app/packages/web/playwright.integration.config.ts @@ -19,10 +19,18 @@ export default defineConfig({ use: { baseURL: 'http://localhost:4174', trace: 'retain-on-failure', - video: 'retain-on-failure', + // Video requires ffmpeg which hangs on install in CI; traces are sufficient + video: process.env.CI ? 'off' : 'retain-on-failure', }, projects: [ - { name: 'chromium', use: { ...devices['Desktop Chrome'] } }, + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + // In CI use the pre-installed system Chrome to avoid downloading Chromium + ...(process.env.CI ? { channel: 'chrome' } : {}), + }, + }, ], webServer: [ { diff --git a/electron.vite.config.ts b/electron.vite.config.ts new file mode 100644 index 0000000..0302835 --- /dev/null +++ b/electron.vite.config.ts @@ -0,0 +1,43 @@ +import { defineConfig, externalizeDepsPlugin } from 'electron-vite'; +import react from '@vitejs/plugin-react'; +import tailwindcss from '@tailwindcss/vite'; +import { fileURLToPath } from 'node:url'; + +/** Resolve a path relative to this config file, regardless of cwd. */ +const r = (p: string) => fileURLToPath(new URL(p, import.meta.url)); + +export default defineConfig({ + main: { + plugins: [externalizeDepsPlugin()], + build: { + rollupOptions: { + input: r('app/packages/desktop-main/src/electron-entry.ts'), + output: { + format: 'es', + }, + }, + }, + }, + preload: { + plugins: [externalizeDepsPlugin()], + build: { + rollupOptions: { + input: r('app/packages/desktop-preload/src/preload.ts'), + }, + }, + }, + renderer: { + root: r('app/packages/web'), + plugins: [react(), tailwindcss()], + resolve: { + alias: { + '@': r('app/packages/web/src'), + }, + }, + build: { + rollupOptions: { + input: r('app/packages/web/index.html'), + }, + }, + }, +}); diff --git a/package-lock.json b/package-lock.json index d569e97..bee19b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,9 @@ "app/packages/lambda/*", "scripts" ], + "devDependencies": { + "electron-vite": "^5.0.0" + }, "engines": { "node": ">=20" } @@ -1560,7 +1563,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", "dev": true, "license": "MIT", "engines": { @@ -1617,6 +1622,22 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.29.7.tgz", + "integrity": "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-react-jsx-self": { "version": "7.27.1", "dev": true, @@ -3870,235 +3891,509 @@ "dev": true, "license": "MIT" }, - "node_modules/@rollup/rollup-linux-x64-gnu": { + "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.3.tgz", + "integrity": "sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw==", "cpu": [ - "x64" + "arm" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" + "android" ] }, - "node_modules/@rollup/rollup-linux-x64-musl": { + "node_modules/@rollup/rollup-android-arm64": { "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.3.tgz", + "integrity": "sha512-xw3xtkDApIOGayehp2+Rz4zimfkaX65r4t47iy+ymQB2G4iJCBBfj0ogVg5jpvjpn8UWn/+q9tprxleYeNp3Hw==", "cpu": [ - "x64" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" + "android" ] }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.3.tgz", + "integrity": "sha512-vo6Y5Qfpx7/5EaamIwi0WqW2+zfiusVihKatLvtN1VFVy3D13uERk/6gZLU1UiHRL6fDXqj/ELIeVRGnvcTE1g==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.3.tgz", + "integrity": "sha512-D+0QGcZhBzTN82weOnsSlY7V7+RMmPuF1CkbxyMAGE8+ZHeUjyb76ZiWmBlCu//AQQONvxcqRbwZTajZKqjuOw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@sinonjs/fake-timers": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", - "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.3.tgz", + "integrity": "sha512-6HnvHCT7fDyj6R0Ph7A6x8dQS/S38MClRWeDLqc0MdfWkxjiu1HSDYrdPhqSILzjTIC/pnXbbJbo+ft+gy/9hQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] }, - "node_modules/@sinonjs/samsam": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.3.tgz", - "integrity": "sha512-hw6HbX+GyVZzmaYNh82Ecj1vdGZrqVIn/keDTg63IgAwiQPO+xCz99uG6Woqgb4tM0mUiFENKZ4cqd7IX94AXQ==", + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.3.tgz", + "integrity": "sha512-KHLgC3WKlUYW3ShFKnnosZDOJ0xjg9zp7au3sIm2bs/tGBeC2ipmvRh/N7JKi0t9Ue20C0dpEshi8WUubg+cnA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "type-detect": "^4.1.0" - } + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] }, - "node_modules/@sinonjs/samsam/node_modules/type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.3.tgz", + "integrity": "sha512-DV6fJoxEYWJOvaZIsok7KrYl0tPvga5OZ2yvKHNNYyk/2roMLqQAbGhr78EQ5YhHpnhLKJD3S1WFusAkmUuV5g==", + "cpu": [ + "arm" + ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "engines": { - "node": ">=4" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@smithy/config-resolver": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.5.1.tgz", - "integrity": "sha512-abXk3LhODsvRHsk0ZS9ztrg/fZatTa9Z/z4pgx65YSLR+rY6kvUG/1IgcDKEUciR8MfdnkT5oPeHJTy/HhzDIQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.3.tgz", + "integrity": "sha512-mQKoJAzvuOs6F+TZybQO4GOTSMUu7v0WdxEk24krQ/uUxXoPTtHjuaUuPmFhtBcM4K0ons8nrE3JyhTuCFtT/w==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@smithy/core": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.24.1.tgz", - "integrity": "sha512-3mT7o4qQyUWttYnVK3A0Z/u3Xha3E81tXn32Tz6vjZiUXhBrkEivpw1hBYfh84iFF9CSzkBU9Y1DJ3Q6RQ231g==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/crc32": "5.2.0", - "@smithy/types": "^4.14.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.3.tgz", + "integrity": "sha512-Whjj2qoiJ6+OOJMGptTYazaJvjOJm+iKHpXQM1P3LzGjt7Ff++Tp7nH4N8J/BUA7R9IHfDyx4DJIflifwnbmIA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@smithy/credential-provider-imds": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.3.1.tgz", - "integrity": "sha512-0S/acwHnqX4WrjXzhdiDRxsG2s9SC0cpPIK9nZ1R6UOHd+j7uL28+4bHu22urbLk2TVw3fkp6na/+fkUt/pLNQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.1", - "@smithy/types": "^4.14.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.3.tgz", + "integrity": "sha512-4YTNHKqGng5+yiZt3mg77nmyuCfmNfX4fPmyUapBcIk+BdwSwmCWGXOUxhXbBEkFHtoN5boLj/5NON+u5QC9tg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@smithy/eventstream-serde-browser": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.3.1.tgz", - "integrity": "sha512-X7MyI1fu8M84IPKk49kO4kb27Mqp6un9/0o/MsA1ngZ5OxxWKGUxPS3S/AJ9q1cPVTSGmRcbaGNfGUSsflTJkg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.3.tgz", + "integrity": "sha512-SU3kNlhkpI4UqlUc2VXPGK9o886ZsSeGfMAX2ba2b8DKmMXq4AL7KUrkSWVbb7koVqx41Yczx6dx5PNargIrEA==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.4.1.tgz", - "integrity": "sha512-JZGbSXaBk7JY8VPzsh66ksJ0nTWXbApduFDkA/pEl3aTm2EoAiUZE1Iltp6c+X1bB8kxPQW0mHDfVdYCpWTOzg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.3.tgz", + "integrity": "sha512-6lDLl5h4TXpB1mTf2rQWnAk/LcXrx9vBfu/DT5TIPhvMhRWaZ5MxkIc8u4lJAmBo6klTe1ywXIUHFjylW505sg==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@smithy/eventstream-serde-node": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.3.1.tgz", - "integrity": "sha512-6Cn4xTNVxn9PWTHSbvf8zmcDhQW8lrLE1Xq5CJgmX6wEvdjS2S0KuE79Aiznv/jx51jpFJ98OuWyE+Bt+oG1MQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.24.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.3.tgz", + "integrity": "sha512-BMo8bOw8evlup/8G+cj5xWtPyp93xPdyoSN16Zy90Q2QZ0ZYRhCt6ZJSwbrRzG9HApFabjwj2p25TUPDWrhzqQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@smithy/fetch-http-handler": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.4.1.tgz", - "integrity": "sha512-r7bN6spQ+caZC8AnyvSxkRUb57zt2jhhRw3Z+2Ez8hjq6coIikDBFUUI/+CQ1xx9K6eX1Gx6wUKo4ylU66TIqw==", - "license": "Apache-2.0", + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.3.tgz", + "integrity": "sha512-E0L8X1dZN1/Rph+5VPF6Xj2G7JJvMACVXtamTJIDrVI44Y3K+G8gQaMEAavbqCGTa16InptiVrX6eM6pmJ+7qA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.3.tgz", + "integrity": "sha512-oZJ/WHaVfHUiRAtmTAeo3DcevNsVvH8mbvodjZy7D5QKvCefO371SiKRpxoDcCxB3PTRTLayWBkvmDQKTcX/sw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.3.tgz", + "integrity": "sha512-Dhbyh7j9FybM3YaTgaHmVALwA8AkUwTPccyCQ79TG9AJUsMQqgN1DDEZNr4+QUfwiWvLDumW5vdwzoeUF+TNxQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.3.tgz", + "integrity": "sha512-cJd1X5XhHHlltkaypz1UcWLA8AcoIi1aWhsvaWDskD1oz2eKCypnqvTQ8ykMNI0RSmm7NkTdSqSSD7zM0xa6Ig==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.3", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.3", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.3.tgz", + "integrity": "sha512-QaWcIgRxqEdQdhJqW4DJctsH6HCmo5vHxY0krHSX4jMtOqfzC+dqDGuHM87bu4H8JBeibWx7jFz+h6/4C8wA5Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.3.tgz", + "integrity": "sha512-AaXwSvUi3QIPtroAUw1t5yHGIyqKEXwH54WUocFolZhpGDruJcs8c+xPNDRn4XiQsS7MEwnYsHW2l0MBLDMkWg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.3.tgz", + "integrity": "sha512-65LAKM/bAWDqKNEelHlcHvm2V+Vfb8C6INFxQXRHCvaVN1rJfwr4NvdP4FyzUaLqWfaCGaadf6UbTm8xJeYfEg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.3.tgz", + "integrity": "sha512-EEM2gyhBF5MFnI6vMKdX1LAosE627RGBzIoGMdLloPZkXrUN0Ckqgr2Qi8+J3zip/8NVVro3/FjB+tjhZUgUHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.3.tgz", + "integrity": "sha512-E5Eb5H/DpxaoXH++Qkv28RcUJboMopmdDUALBczvHMf7hNIxaDZqwY5lK12UK1BHacSmvupoEWGu+n993Z0y1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.3.tgz", + "integrity": "sha512-hPt/bgL5cE+Qp+/TPHBqptcAgPzgj46mPcg/16zNUmbQk0j+mOEQV/+Lqu8QRtDV3Ek95Q6FeFITpuhl6OTsAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", + "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.3.tgz", + "integrity": "sha512-hw6HbX+GyVZzmaYNh82Ecj1vdGZrqVIn/keDTg63IgAwiQPO+xCz99uG6Woqgb4tM0mUiFENKZ4cqd7IX94AXQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "type-detect": "^4.1.0" + } + }, + "node_modules/@sinonjs/samsam/node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.5.1.tgz", + "integrity": "sha512-abXk3LhODsvRHsk0ZS9ztrg/fZatTa9Z/z4pgx65YSLR+rY6kvUG/1IgcDKEUciR8MfdnkT5oPeHJTy/HhzDIQ==", + "license": "Apache-2.0", "dependencies": { "@smithy/core": "^3.24.1", - "@smithy/types": "^4.14.1", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@smithy/hash-node": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.3.1.tgz", - "integrity": "sha512-u0/zo11mg7yNneoYgTkH4sXwSmcBpbl49o4UNCtQ7hYsXxynsN25KYHmXzqi7TPk5HQL5klGnpU5koOY0O+9hw==", + "node_modules/@smithy/core": { + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.24.1.tgz", + "integrity": "sha512-3mT7o4qQyUWttYnVK3A0Z/u3Xha3E81tXn32Tz6vjZiUXhBrkEivpw1hBYfh84iFF9CSzkBU9Y1DJ3Q6RQ231g==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.24.1", + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.14.1", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@smithy/invalid-dependency": { + "node_modules/@smithy/credential-provider-imds": { "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.3.1.tgz", - "integrity": "sha512-cLmwtDoulyZvRepAfyV+3rx5oMvuh51dbE+6En3vGC09j3uVSRt1U4oguNu32ub3soGX0oYtBs8E7S2Q4SxTqg==", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.3.1.tgz", + "integrity": "sha512-0S/acwHnqX4WrjXzhdiDRxsG2s9SC0cpPIK9nZ1R6UOHd+j7uL28+4bHu22urbLk2TVw3fkp6na/+fkUt/pLNQ==", "license": "Apache-2.0", "dependencies": { "@smithy/core": "^3.24.1", + "@smithy/types": "^4.14.1", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@smithy/is-array-buffer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", - "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "node_modules/@smithy/eventstream-serde-browser": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.3.1.tgz", + "integrity": "sha512-X7MyI1fu8M84IPKk49kO4kb27Mqp6un9/0o/MsA1ngZ5OxxWKGUxPS3S/AJ9q1cPVTSGmRcbaGNfGUSsflTJkg==", "license": "Apache-2.0", "dependencies": { + "@smithy/core": "^3.24.1", "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" } }, - "node_modules/@smithy/middleware-compression": { + "node_modules/@smithy/eventstream-serde-config-resolver": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-compression/-/middleware-compression-4.4.1.tgz", - "integrity": "sha512-p5HLi70K05XqhXHPQEhANMv3xhFAgcz0O11sCd8MZEXI45Y86A5hLEwDNQPbvoHh3U3B+NKdh1vqlsjpiozfXw==", - "dev": true, + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.4.1.tgz", + "integrity": "sha512-JZGbSXaBk7JY8VPzsh66ksJ0nTWXbApduFDkA/pEl3aTm2EoAiUZE1Iltp6c+X1bB8kxPQW0mHDfVdYCpWTOzg==", "license": "Apache-2.0", "dependencies": { "@smithy/core": "^3.24.1", - "@smithy/types": "^4.14.1", - "fflate": "0.8.1", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@smithy/middleware-content-length": { + "node_modules/@smithy/eventstream-serde-node": { "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.3.1.tgz", - "integrity": "sha512-l4BUIP+wljW/Ar+0/QcGdmElI9lalrywfzNijXMBG34Z510FRzPyrDLx/blNTZOAm0C4Mvx5t/bf760CZo1ajg==", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.3.1.tgz", + "integrity": "sha512-6Cn4xTNVxn9PWTHSbvf8zmcDhQW8lrLE1Xq5CJgmX6wEvdjS2S0KuE79Aiznv/jx51jpFJ98OuWyE+Bt+oG1MQ==", "license": "Apache-2.0", "dependencies": { "@smithy/core": "^3.24.1", @@ -4108,25 +4403,106 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/middleware-endpoint": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.5.1.tgz", - "integrity": "sha512-qtqu5TS+8Y18ZDkJoiXN5AMW1G4JAg1+xytzpsUvIR5a4EUsgd5HQg12lekEHWpm2TDUmOgg+hBaHK7dvyWdkA==", + "node_modules/@smithy/fetch-http-handler": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.4.1.tgz", + "integrity": "sha512-r7bN6spQ+caZC8AnyvSxkRUb57zt2jhhRw3Z+2Ez8hjq6coIikDBFUUI/+CQ1xx9K6eX1Gx6wUKo4ylU66TIqw==", "license": "Apache-2.0", "dependencies": { "@smithy/core": "^3.24.1", + "@smithy/types": "^4.14.1", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@smithy/middleware-retry": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.6.1.tgz", - "integrity": "sha512-eTaQhxs0rfUuAkL2MSKrH8DTO7YCeAgrdN0B2/RAeuHmXQ+x52dk5qUBsi/jtcqe5LxItgq5AG5tI6Cp8c0sow==", - "license": "Apache-2.0", - "dependencies": { + "node_modules/@smithy/hash-node": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.3.1.tgz", + "integrity": "sha512-u0/zo11mg7yNneoYgTkH4sXwSmcBpbl49o4UNCtQ7hYsXxynsN25KYHmXzqi7TPk5HQL5klGnpU5koOY0O+9hw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.24.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.3.1.tgz", + "integrity": "sha512-cLmwtDoulyZvRepAfyV+3rx5oMvuh51dbE+6En3vGC09j3uVSRt1U4oguNu32ub3soGX0oYtBs8E7S2Q4SxTqg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.24.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-compression": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-compression/-/middleware-compression-4.4.1.tgz", + "integrity": "sha512-p5HLi70K05XqhXHPQEhANMv3xhFAgcz0O11sCd8MZEXI45Y86A5hLEwDNQPbvoHh3U3B+NKdh1vqlsjpiozfXw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.24.1", + "@smithy/types": "^4.14.1", + "fflate": "0.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.3.1.tgz", + "integrity": "sha512-l4BUIP+wljW/Ar+0/QcGdmElI9lalrywfzNijXMBG34Z510FRzPyrDLx/blNTZOAm0C4Mvx5t/bf760CZo1ajg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.24.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.5.1.tgz", + "integrity": "sha512-qtqu5TS+8Y18ZDkJoiXN5AMW1G4JAg1+xytzpsUvIR5a4EUsgd5HQg12lekEHWpm2TDUmOgg+hBaHK7dvyWdkA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.24.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.6.1.tgz", + "integrity": "sha512-eTaQhxs0rfUuAkL2MSKrH8DTO7YCeAgrdN0B2/RAeuHmXQ+x52dk5qUBsi/jtcqe5LxItgq5AG5tI6Cp8c0sow==", + "license": "Apache-2.0", + "dependencies": { "@smithy/core": "^3.24.1", "tslib": "^2.6.2" }, @@ -6855,76 +7231,590 @@ "gopd": "^1.2.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron": { + "version": "36.9.5", + "resolved": "https://registry.npmjs.org/electron/-/electron-36.9.5.tgz", + "integrity": "sha512-1UCss2IqxqujSzg/2jkRjuiT3G+EEXgd6UKB5kUekwQW1LJ6d4QCr8YItfC3Rr9VIGRDJ29eOERmnRNO1Eh+NA==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^22.7.7", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "node_modules/electron-store": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/electron-store/-/electron-store-11.0.2.tgz", + "integrity": "sha512-4VkNRdN+BImL2KcCi41WvAYbh6zLX5AUTi4so68yPqiItjbgTjqpEnGAqasgnG+lB6GuAyUltKwVopp6Uv+gwQ==", + "license": "MIT", + "dependencies": { + "conf": "^15.0.2", + "type-fest": "^5.0.1" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/electron-store/node_modules/type-fest": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.6.0.tgz", + "integrity": "sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA==", + "license": "(MIT OR CC0-1.0)", + "dependencies": { + "tagged-tag": "^1.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.353", + "dev": true, + "license": "ISC" + }, + "node_modules/electron-vite": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/electron-vite/-/electron-vite-5.0.0.tgz", + "integrity": "sha512-OHp/vjdlubNlhNkPkL/+3JD34ii5ov7M0GpuXEVdQeqdQ3ulvVR7Dg/rNBLfS5XPIFwgoBLDf9sjjrL+CuDyRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.4", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "cac": "^6.7.14", + "esbuild": "^0.25.11", + "magic-string": "^0.30.19", + "picocolors": "^1.1.1" + }, + "bin": { + "electron-vite": "bin/electron-vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@swc/core": "^1.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + } + } + }, + "node_modules/electron-vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/electron-vite/node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "node_modules/electron-vite/node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/electron": { - "version": "36.9.5", - "resolved": "https://registry.npmjs.org/electron/-/electron-36.9.5.tgz", - "integrity": "sha512-1UCss2IqxqujSzg/2jkRjuiT3G+EEXgd6UKB5kUekwQW1LJ6d4QCr8YItfC3Rr9VIGRDJ29eOERmnRNO1Eh+NA==", - "hasInstallScript": true, + "node_modules/electron-vite/node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@electron/get": "^2.0.0", - "@types/node": "^22.7.7", - "extract-zip": "^2.0.1" - }, - "bin": { - "electron": "cli.js" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 12.20.55" + "node": ">=18" } }, - "node_modules/electron-store": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/electron-store/-/electron-store-11.0.2.tgz", - "integrity": "sha512-4VkNRdN+BImL2KcCi41WvAYbh6zLX5AUTi4so68yPqiItjbgTjqpEnGAqasgnG+lB6GuAyUltKwVopp6Uv+gwQ==", + "node_modules/electron-vite/node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "conf": "^15.0.2", - "type-fest": "^5.0.1" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/electron-store/node_modules/type-fest": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.6.0.tgz", - "integrity": "sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA==", - "license": "(MIT OR CC0-1.0)", - "dependencies": { - "tagged-tag": "^1.0.0" + "node_modules/electron-vite/node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=20" + "node": ">=18" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" } }, - "node_modules/electron-to-chromium": { - "version": "1.5.353", - "dev": true, - "license": "ISC" - }, "node_modules/electron/node_modules/@types/node": { "version": "22.19.19", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz", @@ -9378,6 +10268,159 @@ "lightningcss-win32-x64-msvc": "1.32.0" } }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/lightningcss-linux-x64-gnu": { "version": "1.32.0", "cpu": [ @@ -9416,6 +10459,48 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", diff --git a/package.json b/package.json index cc1d07b..169bd63 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,10 @@ "scripts" ], "engines": { - "node": ">=20" + "node": ">=22.12.0" + }, + "devDependencies": { + "electron-vite": "^5.0.0" }, "scripts": { "app:dev": "npm run dev -w game-server-manager", @@ -23,6 +26,8 @@ "app:lint:fix": "npm run lint:fix -w game-server-manager", "app:test:e2e": "npm run test:e2e -w @hyveon/web", "app:test:integration": "node app/scripts/embed-tfstate.mjs && npm run build -w @hyveon/desktop-main && npm run test:integration -w @hyveon/web", - "scripts:init-parent": "npm run init-parent -w @hyveon/scripts" + "scripts:init-parent": "npm run init-parent -w @hyveon/scripts", + "desktop:dev": "electron-vite dev", + "desktop:build": "electron-vite build" } }