From 723eefe9d83c36fbe369e33534fd1eec847460e1 Mon Sep 17 00:00:00 2001 From: bubblepipe42 Date: Mon, 29 Sep 2025 11:08:52 +0800 Subject: [PATCH 01/17] electron --- .gitignore | 6 +- electron/README.md | 172 ++++++++++++++++++++++++++++++++++++++++ electron/build.sh | 41 ++++++++++ electron/main.js | 178 ++++++++++++++++++++++++++++++++++++++++++ electron/package.json | 108 +++++++++++++++++++++++++ electron/preload.js | 6 ++ web/package.json | 1 + 7 files changed, 511 insertions(+), 1 deletion(-) create mode 100644 electron/README.md create mode 100755 electron/build.sh create mode 100644 electron/main.js create mode 100644 electron/package.json create mode 100644 electron/preload.js diff --git a/.gitignore b/.gitignore index 1382829fd..570a4385b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,8 @@ web/dist one-api .DS_Store tiktoken_cache -.eslintcache \ No newline at end of file +.eslintcache + +electron/node_modules +electron/dist +electron/package-lock.json \ No newline at end of file diff --git a/electron/README.md b/electron/README.md new file mode 100644 index 000000000..5122a1ba1 --- /dev/null +++ b/electron/README.md @@ -0,0 +1,172 @@ +# New API Electron Desktop App + +This directory contains the Electron wrapper for New API, allowing it to run as a native desktop application on Windows, macOS, and Linux. + +## Architecture + +The Electron app consists of: +- **main.js**: Main process that spawns the Go backend server and creates the application window +- **preload.js**: Preload script for secure context isolation +- **package.json**: Electron dependencies and build configuration + +## Development + +### Prerequisites + +1. Build the Go backend first: +```bash +cd .. +go build -o new-api +``` + +2. Install Electron dependencies: +```bash +cd electron +npm install +``` + +### Running in Development Mode + +```bash +npm start +``` + +This will: +- Start the Go backend on port 3000 +- Open an Electron window pointing to `http://localhost:3000` +- Enable DevTools for debugging + +## Building for Production + +### Quick Build (Current Platform) + +Use the provided build script: +```bash +./build.sh +``` + +This will: +1. Build the frontend (web/dist) +2. Build the Go binary for your platform +3. Package the Electron app + +### Manual Build Steps + +1. Build frontend: +```bash +cd ../web +DISABLE_ESLINT_PLUGIN='true' bun run build +``` + +2. Build backend: +```bash +cd .. +# macOS/Linux +go build -ldflags="-s -w" -o new-api + +# Windows +go build -ldflags="-s -w" -o new-api.exe +``` + +3. Build Electron app: +```bash +cd electron +npm install + +# All platforms +npm run build + +# Or specific platforms +npm run build:mac # macOS (DMG, ZIP) +npm run build:win # Windows (NSIS installer, Portable) +npm run build:linux # Linux (AppImage, DEB) +``` + +### Output + +Built apps are located in `electron/dist/`: +- **macOS**: `.dmg` and `.zip` +- **Windows**: `.exe` installer and portable `.exe` +- **Linux**: `.AppImage` and `.deb` + +## Cross-Platform Building + +To build for other platforms: + +```bash +# From macOS, build Windows app +npm run build:win + +# From macOS, build Linux app +npm run build:linux +``` + +Note: Building macOS apps requires macOS. Building Windows apps with code signing requires Windows. + +## Configuration + +### Port + +The app uses port 3000 by default. To change: + +Edit `electron/main.js`: +```javascript +const PORT = 3000; // Change to your desired port +``` + +### Data Directory + +- **Development**: Uses `data/` in the project root +- **Production**: Uses Electron's `userData` directory: + - macOS: `~/Library/Application Support/New API/data/` + - Windows: `%APPDATA%/New API/data/` + - Linux: `~/.config/New API/data/` + +### Window Size + +Edit `electron/main.js` in the `createWindow()` function: +```javascript +mainWindow = new BrowserWindow({ + width: 1400, // Change width + height: 900, // Change height + // ... +}); +``` + +## Troubleshooting + +### Server fails to start + +Check the console logs in DevTools (Cmd/Ctrl+Shift+I). Common issues: +- Go binary not found (ensure it's built) +- Port 3000 already in use +- Database file permission issues + +### Binary not found in production + +Ensure the Go binary is built before running `electron-builder`: +```bash +go build -o new-api # macOS/Linux +go build -o new-api.exe # Windows +``` + +The binary must be in the project root, not inside `electron/`. + +### Database issues + +If you encounter database errors, delete the data directory and restart: +- Dev: `rm -rf data/` +- Prod: Clear Electron's userData folder (see "Data Directory" above) + +## Icon + +To add a custom icon: +1. Place a 512x512 PNG icon at `electron/icon.png` +2. Rebuild the app with `npm run build` + +## Security + +- Context isolation is enabled +- Node integration is disabled in renderer process +- Only safe APIs are exposed via preload script +- Backend runs as a local subprocess with no external network access by default \ No newline at end of file diff --git a/electron/build.sh b/electron/build.sh new file mode 100755 index 000000000..cef714328 --- /dev/null +++ b/electron/build.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +set -e + +echo "Building New API Electron App..." + +echo "Step 1: Building frontend..." +cd ../web +DISABLE_ESLINT_PLUGIN='true' bun run build +cd ../electron + +echo "Step 2: Building Go backend..." +cd .. + +if [[ "$OSTYPE" == "darwin"* ]]; then + echo "Building for macOS..." + CGO_ENABLED=1 go build -ldflags="-s -w" -o new-api + cd electron + npm install + npm run build:mac +elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + echo "Building for Linux..." + CGO_ENABLED=1 go build -ldflags="-s -w" -o new-api + cd electron + npm install + npm run build:linux +elif [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || "$OSTYPE" == "win32" ]]; then + echo "Building for Windows..." + CGO_ENABLED=1 go build -ldflags="-s -w" -o new-api.exe + cd electron + npm install + npm run build:win +else + echo "Unknown OS, building for current platform..." + CGO_ENABLED=1 go build -ldflags="-s -w" -o new-api + cd electron + npm install + npm run build +fi + +echo "Build complete! Check electron/dist/ for output." \ No newline at end of file diff --git a/electron/main.js b/electron/main.js new file mode 100644 index 000000000..9fb954b88 --- /dev/null +++ b/electron/main.js @@ -0,0 +1,178 @@ +const { app, BrowserWindow, dialog } = require('electron'); +const { spawn } = require('child_process'); +const path = require('path'); +const http = require('http'); +const fs = require('fs'); + +let mainWindow; +let serverProcess; +const PORT = 3000; + +function getBinaryPath() { + const isDev = process.env.NODE_ENV === 'development'; + const platform = process.platform; + + if (isDev) { + const binaryName = platform === 'win32' ? 'new-api.exe' : 'new-api'; + return path.join(__dirname, '..', binaryName); + } + + let binaryName; + switch (platform) { + case 'win32': + binaryName = 'new-api.exe'; + break; + case 'darwin': + binaryName = 'new-api'; + break; + case 'linux': + binaryName = 'new-api'; + break; + default: + binaryName = 'new-api'; + } + + return path.join(process.resourcesPath, 'bin', binaryName); +} + +function startServer() { + return new Promise((resolve, reject) => { + const binaryPath = getBinaryPath(); + const isDev = process.env.NODE_ENV === 'development'; + + console.log('Starting server from:', binaryPath); + + const env = { ...process.env, PORT: PORT.toString() }; + + let dataDir; + if (isDev) { + dataDir = path.join(__dirname, '..', 'data'); + } else { + const userDataPath = app.getPath('userData'); + dataDir = path.join(userDataPath, 'data'); + } + + if (!fs.existsSync(dataDir)) { + fs.mkdirSync(dataDir, { recursive: true }); + } + + env.SQLITE_PATH = path.join(dataDir, 'new-api.db'); + + const workingDir = isDev + ? path.join(__dirname, '..') + : process.resourcesPath; + + serverProcess = spawn(binaryPath, [], { + env, + cwd: workingDir + }); + + serverProcess.stdout.on('data', (data) => { + console.log(`Server: ${data}`); + }); + + serverProcess.stderr.on('data', (data) => { + console.error(`Server Error: ${data}`); + }); + + serverProcess.on('error', (err) => { + console.error('Failed to start server:', err); + reject(err); + }); + + serverProcess.on('close', (code) => { + console.log(`Server process exited with code ${code}`); + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.close(); + } + }); + + waitForServer(resolve, reject); + }); +} + +function waitForServer(resolve, reject, retries = 30) { + if (retries === 0) { + reject(new Error('Server failed to start within timeout')); + return; + } + + const req = http.get(`http://localhost:${PORT}`, (res) => { + console.log('Server is ready'); + resolve(); + }); + + req.on('error', () => { + setTimeout(() => waitForServer(resolve, reject, retries - 1), 1000); + }); + + req.end(); +} + +function createWindow() { + mainWindow = new BrowserWindow({ + width: 1400, + height: 900, + webPreferences: { + preload: path.join(__dirname, 'preload.js'), + nodeIntegration: false, + contextIsolation: true + }, + title: 'New API', + icon: path.join(__dirname, 'icon.png') + }); + + mainWindow.loadURL(`http://localhost:${PORT}`); + + if (process.env.NODE_ENV === 'development') { + mainWindow.webContents.openDevTools(); + } + + mainWindow.on('closed', () => { + mainWindow = null; + }); +} + +app.whenReady().then(async () => { + try { + await startServer(); + createWindow(); + } catch (err) { + console.error('Failed to start application:', err); + dialog.showErrorBox('Startup Error', `Failed to start server: ${err.message}`); + app.quit(); + } +}); + +app.on('window-all-closed', () => { + if (process.platform !== 'darwin') { + app.quit(); + } +}); + +app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) { + createWindow(); + } +}); + +app.on('before-quit', (event) => { + if (serverProcess) { + event.preventDefault(); + + console.log('Shutting down server...'); + serverProcess.kill('SIGTERM'); + + setTimeout(() => { + if (serverProcess) { + serverProcess.kill('SIGKILL'); + } + app.exit(); + }, 5000); + + serverProcess.on('close', () => { + serverProcess = null; + app.exit(); + }); + } +}); \ No newline at end of file diff --git a/electron/package.json b/electron/package.json new file mode 100644 index 000000000..d7fd66100 --- /dev/null +++ b/electron/package.json @@ -0,0 +1,108 @@ +{ + "name": "new-api-electron", + "version": "1.0.0", + "description": "New API - AI Model Gateway Desktop Application", + "main": "main.js", + "scripts": { + "start": "NODE_ENV=development electron .", + "build": "electron-builder", + "build:mac": "electron-builder --mac", + "build:win": "electron-builder --win", + "build:linux": "electron-builder --linux" + }, + "keywords": [ + "ai", + "api", + "gateway", + "openai", + "claude" + ], + "author": "", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/Calcium-Ion/new-api" + }, + "devDependencies": { + "electron": "^28.0.0", + "electron-builder": "^24.9.1" + }, + "build": { + "appId": "com.newapi.desktop", + "productName": "New API", + "publish": null, + "directories": { + "output": "dist" + }, + "files": [ + "main.js", + "preload.js", + "icon.png" + ], + "extraResources": [ + { + "from": "../new-api", + "to": "bin/new-api", + "filter": [ + "**/*" + ] + }, + { + "from": "../new-api.exe", + "to": "bin/new-api.exe", + "filter": [ + "**/*" + ] + } + ], + "mac": { + "category": "public.app-category.developer-tools", + "icon": "icon.png", + "target": [ + "dmg", + "zip" + ], + "extraResources": [ + { + "from": "../new-api", + "to": "bin/new-api" + }, + { + "from": "../web/dist", + "to": "web/dist" + } + ] + }, + "win": { + "icon": "icon.png", + "target": [ + "nsis", + "portable" + ], + "extraResources": [ + { + "from": "../new-api.exe", + "to": "bin/new-api.exe" + } + ] + }, + "linux": { + "icon": "icon.png", + "target": [ + "AppImage", + "deb" + ], + "category": "Development", + "extraResources": [ + { + "from": "../new-api", + "to": "bin/new-api" + } + ] + }, + "nsis": { + "oneClick": false, + "allowToChangeInstallationDirectory": true + } + } +} \ No newline at end of file diff --git a/electron/preload.js b/electron/preload.js new file mode 100644 index 000000000..6d8b6daa0 --- /dev/null +++ b/electron/preload.js @@ -0,0 +1,6 @@ +const { contextBridge } = require('electron'); + +contextBridge.exposeInMainWorld('electron', { + version: process.versions.electron, + platform: process.platform +}); \ No newline at end of file diff --git a/web/package.json b/web/package.json index f014d84b9..b94445f3c 100644 --- a/web/package.json +++ b/web/package.json @@ -10,6 +10,7 @@ "@visactor/react-vchart": "~1.8.8", "@visactor/vchart": "~1.8.8", "@visactor/vchart-semi-theme": "~1.8.8", + "antd": "^5.27.4", "axios": "^0.27.2", "clsx": "^2.1.1", "country-flag-icons": "^1.5.19", From 0046282fb8d968c001a1c63864c17b39ce4d87c8 Mon Sep 17 00:00:00 2001 From: bubblepipe42 Date: Mon, 29 Sep 2025 13:01:07 +0800 Subject: [PATCH 02/17] stash --- electron/create-tray-icon.js | 60 +++++++++++++++++++++++++++++++ electron/entitlements.mac.plist | 18 ++++++++++ electron/main.js | 63 ++++++++++++++++++++++++++++++--- electron/package.json | 5 +++ 4 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 electron/create-tray-icon.js create mode 100644 electron/entitlements.mac.plist diff --git a/electron/create-tray-icon.js b/electron/create-tray-icon.js new file mode 100644 index 000000000..517393b2e --- /dev/null +++ b/electron/create-tray-icon.js @@ -0,0 +1,60 @@ +// Create a simple tray icon for macOS +// Run: node create-tray-icon.js + +const fs = require('fs'); +const { createCanvas } = require('canvas'); + +function createTrayIcon() { + // For macOS, we'll use a Template image (black and white) + // Size should be 22x22 for Retina displays (@2x would be 44x44) + const canvas = createCanvas(22, 22); + const ctx = canvas.getContext('2d'); + + // Clear canvas + ctx.clearRect(0, 0, 22, 22); + + // Draw a simple "API" icon + ctx.fillStyle = '#000000'; + ctx.font = 'bold 10px system-ui'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText('API', 11, 11); + + // Save as PNG + const buffer = canvas.toBuffer('image/png'); + fs.writeFileSync('tray-icon.png', buffer); + + // For Template images on macOS (will adapt to menu bar theme) + fs.writeFileSync('tray-iconTemplate.png', buffer); + fs.writeFileSync('tray-iconTemplate@2x.png', buffer); + + console.log('Tray icon created successfully!'); +} + +// Check if canvas is installed +try { + createTrayIcon(); +} catch (err) { + console.log('Canvas module not installed.'); + console.log('For now, creating a placeholder. Install canvas with: npm install canvas'); + + // Create a minimal 1x1 transparent PNG as placeholder + const minimalPNG = Buffer.from([ + 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, + 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x03, 0x00, 0x00, 0x00, 0x25, 0xDB, 0x56, + 0xCA, 0x00, 0x00, 0x00, 0x03, 0x50, 0x4C, 0x54, + 0x45, 0x00, 0x00, 0x00, 0xA7, 0x7A, 0x3D, 0xDA, + 0x00, 0x00, 0x00, 0x01, 0x74, 0x52, 0x4E, 0x53, + 0x00, 0x40, 0xE6, 0xD8, 0x66, 0x00, 0x00, 0x00, + 0x0A, 0x49, 0x44, 0x41, 0x54, 0x08, 0x1D, 0x62, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x01, 0x0A, 0x2D, 0xCB, 0x59, 0x00, 0x00, + 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, + 0x60, 0x82 + ]); + + fs.writeFileSync('tray-icon.png', minimalPNG); + console.log('Created placeholder tray icon.'); +} \ No newline at end of file diff --git a/electron/entitlements.mac.plist b/electron/entitlements.mac.plist new file mode 100644 index 000000000..a00aebcd0 --- /dev/null +++ b/electron/entitlements.mac.plist @@ -0,0 +1,18 @@ + + + + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.allow-jit + + com.apple.security.cs.disable-library-validation + + com.apple.security.cs.allow-dyld-environment-variables + + com.apple.security.network.client + + com.apple.security.network.server + + + \ No newline at end of file diff --git a/electron/main.js b/electron/main.js index 9fb954b88..50307eac2 100644 --- a/electron/main.js +++ b/electron/main.js @@ -1,4 +1,4 @@ -const { app, BrowserWindow, dialog } = require('electron'); +const { app, BrowserWindow, dialog, Tray, Menu } = require('electron'); const { spawn } = require('child_process'); const path = require('path'); const http = require('http'); @@ -6,6 +6,7 @@ const fs = require('fs'); let mainWindow; let serverProcess; +let tray = null; const PORT = 3000; function getBinaryPath() { @@ -109,6 +110,49 @@ function waitForServer(resolve, reject, retries = 30) { req.end(); } +function createTray() { + tray = new Tray(path.join(__dirname, 'tray-icon.png')); + + const contextMenu = Menu.buildFromTemplate([ + { + label: 'Show New API', + click: () => { + if (mainWindow === null) { + createWindow(); + } else { + mainWindow.show(); + if (process.platform === 'darwin') { + app.dock.show(); + } + } + } + }, + { type: 'separator' }, + { + label: 'Quit', + click: () => { + app.isQuitting = true; + app.quit(); + } + } + ]); + + tray.setToolTip('New API'); + tray.setContextMenu(contextMenu); + + // On macOS, clicking the tray icon shows the menu + tray.on('click', () => { + if (mainWindow === null) { + createWindow(); + } else { + mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show(); + if (mainWindow.isVisible() && process.platform === 'darwin') { + app.dock.show(); + } + } + }); +} + function createWindow() { mainWindow = new BrowserWindow({ width: 1400, @@ -128,6 +172,17 @@ function createWindow() { mainWindow.webContents.openDevTools(); } + // Close to tray instead of quitting + mainWindow.on('close', (event) => { + if (!app.isQuitting) { + event.preventDefault(); + mainWindow.hide(); + if (process.platform === 'darwin') { + app.dock.hide(); + } + } + }); + mainWindow.on('closed', () => { mainWindow = null; }); @@ -136,6 +191,7 @@ function createWindow() { app.whenReady().then(async () => { try { await startServer(); + createTray(); createWindow(); } catch (err) { console.error('Failed to start application:', err); @@ -145,9 +201,8 @@ app.whenReady().then(async () => { }); app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - app.quit(); - } + // Don't quit when window is closed, keep running in tray + // Only quit when explicitly choosing Quit from tray menu }); app.on('activate', () => { diff --git a/electron/package.json b/electron/package.json index d7fd66100..a480b5da0 100644 --- a/electron/package.json +++ b/electron/package.json @@ -58,6 +58,11 @@ "mac": { "category": "public.app-category.developer-tools", "icon": "icon.png", + "identity": null, + "hardenedRuntime": false, + "gatekeeperAssess": false, + "entitlements": "entitlements.mac.plist", + "entitlementsInherit": "entitlements.mac.plist", "target": [ "dmg", "zip" From a57a36a739244878d00bf04acf250d6f4382f046 Mon Sep 17 00:00:00 2001 From: bubblepipe42 Date: Mon, 29 Sep 2025 13:25:22 +0800 Subject: [PATCH 03/17] tray --- electron/main.js | 86 +++++++++++++++--------------- electron/tray-iconTemplate.png | Bin 0 -> 459 bytes electron/tray-iconTemplate@2x.png | Bin 0 -> 754 bytes 3 files changed, 43 insertions(+), 43 deletions(-) create mode 100644 electron/tray-iconTemplate.png create mode 100644 electron/tray-iconTemplate@2x.png diff --git a/electron/main.js b/electron/main.js index 50307eac2..bbe6e7cc8 100644 --- a/electron/main.js +++ b/electron/main.js @@ -110,49 +110,6 @@ function waitForServer(resolve, reject, retries = 30) { req.end(); } -function createTray() { - tray = new Tray(path.join(__dirname, 'tray-icon.png')); - - const contextMenu = Menu.buildFromTemplate([ - { - label: 'Show New API', - click: () => { - if (mainWindow === null) { - createWindow(); - } else { - mainWindow.show(); - if (process.platform === 'darwin') { - app.dock.show(); - } - } - } - }, - { type: 'separator' }, - { - label: 'Quit', - click: () => { - app.isQuitting = true; - app.quit(); - } - } - ]); - - tray.setToolTip('New API'); - tray.setContextMenu(contextMenu); - - // On macOS, clicking the tray icon shows the menu - tray.on('click', () => { - if (mainWindow === null) { - createWindow(); - } else { - mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show(); - if (mainWindow.isVisible() && process.platform === 'darwin') { - app.dock.show(); - } - } - }); -} - function createWindow() { mainWindow = new BrowserWindow({ width: 1400, @@ -188,6 +145,49 @@ function createWindow() { }); } +function createTray() { + tray = new Tray(path.join(__dirname, 'tray-iconTemplate.png')); + + const contextMenu = Menu.buildFromTemplate([ + { + label: 'Show New API', + click: () => { + if (mainWindow === null) { + createWindow(); + } else { + mainWindow.show(); + if (process.platform === 'darwin') { + app.dock.show(); + } + } + } + }, + { type: 'separator' }, + { + label: 'Quit', + click: () => { + app.isQuitting = true; + app.quit(); + } + } + ]); + + tray.setToolTip('New API'); + tray.setContextMenu(contextMenu); + + // On macOS, clicking the tray icon shows the window + tray.on('click', () => { + if (mainWindow === null) { + createWindow(); + } else { + mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show(); + if (mainWindow.isVisible() && process.platform === 'darwin') { + app.dock.show(); + } + } + }); +} + app.whenReady().then(async () => { try { await startServer(); diff --git a/electron/tray-iconTemplate.png b/electron/tray-iconTemplate.png new file mode 100644 index 0000000000000000000000000000000000000000..187741e10d7ad49cae1e1624c3dfb5253355d15c GIT binary patch literal 459 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H3?x5i&EW)6jKx9jPK-BC>eK@{oCO|{#S9GG z!XV7ZFl&wkP_Qw;C&U#sR%fZ>$7zmYc*&kIant>eck|4iehX2gQcmEuz z{F=Cqqha|&@g1y&Q9jxs3q=B%)Lf^Ze_X8e;U;hDvn_g?JpUEm5dvyk4UX$+uyx4kfBSaIWU^~T@O3fm^-Kre+=ySF ztIN7`AEV68qdOf$gj<*MZ%*T%kkyu}&oDVnIL!Bma2BgTrd;A1okE#&RSFl@D1GU% z_B&L@y!aW1fUfGC726WB=3QBK{+fx4&*Zy3b6A)2uj2#x-P6_2Wt~$(69B(4fSCXQ literal 0 HcmV?d00001 diff --git a/electron/tray-iconTemplate@2x.png b/electron/tray-iconTemplate@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d5666a04e55b0233bb3c3981a361d1f61ea575e8 GIT binary patch literal 754 zcmeAS@N?(olHy`uVBq!ia0vp^Iv~u!3?wz9Rv7~+#^NA%C&rs6b?Si}&H|6fVg?3o zVGw3ym^DWND7Z1eC&U#<(-tr?Qf@vs7dImtJ1-9(0~3?yBj?9J6Rk^v{DK+&OR<)| z@c6UW_#^+~Ut2k5J`mR9I#O^({^GUsYC#Th;(3R59yh-|afM>FwWe=t+Uu`f%O0zo zbTf6`a%|?!3}7Hl_H=O!shIP2%JoTy40v4Ms`xd2VN?8a&-(Vi|A()MO1#-%ZT-7L z&gk0Jjf*_W7%Fbs&svwcU*)n&dHZdVBlh_#_`UekvNvo}p7QkU@->g6FIclOTv6Eg zc|qLSGC?(`GfXGWeA4cIDOd1kwf{89m3iFz%O1O3*>V5TQ~94gb*}vMbBs2Q zW&ExqberRQQt>Xci8r^XOuV)>`mf@0_o7!vlo`M4P1sWLY8%UQlLUj~CMP!^4xTL} z6I6R#ra6!68IPUarl{su-p>{?-C4R#e)sXjpv{>g0!qyLYYdkrJuWnmnWx9mvpiTJ zqWo&XncKG(#x>5^6>|8&i3gPhza1FLLb#Xa&G?}A^|$(auBkkNHAU=&arfnkhefSI<14qid^b4TcP^#>`ia1e z6$Z(U>06Q>$?eJ#yS#4&i#4MrQ|P8A+Y8g&B{r+`$G_{6+F|;c$MqZ68sisJ_p0yb t4fNr;^!CD8Vb}Vr(k55u*4>={R(g)PNNv{CrnR7Svd$@?2>^`i{gwa# literal 0 HcmV?d00001 From 050e0221c75576f4e7ce0f84046d60748957d5c6 Mon Sep 17 00:00:00 2001 From: bubblepipe42 Date: Mon, 29 Sep 2025 13:33:41 +0800 Subject: [PATCH 04/17] README --- electron/README.md | 167 +++++++++------------------------------------ 1 file changed, 34 insertions(+), 133 deletions(-) diff --git a/electron/README.md b/electron/README.md index 5122a1ba1..88463b8ae 100644 --- a/electron/README.md +++ b/electron/README.md @@ -1,172 +1,73 @@ # New API Electron Desktop App -This directory contains the Electron wrapper for New API, allowing it to run as a native desktop application on Windows, macOS, and Linux. +This directory contains the Electron wrapper for New API, providing a native desktop application with system tray support for Windows, macOS, and Linux. -## Architecture +## Prerequisites -The Electron app consists of: -- **main.js**: Main process that spawns the Go backend server and creates the application window -- **preload.js**: Preload script for secure context isolation -- **package.json**: Electron dependencies and build configuration +### 1. Go Binary (Required) +The Electron app requires the compiled Go binary to function. You have two options: -## Development - -### Prerequisites - -1. Build the Go backend first: +**Option A: Use existing binary (without Go installed)** ```bash -cd .. -go build -o new-api +# If you have a pre-built binary (e.g., new-api-macos) +cp ../new-api-macos ../new-api ``` -2. Install Electron dependencies: +**Option B: Build from source (requires Go)** +TODO + +### 3. Electron Dependencies ```bash cd electron npm install ``` -### Running in Development Mode +## Development +Run the app in development mode: ```bash npm start ``` This will: - Start the Go backend on port 3000 -- Open an Electron window pointing to `http://localhost:3000` -- Enable DevTools for debugging +- Open an Electron window with DevTools enabled +- Create a system tray icon (menu bar on macOS) +- Store database in `../data/new-api.db` ## Building for Production -### Quick Build (Current Platform) - -Use the provided build script: +### Quick Build ```bash -./build.sh -``` +# Ensure Go binary exists in parent directory +ls ../new-api # Should exist -This will: -1. Build the frontend (web/dist) -2. Build the Go binary for your platform -3. Package the Electron app - -### Manual Build Steps - -1. Build frontend: -```bash -cd ../web -DISABLE_ESLINT_PLUGIN='true' bun run build -``` - -2. Build backend: -```bash -cd .. -# macOS/Linux -go build -ldflags="-s -w" -o new-api - -# Windows -go build -ldflags="-s -w" -o new-api.exe -``` - -3. Build Electron app: -```bash -cd electron -npm install - -# All platforms +# Build for current platform npm run build -# Or specific platforms -npm run build:mac # macOS (DMG, ZIP) -npm run build:win # Windows (NSIS installer, Portable) -npm run build:linux # Linux (AppImage, DEB) +# Platform-specific builds +npm run build:mac # Creates .dmg and .zip +npm run build:win # Creates .exe installer +npm run build:linux # Creates .AppImage and .deb ``` -### Output - -Built apps are located in `electron/dist/`: -- **macOS**: `.dmg` and `.zip` -- **Windows**: `.exe` installer and portable `.exe` -- **Linux**: `.AppImage` and `.deb` - -## Cross-Platform Building - -To build for other platforms: - -```bash -# From macOS, build Windows app -npm run build:win - -# From macOS, build Linux app -npm run build:linux -``` - -Note: Building macOS apps requires macOS. Building Windows apps with code signing requires Windows. +### Build Output +- Built applications are in `electron/dist/` +- macOS: `.dmg` (installer) and `.zip` (portable) +- Windows: `.exe` (installer) and portable exe +- Linux: `.AppImage` and `.deb` ## Configuration ### Port - -The app uses port 3000 by default. To change: - -Edit `electron/main.js`: +Default port is 3000. To change, edit `main.js`: ```javascript -const PORT = 3000; // Change to your desired port +const PORT = 3000; // Change to desired port ``` -### Data Directory - -- **Development**: Uses `data/` in the project root -- **Production**: Uses Electron's `userData` directory: +### Database Location +- **Development**: `../data/new-api.db` (project directory) +- **Production**: - macOS: `~/Library/Application Support/New API/data/` - Windows: `%APPDATA%/New API/data/` - Linux: `~/.config/New API/data/` - -### Window Size - -Edit `electron/main.js` in the `createWindow()` function: -```javascript -mainWindow = new BrowserWindow({ - width: 1400, // Change width - height: 900, // Change height - // ... -}); -``` - -## Troubleshooting - -### Server fails to start - -Check the console logs in DevTools (Cmd/Ctrl+Shift+I). Common issues: -- Go binary not found (ensure it's built) -- Port 3000 already in use -- Database file permission issues - -### Binary not found in production - -Ensure the Go binary is built before running `electron-builder`: -```bash -go build -o new-api # macOS/Linux -go build -o new-api.exe # Windows -``` - -The binary must be in the project root, not inside `electron/`. - -### Database issues - -If you encounter database errors, delete the data directory and restart: -- Dev: `rm -rf data/` -- Prod: Clear Electron's userData folder (see "Data Directory" above) - -## Icon - -To add a custom icon: -1. Place a 512x512 PNG icon at `electron/icon.png` -2. Rebuild the app with `npm run build` - -## Security - -- Context isolation is enabled -- Node integration is disabled in renderer process -- Only safe APIs are exposed via preload script -- Backend runs as a local subprocess with no external network access by default \ No newline at end of file From 7c7f9abd04762da9bf49541c57f56c0eb2f539c0 Mon Sep 17 00:00:00 2001 From: bubblepipe42 Date: Mon, 29 Sep 2025 13:41:17 +0800 Subject: [PATCH 05/17] icon --- electron/icon.png | Bin 0 -> 31262 bytes electron/package.json | 4 +++- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 electron/icon.png diff --git a/electron/icon.png b/electron/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c63ac2d77598af361f898c561ed40938719c8391 GIT binary patch literal 31262 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 Q5b%+eRFbIrXcGMY0IP Date: Tue, 30 Sep 2025 15:55:31 +0800 Subject: [PATCH 06/17] fix build on windows --- electron/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/electron/package.json b/electron/package.json index 21c56d315..cd1d1c46b 100644 --- a/electron/package.json +++ b/electron/package.json @@ -4,7 +4,7 @@ "description": "New API - AI Model Gateway Desktop Application", "main": "main.js", "scripts": { - "start": "NODE_ENV=development electron .", + "start": "set NODE_ENV=development&& electron .", "build": "electron-builder", "build:mac": "electron-builder --mac", "build:win": "electron-builder --win", From 922ecef31e2aca2b8eff365a5f07c309f335dcf0 Mon Sep 17 00:00:00 2001 From: bubblepipe Date: Tue, 30 Sep 2025 16:41:41 +0800 Subject: [PATCH 07/17] fix wn --- electron/package.json | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/electron/package.json b/electron/package.json index cd1d1c46b..0eb07afd9 100644 --- a/electron/package.json +++ b/electron/package.json @@ -41,22 +41,6 @@ "tray-iconTemplate.png", "tray-iconTemplate@2x.png" ], - "extraResources": [ - { - "from": "../new-api", - "to": "bin/new-api", - "filter": [ - "**/*" - ] - }, - { - "from": "../new-api.exe", - "to": "bin/new-api.exe", - "filter": [ - "**/*" - ] - } - ], "mac": { "category": "public.app-category.developer-tools", "icon": "icon.png", From 15b21c075f1007bfce7ccfb514ff694cf288762c Mon Sep 17 00:00:00 2001 From: bubblepipe42 Date: Thu, 2 Oct 2025 14:55:06 +0800 Subject: [PATCH 08/17] windows tray icon --- electron/main.js | 8 +++++++- electron/package.json | 3 ++- electron/tray-icon-windows.png | Bin 0 -> 1203 bytes 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 electron/tray-icon-windows.png diff --git a/electron/main.js b/electron/main.js index bbe6e7cc8..9a8534f3a 100644 --- a/electron/main.js +++ b/electron/main.js @@ -146,7 +146,13 @@ function createWindow() { } function createTray() { - tray = new Tray(path.join(__dirname, 'tray-iconTemplate.png')); + // Use template icon for macOS (black with transparency, auto-adapts to theme) + // Use colored icon for Windows + const trayIconPath = process.platform === 'darwin' + ? path.join(__dirname, 'tray-iconTemplate.png') + : path.join(__dirname, 'tray-icon-windows.png'); + + tray = new Tray(trayIconPath); const contextMenu = Menu.buildFromTemplate([ { diff --git a/electron/package.json b/electron/package.json index 0eb07afd9..9cdf3d12f 100644 --- a/electron/package.json +++ b/electron/package.json @@ -39,7 +39,8 @@ "preload.js", "icon.png", "tray-iconTemplate.png", - "tray-iconTemplate@2x.png" + "tray-iconTemplate@2x.png", + "tray-icon-windows.png" ], "mac": { "category": "public.app-category.developer-tools", diff --git a/electron/tray-icon-windows.png b/electron/tray-icon-windows.png new file mode 100644 index 0000000000000000000000000000000000000000..57df8ead031450e7787bb01bec1c0be0e906f0f6 GIT binary patch literal 1203 zcmZWoX;f236n;rvfI{xH-x6O3{njggI5v=Wc$#U=e%R68bWBN8VMHfzbW1tZ*yONWT$X`dbxkNYM3rj|%}VT7BC zju^x>I%DJ=G98V%s;iP<%|iUxDZSIIx_b|ieoi0Ip~))Kf2u-R3u-c5ZIY8o6}p5< z-JMVz6Wt?I=17^YJlS~ixZ%V}17{rB-G_o`(#yJ50S**iFKUEa<)yj<_ceHIzkjDD zUts`tw=o24cp2aF*o(+5(m(egou(G;(Iq13PaYl51sxuz3U1aq zEU1l#n*gtravdiADZD{T%Jeq6B`l`b4qf_e040+D0(xyEHpwS%gkc!KmX3to(t18a z&tw?Mw0|S&wSWa4`y{dsClTLn zlt_66Zt?CxiTDvfkTtJ9@KCdT7$FiTK(R!%+G-dB_JTaauiHtlpHaaB4T!&E2q9Dd z0qM#*z05K62dzD_6!fD8pf$+}02NgBe5!%{Qhim7^?8w?5V&;EBsWDgXhD5TvW>Qy z#btJIv-6Ca%y@G!^R?`(-ahxtb?{d1%Yp+BLe&3T*NQi`*Ka+mfiS&Qofu876Fph< zFNQ}BafQFFxH!V0p@MT^Gj>R*KD%9v)xq!A*tDimtIvnhG1}P3(cD7;sT|v4LAAev ziEYDnKityNL$eP~p+33a*gzk&9z3=sg)+=i;_1iPW5>-X>U-W)6h-bTj0&Ly^Fbdf z7-Ue5^r8cuqUNx`r^B!5#}nF0OxLKp%1f2tW5E0Ucp=$UVwjQ4juT68ugj#_?P47W(#k5m*34;x)Qo3<`Uja=OtMc=kLnFp3iS9+q2e8;1>k<4h)RH7iGtRY`dO$ zTbEVCWw#TjEUle}Ec~5YAjO8_{I6LomSzJ(*8Y{Mlg?oLjvz=*wM*Re+}z;-<=Gf! z_%{{ZN})=n>SXe}oJAs!roHSMDfiR@hs}OoTJ3$9&kq}2^YqJCt7f<{63LakYNc;1 zk?HBVo^kJNVc`>VzM|;6+S<0v#+3!@I|Cv*ohs*i;A zH%2+!N1NzR?Mj0}1pG@9xPn!8)74RA6}>V(F45+3h!PfVcJCa#$djf$NMNp$TDyE3 kyV0{HeVn Date: Fri, 3 Oct 2025 13:23:56 +0800 Subject: [PATCH 09/17] action --- .github/workflows/electron-build.yml | 103 +++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 .github/workflows/electron-build.yml diff --git a/.github/workflows/electron-build.yml b/.github/workflows/electron-build.yml new file mode 100644 index 000000000..c7b562931 --- /dev/null +++ b/.github/workflows/electron-build.yml @@ -0,0 +1,103 @@ +name: Build Electron App + +on: + push: + tags: + - 'v*.*.*' # Triggers on version tags like v1.0.0 + workflow_dispatch: # Allows manual triggering + +jobs: + build: + strategy: + matrix: + os: [macos-latest, windows-latest] + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: '1.21' + + - name: Build frontend + run: | + cd web + npm install --legacy-peer-deps + npm run build + env: + DISABLE_ESLINT_PLUGIN: 'true' + + - name: Build Go binary (darwin/Linux) + if: runner.os != 'Windows' + run: | + go build -ldflags="-s -w" -o new-api + + - name: Build Go binary (Windows) + if: runner.os == 'Windows' + run: | + go build -ldflags="-s -w" -o new-api.exe + + - name: Install Electron dependencies + run: | + cd electron + npm install + + - name: Build Electron app (macOS) + if: runner.os == 'macOS' + run: | + cd electron + npm run build:mac + env: + CSC_IDENTITY_AUTO_DISCOVERY: false # Skip code signing + + - name: Build Electron app (Windows) + if: runner.os == 'Windows' + run: | + cd electron + npm run build:win + + - name: Upload artifacts (macOS) + if: runner.os == 'macOS' + uses: actions/upload-artifact@v4 + with: + name: darwin-build + path: | + electron/dist/*.dmg + electron/dist/*.zip + + - name: Upload artifacts (Windows) + if: runner.os == 'Windows' + uses: actions/upload-artifact@v4 + with: + name: windows-build + path: | + electron/dist/*.exe + + release: + needs: build + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/') + + steps: + - name: Download all artifacts + uses: actions/download-artifact@v4 + + - name: Create Release + uses: softprops/action-gh-release@v1 + with: + files: | + darwin-build/* + windows-build/* + draft: false + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 93e30703d4a19a54a38373a47665b8573058bd4c Mon Sep 17 00:00:00 2001 From: bubblepipe42 Date: Fri, 3 Oct 2025 13:55:19 +0800 Subject: [PATCH 10/17] action --- .github/workflows/electron-build.yml | 104 ++++++++++++ .gitignore | 6 +- electron/README.md | 73 ++++++++ electron/build.sh | 41 +++++ electron/create-tray-icon.js | 60 +++++++ electron/entitlements.mac.plist | 18 ++ electron/icon.png | Bin 0 -> 31262 bytes electron/main.js | 239 +++++++++++++++++++++++++++ electron/package.json | 100 +++++++++++ electron/preload.js | 6 + electron/tray-icon-windows.png | Bin 0 -> 1203 bytes electron/tray-iconTemplate.png | Bin 0 -> 459 bytes electron/tray-iconTemplate@2x.png | Bin 0 -> 754 bytes web/package.json | 1 + 14 files changed, 647 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/electron-build.yml create mode 100644 electron/README.md create mode 100755 electron/build.sh create mode 100644 electron/create-tray-icon.js create mode 100644 electron/entitlements.mac.plist create mode 100644 electron/icon.png create mode 100644 electron/main.js create mode 100644 electron/package.json create mode 100644 electron/preload.js create mode 100644 electron/tray-icon-windows.png create mode 100644 electron/tray-iconTemplate.png create mode 100644 electron/tray-iconTemplate@2x.png diff --git a/.github/workflows/electron-build.yml b/.github/workflows/electron-build.yml new file mode 100644 index 000000000..b274db857 --- /dev/null +++ b/.github/workflows/electron-build.yml @@ -0,0 +1,104 @@ +name: Build Electron App + +on: + push: + tags: + - 'v*.*.*' # Triggers on version tags like v1.0.0 + workflow_dispatch: # Allows manual triggering + +jobs: + build: + strategy: + matrix: + os: [macos-latest, windows-latest] + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: '1.21' + + - name: Build frontend + run: | + cd web + npm install --legacy-peer-deps + npm run build + env: + DISABLE_ESLINT_PLUGIN: 'true' + NODE_OPTIONS: '--max_old_space_size=4096' + + - name: Build Go binary (macos/Linux) + if: runner.os != 'Windows' + run: | + go build -ldflags="-s -w" -o new-api + + - name: Build Go binary (Windows) + if: runner.os == 'Windows' + run: | + go build -ldflags="-s -w" -o new-api.exe + + - name: Install Electron dependencies + run: | + cd electron + npm install + + - name: Build Electron app (macOS) + if: runner.os == 'macOS' + run: | + cd electron + npm run build:mac + env: + CSC_IDENTITY_AUTO_DISCOVERY: false # Skip code signing + + - name: Build Electron app (Windows) + if: runner.os == 'Windows' + run: | + cd electron + npm run build:win + + - name: Upload artifacts (macOS) + if: runner.os == 'macOS' + uses: actions/upload-artifact@v4 + with: + name: macos-build + path: | + electron/dist/*.dmg + electron/dist/*.zip + + - name: Upload artifacts (Windows) + if: runner.os == 'Windows' + uses: actions/upload-artifact@v4 + with: + name: windows-build + path: | + electron/dist/*.exe + + release: + needs: build + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/') + + steps: + - name: Download all artifacts + uses: actions/download-artifact@v4 + + - name: Create Release + uses: softprops/action-gh-release@v1 + with: + files: | + macos-build/* + windows-build/* + draft: false + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1382829fd..570a4385b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,8 @@ web/dist one-api .DS_Store tiktoken_cache -.eslintcache \ No newline at end of file +.eslintcache + +electron/node_modules +electron/dist +electron/package-lock.json \ No newline at end of file diff --git a/electron/README.md b/electron/README.md new file mode 100644 index 000000000..88463b8ae --- /dev/null +++ b/electron/README.md @@ -0,0 +1,73 @@ +# New API Electron Desktop App + +This directory contains the Electron wrapper for New API, providing a native desktop application with system tray support for Windows, macOS, and Linux. + +## Prerequisites + +### 1. Go Binary (Required) +The Electron app requires the compiled Go binary to function. You have two options: + +**Option A: Use existing binary (without Go installed)** +```bash +# If you have a pre-built binary (e.g., new-api-macos) +cp ../new-api-macos ../new-api +``` + +**Option B: Build from source (requires Go)** +TODO + +### 3. Electron Dependencies +```bash +cd electron +npm install +``` + +## Development + +Run the app in development mode: +```bash +npm start +``` + +This will: +- Start the Go backend on port 3000 +- Open an Electron window with DevTools enabled +- Create a system tray icon (menu bar on macOS) +- Store database in `../data/new-api.db` + +## Building for Production + +### Quick Build +```bash +# Ensure Go binary exists in parent directory +ls ../new-api # Should exist + +# Build for current platform +npm run build + +# Platform-specific builds +npm run build:mac # Creates .dmg and .zip +npm run build:win # Creates .exe installer +npm run build:linux # Creates .AppImage and .deb +``` + +### Build Output +- Built applications are in `electron/dist/` +- macOS: `.dmg` (installer) and `.zip` (portable) +- Windows: `.exe` (installer) and portable exe +- Linux: `.AppImage` and `.deb` + +## Configuration + +### Port +Default port is 3000. To change, edit `main.js`: +```javascript +const PORT = 3000; // Change to desired port +``` + +### Database Location +- **Development**: `../data/new-api.db` (project directory) +- **Production**: + - macOS: `~/Library/Application Support/New API/data/` + - Windows: `%APPDATA%/New API/data/` + - Linux: `~/.config/New API/data/` diff --git a/electron/build.sh b/electron/build.sh new file mode 100755 index 000000000..cef714328 --- /dev/null +++ b/electron/build.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +set -e + +echo "Building New API Electron App..." + +echo "Step 1: Building frontend..." +cd ../web +DISABLE_ESLINT_PLUGIN='true' bun run build +cd ../electron + +echo "Step 2: Building Go backend..." +cd .. + +if [[ "$OSTYPE" == "darwin"* ]]; then + echo "Building for macOS..." + CGO_ENABLED=1 go build -ldflags="-s -w" -o new-api + cd electron + npm install + npm run build:mac +elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + echo "Building for Linux..." + CGO_ENABLED=1 go build -ldflags="-s -w" -o new-api + cd electron + npm install + npm run build:linux +elif [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || "$OSTYPE" == "win32" ]]; then + echo "Building for Windows..." + CGO_ENABLED=1 go build -ldflags="-s -w" -o new-api.exe + cd electron + npm install + npm run build:win +else + echo "Unknown OS, building for current platform..." + CGO_ENABLED=1 go build -ldflags="-s -w" -o new-api + cd electron + npm install + npm run build +fi + +echo "Build complete! Check electron/dist/ for output." \ No newline at end of file diff --git a/electron/create-tray-icon.js b/electron/create-tray-icon.js new file mode 100644 index 000000000..517393b2e --- /dev/null +++ b/electron/create-tray-icon.js @@ -0,0 +1,60 @@ +// Create a simple tray icon for macOS +// Run: node create-tray-icon.js + +const fs = require('fs'); +const { createCanvas } = require('canvas'); + +function createTrayIcon() { + // For macOS, we'll use a Template image (black and white) + // Size should be 22x22 for Retina displays (@2x would be 44x44) + const canvas = createCanvas(22, 22); + const ctx = canvas.getContext('2d'); + + // Clear canvas + ctx.clearRect(0, 0, 22, 22); + + // Draw a simple "API" icon + ctx.fillStyle = '#000000'; + ctx.font = 'bold 10px system-ui'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText('API', 11, 11); + + // Save as PNG + const buffer = canvas.toBuffer('image/png'); + fs.writeFileSync('tray-icon.png', buffer); + + // For Template images on macOS (will adapt to menu bar theme) + fs.writeFileSync('tray-iconTemplate.png', buffer); + fs.writeFileSync('tray-iconTemplate@2x.png', buffer); + + console.log('Tray icon created successfully!'); +} + +// Check if canvas is installed +try { + createTrayIcon(); +} catch (err) { + console.log('Canvas module not installed.'); + console.log('For now, creating a placeholder. Install canvas with: npm install canvas'); + + // Create a minimal 1x1 transparent PNG as placeholder + const minimalPNG = Buffer.from([ + 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, + 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x03, 0x00, 0x00, 0x00, 0x25, 0xDB, 0x56, + 0xCA, 0x00, 0x00, 0x00, 0x03, 0x50, 0x4C, 0x54, + 0x45, 0x00, 0x00, 0x00, 0xA7, 0x7A, 0x3D, 0xDA, + 0x00, 0x00, 0x00, 0x01, 0x74, 0x52, 0x4E, 0x53, + 0x00, 0x40, 0xE6, 0xD8, 0x66, 0x00, 0x00, 0x00, + 0x0A, 0x49, 0x44, 0x41, 0x54, 0x08, 0x1D, 0x62, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x01, 0x0A, 0x2D, 0xCB, 0x59, 0x00, 0x00, + 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, + 0x60, 0x82 + ]); + + fs.writeFileSync('tray-icon.png', minimalPNG); + console.log('Created placeholder tray icon.'); +} \ No newline at end of file diff --git a/electron/entitlements.mac.plist b/electron/entitlements.mac.plist new file mode 100644 index 000000000..a00aebcd0 --- /dev/null +++ b/electron/entitlements.mac.plist @@ -0,0 +1,18 @@ + + + + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.allow-jit + + com.apple.security.cs.disable-library-validation + + com.apple.security.cs.allow-dyld-environment-variables + + com.apple.security.network.client + + com.apple.security.network.server + + + \ No newline at end of file diff --git a/electron/icon.png b/electron/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c63ac2d77598af361f898c561ed40938719c8391 GIT binary patch literal 31262 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 Q5b%+eRFbIrXcGMY0IP { + const binaryPath = getBinaryPath(); + const isDev = process.env.NODE_ENV === 'development'; + + console.log('Starting server from:', binaryPath); + + const env = { ...process.env, PORT: PORT.toString() }; + + let dataDir; + if (isDev) { + dataDir = path.join(__dirname, '..', 'data'); + } else { + const userDataPath = app.getPath('userData'); + dataDir = path.join(userDataPath, 'data'); + } + + if (!fs.existsSync(dataDir)) { + fs.mkdirSync(dataDir, { recursive: true }); + } + + env.SQLITE_PATH = path.join(dataDir, 'new-api.db'); + + const workingDir = isDev + ? path.join(__dirname, '..') + : process.resourcesPath; + + serverProcess = spawn(binaryPath, [], { + env, + cwd: workingDir + }); + + serverProcess.stdout.on('data', (data) => { + console.log(`Server: ${data}`); + }); + + serverProcess.stderr.on('data', (data) => { + console.error(`Server Error: ${data}`); + }); + + serverProcess.on('error', (err) => { + console.error('Failed to start server:', err); + reject(err); + }); + + serverProcess.on('close', (code) => { + console.log(`Server process exited with code ${code}`); + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.close(); + } + }); + + waitForServer(resolve, reject); + }); +} + +function waitForServer(resolve, reject, retries = 30) { + if (retries === 0) { + reject(new Error('Server failed to start within timeout')); + return; + } + + const req = http.get(`http://localhost:${PORT}`, (res) => { + console.log('Server is ready'); + resolve(); + }); + + req.on('error', () => { + setTimeout(() => waitForServer(resolve, reject, retries - 1), 1000); + }); + + req.end(); +} + +function createWindow() { + mainWindow = new BrowserWindow({ + width: 1400, + height: 900, + webPreferences: { + preload: path.join(__dirname, 'preload.js'), + nodeIntegration: false, + contextIsolation: true + }, + title: 'New API', + icon: path.join(__dirname, 'icon.png') + }); + + mainWindow.loadURL(`http://localhost:${PORT}`); + + if (process.env.NODE_ENV === 'development') { + mainWindow.webContents.openDevTools(); + } + + // Close to tray instead of quitting + mainWindow.on('close', (event) => { + if (!app.isQuitting) { + event.preventDefault(); + mainWindow.hide(); + if (process.platform === 'darwin') { + app.dock.hide(); + } + } + }); + + mainWindow.on('closed', () => { + mainWindow = null; + }); +} + +function createTray() { + // Use template icon for macOS (black with transparency, auto-adapts to theme) + // Use colored icon for Windows + const trayIconPath = process.platform === 'darwin' + ? path.join(__dirname, 'tray-iconTemplate.png') + : path.join(__dirname, 'tray-icon-windows.png'); + + tray = new Tray(trayIconPath); + + const contextMenu = Menu.buildFromTemplate([ + { + label: 'Show New API', + click: () => { + if (mainWindow === null) { + createWindow(); + } else { + mainWindow.show(); + if (process.platform === 'darwin') { + app.dock.show(); + } + } + } + }, + { type: 'separator' }, + { + label: 'Quit', + click: () => { + app.isQuitting = true; + app.quit(); + } + } + ]); + + tray.setToolTip('New API'); + tray.setContextMenu(contextMenu); + + // On macOS, clicking the tray icon shows the window + tray.on('click', () => { + if (mainWindow === null) { + createWindow(); + } else { + mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show(); + if (mainWindow.isVisible() && process.platform === 'darwin') { + app.dock.show(); + } + } + }); +} + +app.whenReady().then(async () => { + try { + await startServer(); + createTray(); + createWindow(); + } catch (err) { + console.error('Failed to start application:', err); + dialog.showErrorBox('Startup Error', `Failed to start server: ${err.message}`); + app.quit(); + } +}); + +app.on('window-all-closed', () => { + // Don't quit when window is closed, keep running in tray + // Only quit when explicitly choosing Quit from tray menu +}); + +app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) { + createWindow(); + } +}); + +app.on('before-quit', (event) => { + if (serverProcess) { + event.preventDefault(); + + console.log('Shutting down server...'); + serverProcess.kill('SIGTERM'); + + setTimeout(() => { + if (serverProcess) { + serverProcess.kill('SIGKILL'); + } + app.exit(); + }, 5000); + + serverProcess.on('close', () => { + serverProcess = null; + app.exit(); + }); + } +}); \ No newline at end of file diff --git a/electron/package.json b/electron/package.json new file mode 100644 index 000000000..9cdf3d12f --- /dev/null +++ b/electron/package.json @@ -0,0 +1,100 @@ +{ + "name": "new-api-electron", + "version": "1.0.0", + "description": "New API - AI Model Gateway Desktop Application", + "main": "main.js", + "scripts": { + "start": "set NODE_ENV=development&& electron .", + "build": "electron-builder", + "build:mac": "electron-builder --mac", + "build:win": "electron-builder --win", + "build:linux": "electron-builder --linux" + }, + "keywords": [ + "ai", + "api", + "gateway", + "openai", + "claude" + ], + "author": "", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/Calcium-Ion/new-api" + }, + "devDependencies": { + "electron": "^28.0.0", + "electron-builder": "^24.9.1" + }, + "build": { + "appId": "com.newapi.desktop", + "productName": "New API", + "publish": null, + "directories": { + "output": "dist" + }, + "files": [ + "main.js", + "preload.js", + "icon.png", + "tray-iconTemplate.png", + "tray-iconTemplate@2x.png", + "tray-icon-windows.png" + ], + "mac": { + "category": "public.app-category.developer-tools", + "icon": "icon.png", + "identity": null, + "hardenedRuntime": false, + "gatekeeperAssess": false, + "entitlements": "entitlements.mac.plist", + "entitlementsInherit": "entitlements.mac.plist", + "target": [ + "dmg", + "zip" + ], + "extraResources": [ + { + "from": "../new-api", + "to": "bin/new-api" + }, + { + "from": "../web/dist", + "to": "web/dist" + } + ] + }, + "win": { + "icon": "icon.png", + "target": [ + "nsis", + "portable" + ], + "extraResources": [ + { + "from": "../new-api.exe", + "to": "bin/new-api.exe" + } + ] + }, + "linux": { + "icon": "icon.png", + "target": [ + "AppImage", + "deb" + ], + "category": "Development", + "extraResources": [ + { + "from": "../new-api", + "to": "bin/new-api" + } + ] + }, + "nsis": { + "oneClick": false, + "allowToChangeInstallationDirectory": true + } + } +} \ No newline at end of file diff --git a/electron/preload.js b/electron/preload.js new file mode 100644 index 000000000..6d8b6daa0 --- /dev/null +++ b/electron/preload.js @@ -0,0 +1,6 @@ +const { contextBridge } = require('electron'); + +contextBridge.exposeInMainWorld('electron', { + version: process.versions.electron, + platform: process.platform +}); \ No newline at end of file diff --git a/electron/tray-icon-windows.png b/electron/tray-icon-windows.png new file mode 100644 index 0000000000000000000000000000000000000000..57df8ead031450e7787bb01bec1c0be0e906f0f6 GIT binary patch literal 1203 zcmZWoX;f236n;rvfI{xH-x6O3{njggI5v=Wc$#U=e%R68bWBN8VMHfzbW1tZ*yONWT$X`dbxkNYM3rj|%}VT7BC zju^x>I%DJ=G98V%s;iP<%|iUxDZSIIx_b|ieoi0Ip~))Kf2u-R3u-c5ZIY8o6}p5< z-JMVz6Wt?I=17^YJlS~ixZ%V}17{rB-G_o`(#yJ50S**iFKUEa<)yj<_ceHIzkjDD zUts`tw=o24cp2aF*o(+5(m(egou(G;(Iq13PaYl51sxuz3U1aq zEU1l#n*gtravdiADZD{T%Jeq6B`l`b4qf_e040+D0(xyEHpwS%gkc!KmX3to(t18a z&tw?Mw0|S&wSWa4`y{dsClTLn zlt_66Zt?CxiTDvfkTtJ9@KCdT7$FiTK(R!%+G-dB_JTaauiHtlpHaaB4T!&E2q9Dd z0qM#*z05K62dzD_6!fD8pf$+}02NgBe5!%{Qhim7^?8w?5V&;EBsWDgXhD5TvW>Qy z#btJIv-6Ca%y@G!^R?`(-ahxtb?{d1%Yp+BLe&3T*NQi`*Ka+mfiS&Qofu876Fph< zFNQ}BafQFFxH!V0p@MT^Gj>R*KD%9v)xq!A*tDimtIvnhG1}P3(cD7;sT|v4LAAev ziEYDnKityNL$eP~p+33a*gzk&9z3=sg)+=i;_1iPW5>-X>U-W)6h-bTj0&Ly^Fbdf z7-Ue5^r8cuqUNx`r^B!5#}nF0OxLKp%1f2tW5E0Ucp=$UVwjQ4juT68ugj#_?P47W(#k5m*34;x)Qo3<`Uja=OtMc=kLnFp3iS9+q2e8;1>k<4h)RH7iGtRY`dO$ zTbEVCWw#TjEUle}Ec~5YAjO8_{I6LomSzJ(*8Y{Mlg?oLjvz=*wM*Re+}z;-<=Gf! z_%{{ZN})=n>SXe}oJAs!roHSMDfiR@hs}OoTJ3$9&kq}2^YqJCt7f<{63LakYNc;1 zk?HBVo^kJNVc`>VzM|;6+S<0v#+3!@I|Cv*ohs*i;A zH%2+!N1NzR?Mj0}1pG@9xPn!8)74RA6}>V(F45+3h!PfVcJCa#$djf$NMNp$TDyE3 kyV0{HeVneK@{oCO|{#S9GG z!XV7ZFl&wkP_Qw;C&U#sR%fZ>$7zmYc*&kIant>eck|4iehX2gQcmEuz z{F=Cqqha|&@g1y&Q9jxs3q=B%)Lf^Ze_X8e;U;hDvn_g?JpUEm5dvyk4UX$+uyx4kfBSaIWU^~T@O3fm^-Kre+=ySF ztIN7`AEV68qdOf$gj<*MZ%*T%kkyu}&oDVnIL!Bma2BgTrd;A1okE#&RSFl@D1GU% z_B&L@y!aW1fUfGC726WB=3QBK{+fx4&*Zy3b6A)2uj2#x-P6_2Wt~$(69B(4fSCXQ literal 0 HcmV?d00001 diff --git a/electron/tray-iconTemplate@2x.png b/electron/tray-iconTemplate@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d5666a04e55b0233bb3c3981a361d1f61ea575e8 GIT binary patch literal 754 zcmeAS@N?(olHy`uVBq!ia0vp^Iv~u!3?wz9Rv7~+#^NA%C&rs6b?Si}&H|6fVg?3o zVGw3ym^DWND7Z1eC&U#<(-tr?Qf@vs7dImtJ1-9(0~3?yBj?9J6Rk^v{DK+&OR<)| z@c6UW_#^+~Ut2k5J`mR9I#O^({^GUsYC#Th;(3R59yh-|afM>FwWe=t+Uu`f%O0zo zbTf6`a%|?!3}7Hl_H=O!shIP2%JoTy40v4Ms`xd2VN?8a&-(Vi|A()MO1#-%ZT-7L z&gk0Jjf*_W7%Fbs&svwcU*)n&dHZdVBlh_#_`UekvNvo}p7QkU@->g6FIclOTv6Eg zc|qLSGC?(`GfXGWeA4cIDOd1kwf{89m3iFz%O1O3*>V5TQ~94gb*}vMbBs2Q zW&ExqberRQQt>Xci8r^XOuV)>`mf@0_o7!vlo`M4P1sWLY8%UQlLUj~CMP!^4xTL} z6I6R#ra6!68IPUarl{su-p>{?-C4R#e)sXjpv{>g0!qyLYYdkrJuWnmnWx9mvpiTJ zqWo&XncKG(#x>5^6>|8&i3gPhza1FLLb#Xa&G?}A^|$(auBkkNHAU=&arfnkhefSI<14qid^b4TcP^#>`ia1e z6$Z(U>06Q>$?eJ#yS#4&i#4MrQ|P8A+Y8g&B{r+`$G_{6+F|;c$MqZ68sisJ_p0yb t4fNr;^!CD8Vb}Vr(k55u*4>={R(g)PNNv{CrnR7Svd$@?2>^`i{gwa# literal 0 HcmV?d00001 diff --git a/web/package.json b/web/package.json index f014d84b9..b94445f3c 100644 --- a/web/package.json +++ b/web/package.json @@ -10,6 +10,7 @@ "@visactor/react-vchart": "~1.8.8", "@visactor/vchart": "~1.8.8", "@visactor/vchart-semi-theme": "~1.8.8", + "antd": "^5.27.4", "axios": "^0.27.2", "clsx": "^2.1.1", "country-flag-icons": "^1.5.19", From d2492d2af963b391faf6b61f128bb6242f6c4ea4 Mon Sep 17 00:00:00 2001 From: bubblepipe42 Date: Fri, 3 Oct 2025 14:28:29 +0800 Subject: [PATCH 11/17] fix deps --- web/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/web/package.json b/web/package.json index b94445f3c..f014d84b9 100644 --- a/web/package.json +++ b/web/package.json @@ -10,7 +10,6 @@ "@visactor/react-vchart": "~1.8.8", "@visactor/vchart": "~1.8.8", "@visactor/vchart-semi-theme": "~1.8.8", - "antd": "^5.27.4", "axios": "^0.27.2", "clsx": "^2.1.1", "country-flag-icons": "^1.5.19", From 8026e5142ba9178f866d369dd6715adc98db0c43 Mon Sep 17 00:00:00 2001 From: bubblepipe42 Date: Fri, 3 Oct 2025 14:30:48 +0800 Subject: [PATCH 12/17] fix deps --- web/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/web/package.json b/web/package.json index b94445f3c..f014d84b9 100644 --- a/web/package.json +++ b/web/package.json @@ -10,7 +10,6 @@ "@visactor/react-vchart": "~1.8.8", "@visactor/vchart": "~1.8.8", "@visactor/vchart-semi-theme": "~1.8.8", - "antd": "^5.27.4", "axios": "^0.27.2", "clsx": "^2.1.1", "country-flag-icons": "^1.5.19", From 3da7cebec67b50c392a09fb7b7a3554af53fc2a0 Mon Sep 17 00:00:00 2001 From: CaIon Date: Sun, 5 Oct 2025 15:44:00 +0800 Subject: [PATCH 13/17] =?UTF-8?q?feat:=20=E9=98=B2=E5=91=86=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + electron/main.js | 294 +++++++++++++++++++++++++++++++++++++++++- electron/package.json | 11 +- electron/preload.js | 4 +- 4 files changed, 298 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 570a4385b..bc0b14579 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ logs web/dist .env one-api +new-api .DS_Store tiktoken_cache .eslintcache diff --git a/electron/main.js b/electron/main.js index 9a8534f3a..82f954f00 100644 --- a/electron/main.js +++ b/electron/main.js @@ -1,4 +1,4 @@ -const { app, BrowserWindow, dialog, Tray, Menu } = require('electron'); +const { app, BrowserWindow, dialog, Tray, Menu, shell } = require('electron'); const { spawn } = require('child_process'); const path = require('path'); const http = require('http'); @@ -7,8 +7,145 @@ const fs = require('fs'); let mainWindow; let serverProcess; let tray = null; +let serverErrorLogs = []; const PORT = 3000; +// 保存日志到文件并打开 +function saveAndOpenErrorLog() { + try { + const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); + const logFileName = `new-api-crash-${timestamp}.log`; + const logDir = app.getPath('logs'); + const logFilePath = path.join(logDir, logFileName); + + // 确保日志目录存在 + if (!fs.existsSync(logDir)) { + fs.mkdirSync(logDir, { recursive: true }); + } + + // 写入日志 + const logContent = `New API 崩溃日志 +生成时间: ${new Date().toLocaleString('zh-CN')} +平台: ${process.platform} +架构: ${process.arch} +应用版本: ${app.getVersion()} + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +完整错误日志: + +${serverErrorLogs.join('\n')} + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +日志文件位置: ${logFilePath} +`; + + fs.writeFileSync(logFilePath, logContent, 'utf8'); + + // 打开日志文件 + shell.openPath(logFilePath).then((error) => { + if (error) { + console.error('Failed to open log file:', error); + // 如果打开文件失败,至少显示文件位置 + shell.showItemInFolder(logFilePath); + } + }); + + return logFilePath; + } catch (err) { + console.error('Failed to save error log:', err); + return null; + } +} + +// 分析错误日志,识别常见错误并提供解决方案 +function analyzeError(errorLogs) { + const allLogs = errorLogs.join('\n'); + + // 检测端口占用错误 + if (allLogs.includes('failed to start HTTP server') || + allLogs.includes('bind: address already in use') || + allLogs.includes('listen tcp') && allLogs.includes('bind: address already in use')) { + return { + type: '端口被占用', + title: '端口 ' + PORT + ' 被占用', + message: '无法启动服务器,端口已被其他程序占用', + solution: `可能的解决方案:\n\n1. 关闭占用端口 ${PORT} 的其他程序\n2. 检查是否已经运行了另一个 New API 实例\n3. 使用以下命令查找占用端口的进程:\n Mac/Linux: lsof -i :${PORT}\n Windows: netstat -ano | findstr :${PORT}\n4. 重启电脑以释放端口` + }; + } + + // 检测数据库错误 + if (allLogs.includes('database is locked') || + allLogs.includes('unable to open database')) { + return { + type: '数据库错误', + title: '数据库访问失败', + message: '无法访问或锁定数据库文件', + solution: '可能的解决方案:\n\n1. 确保没有其他 New API 实例正在运行\n2. 检查数据库文件权限\n3. 尝试删除数据库锁文件(.db-shm 和 .db-wal)\n4. 重启应用程序' + }; + } + + // 检测权限错误 + if (allLogs.includes('permission denied') || + allLogs.includes('access denied')) { + return { + type: '权限错误', + title: '权限不足', + message: '程序没有足够的权限执行操作', + solution: '可能的解决方案:\n\n1. 以管理员/root权限运行程序\n2. 检查数据目录的读写权限\n3. 检查可执行文件的权限\n4. 在 Mac 上,检查安全性与隐私设置' + }; + } + + // 检测网络错误 + if (allLogs.includes('network is unreachable') || + allLogs.includes('no such host') || + allLogs.includes('connection refused')) { + return { + type: '网络错误', + title: '网络连接失败', + message: '无法建立网络连接', + solution: '可能的解决方案:\n\n1. 检查网络连接是否正常\n2. 检查防火墙设置\n3. 检查代理配置\n4. 确认目标服务器地址正确' + }; + } + + // 检测配置文件错误 + if (allLogs.includes('invalid configuration') || + allLogs.includes('failed to parse config') || + allLogs.includes('yaml') || allLogs.includes('json') && allLogs.includes('parse')) { + return { + type: '配置错误', + title: '配置文件错误', + message: '配置文件格式不正确或包含无效配置', + solution: '可能的解决方案:\n\n1. 检查配置文件格式是否正确\n2. 恢复默认配置\n3. 删除配置文件让程序重新生成\n4. 查看文档了解正确的配置格式' + }; + } + + // 检测内存不足 + if (allLogs.includes('out of memory') || + allLogs.includes('cannot allocate memory')) { + return { + type: '内存不足', + title: '系统内存不足', + message: '程序运行时内存不足', + solution: '可能的解决方案:\n\n1. 关闭其他占用内存的程序\n2. 增加系统可用内存\n3. 重启电脑释放内存\n4. 检查是否存在内存泄漏' + }; + } + + // 检测文件不存在错误 + if (allLogs.includes('no such file or directory') || + allLogs.includes('cannot find the file')) { + return { + type: '文件缺失', + title: '找不到必需的文件', + message: '缺少程序运行所需的文件', + solution: '可能的解决方案:\n\n1. 重新安装应用程序\n2. 检查安装目录是否完整\n3. 确保所有依赖文件都存在\n4. 检查文件路径是否正确' + }; + } + + return null; +} + function getBinaryPath() { const isDev = process.env.NODE_ENV === 'development'; const platform = process.platform; @@ -73,7 +210,13 @@ function startServer() { }); serverProcess.stderr.on('data', (data) => { - console.error(`Server Error: ${data}`); + const errorMsg = data.toString(); + console.error(`Server Error: ${errorMsg}`); + serverErrorLogs.push(errorMsg); + // 只保留最近的100条错误日志 + if (serverErrorLogs.length > 100) { + serverErrorLogs.shift(); + } }); serverProcess.on('error', (err) => { @@ -83,8 +226,76 @@ function startServer() { serverProcess.on('close', (code) => { console.log(`Server process exited with code ${code}`); - if (mainWindow && !mainWindow.isDestroyed()) { - mainWindow.close(); + + // 如果退出代码不是0,说明服务器异常退出 + if (code !== 0 && code !== null) { + const errorDetails = serverErrorLogs.length > 0 + ? serverErrorLogs.slice(-20).join('\n') + : '没有捕获到错误日志'; + + // 分析错误类型 + const knownError = analyzeError(serverErrorLogs); + + let dialogOptions; + if (knownError) { + // 识别到已知错误,显示友好的错误信息和解决方案 + dialogOptions = { + type: 'error', + title: knownError.title, + message: knownError.message, + detail: `${knownError.solution}\n\n━━━━━━━━━━━━━━━━━━━━━━\n\n退出代码: ${code}\n\n错误类型: ${knownError.type}\n\n最近的错误日志:\n${errorDetails}`, + buttons: ['退出应用', '查看完整日志'], + defaultId: 0, + cancelId: 0 + }; + } else { + // 未识别的错误,显示通用错误信息 + dialogOptions = { + type: 'error', + title: '服务器崩溃', + message: '服务器进程异常退出', + detail: `退出代码: ${code}\n\n最近的错误信息:\n${errorDetails}`, + buttons: ['退出应用', '查看完整日志'], + defaultId: 0, + cancelId: 0 + }; + } + + dialog.showMessageBox(dialogOptions).then((result) => { + if (result.response === 1) { + // 用户选择查看详情,保存并打开日志文件 + const logPath = saveAndOpenErrorLog(); + + // 显示确认对话框 + const confirmMessage = logPath + ? `日志已保存到:\n${logPath}\n\n日志文件已在默认文本编辑器中打开。\n\n点击"退出"关闭应用程序。` + : '日志保存失败,但已在控制台输出。\n\n点击"退出"关闭应用程序。'; + + dialog.showMessageBox({ + type: 'info', + title: '日志已保存', + message: confirmMessage, + buttons: ['退出'], + defaultId: 0 + }).then(() => { + app.isQuitting = true; + app.quit(); + }); + + // 同时在控制台输出 + console.log('=== 完整错误日志 ==='); + console.log(serverErrorLogs.join('\n')); + } else { + // 用户选择直接退出 + app.isQuitting = true; + app.quit(); + } + }); + } else { + // 正常退出(code为0或null),直接关闭窗口 + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.close(); + } } }); @@ -201,8 +412,79 @@ app.whenReady().then(async () => { createWindow(); } catch (err) { console.error('Failed to start application:', err); - dialog.showErrorBox('Startup Error', `Failed to start server: ${err.message}`); - app.quit(); + + // 分析启动失败的错误 + const knownError = analyzeError(serverErrorLogs); + + if (knownError) { + dialog.showMessageBox({ + type: 'error', + title: knownError.title, + message: `启动失败: ${knownError.message}`, + detail: `${knownError.solution}\n\n━━━━━━━━━━━━━━━━━━━━━━\n\n错误信息: ${err.message}\n\n错误类型: ${knownError.type}`, + buttons: ['退出', '查看完整日志'], + defaultId: 0, + cancelId: 0 + }).then((result) => { + if (result.response === 1) { + // 用户选择查看日志 + const logPath = saveAndOpenErrorLog(); + + const confirmMessage = logPath + ? `日志已保存到:\n${logPath}\n\n日志文件已在默认文本编辑器中打开。\n\n点击"退出"关闭应用程序。` + : '日志保存失败,但已在控制台输出。\n\n点击"退出"关闭应用程序。'; + + dialog.showMessageBox({ + type: 'info', + title: '日志已保存', + message: confirmMessage, + buttons: ['退出'], + defaultId: 0 + }).then(() => { + app.quit(); + }); + + console.log('=== 完整错误日志 ==='); + console.log(serverErrorLogs.join('\n')); + } else { + app.quit(); + } + }); + } else { + dialog.showMessageBox({ + type: 'error', + title: '启动失败', + message: '无法启动服务器', + detail: `错误信息: ${err.message}\n\n请检查日志获取更多信息。`, + buttons: ['退出', '查看完整日志'], + defaultId: 0, + cancelId: 0 + }).then((result) => { + if (result.response === 1) { + // 用户选择查看日志 + const logPath = saveAndOpenErrorLog(); + + const confirmMessage = logPath + ? `日志已保存到:\n${logPath}\n\n日志文件已在默认文本编辑器中打开。\n\n点击"退出"关闭应用程序。` + : '日志保存失败,但已在控制台输出。\n\n点击"退出"关闭应用程序。'; + + dialog.showMessageBox({ + type: 'info', + title: '日志已保存', + message: confirmMessage, + buttons: ['退出'], + defaultId: 0 + }).then(() => { + app.quit(); + }); + + console.log('=== 完整错误日志 ==='); + console.log(serverErrorLogs.join('\n')); + } else { + app.quit(); + } + }); + } } }); diff --git a/electron/package.json b/electron/package.json index 9cdf3d12f..21c933560 100644 --- a/electron/package.json +++ b/electron/package.json @@ -4,7 +4,8 @@ "description": "New API - AI Model Gateway Desktop Application", "main": "main.js", "scripts": { - "start": "set NODE_ENV=development&& electron .", + "start": "electron .", + "dev": "cross-env NODE_ENV=development electron .", "build": "electron-builder", "build:mac": "electron-builder --mac", "build:win": "electron-builder --win", @@ -17,14 +18,14 @@ "openai", "claude" ], - "author": "", - "license": "MIT", + "author": "QuantumNous", "repository": { "type": "git", - "url": "https://github.com/Calcium-Ion/new-api" + "url": "https://github.com/QuantumNous/new-api" }, "devDependencies": { - "electron": "^28.0.0", + "cross-env": "^7.0.3", + "electron": "28.3.3", "electron-builder": "^24.9.1" }, "build": { diff --git a/electron/preload.js b/electron/preload.js index 6d8b6daa0..217f5a410 100644 --- a/electron/preload.js +++ b/electron/preload.js @@ -1,6 +1,8 @@ const { contextBridge } = require('electron'); contextBridge.exposeInMainWorld('electron', { + isElectron: true, version: process.versions.electron, - platform: process.platform + platform: process.platform, + versions: process.versions }); \ No newline at end of file From ff77ba11577fba55f746472e7179a320ecb7d911 Mon Sep 17 00:00:00 2001 From: CaIon Date: Sun, 5 Oct 2025 16:45:29 +0800 Subject: [PATCH 14/17] feat: enhance Electron environment detection and improve database warnings --- electron/main.js | 147 +++++++++++++----- electron/package.json | 4 +- electron/preload.js | 22 ++- .../setup/components/steps/DatabaseStep.jsx | 53 +++++-- 4 files changed, 168 insertions(+), 58 deletions(-) diff --git a/electron/main.js b/electron/main.js index 82f954f00..3cebd34f8 100644 --- a/electron/main.js +++ b/electron/main.js @@ -9,6 +9,7 @@ let serverProcess; let tray = null; let serverErrorLogs = []; const PORT = 3000; +const DEV_FRONTEND_PORT = 5173; // Vite dev server port // 保存日志到文件并打开 function saveAndOpenErrorLog() { @@ -79,10 +80,10 @@ function analyzeError(errorLogs) { if (allLogs.includes('database is locked') || allLogs.includes('unable to open database')) { return { - type: '数据库错误', - title: '数据库访问失败', - message: '无法访问或锁定数据库文件', - solution: '可能的解决方案:\n\n1. 确保没有其他 New API 实例正在运行\n2. 检查数据库文件权限\n3. 尝试删除数据库锁文件(.db-shm 和 .db-wal)\n4. 重启应用程序' + type: '数据文件被占用', + title: '无法访问数据文件', + message: '应用的数据文件正被其他程序占用', + solution: '可能的解决方案:\n\n1. 检查是否已经打开了另一个 New API 窗口\n - 查看任务栏/Dock 中是否有其他 New API 图标\n - 查看系统托盘(Windows)或菜单栏(Mac)中是否有 New API 图标\n\n2. 如果刚刚关闭过应用,请等待 10 秒后再试\n\n3. 重启电脑以释放被占用的文件\n\n4. 如果问题持续,可以尝试:\n - 退出所有 New API 实例\n - 删除数据目录中的临时文件(.db-shm 和 .db-wal)\n - 重新启动应用' }; } @@ -173,32 +174,101 @@ function getBinaryPath() { return path.join(process.resourcesPath, 'bin', binaryName); } +// Check if a server is available with retry logic +function checkServerAvailability(port, maxRetries = 30, retryDelay = 1000) { + return new Promise((resolve, reject) => { + let currentAttempt = 0; + + const tryConnect = () => { + currentAttempt++; + + if (currentAttempt % 5 === 1 && currentAttempt > 1) { + console.log(`Attempting to connect to port ${port}... (attempt ${currentAttempt}/${maxRetries})`); + } + + const req = http.get({ + hostname: '127.0.0.1', // Use IPv4 explicitly instead of 'localhost' to avoid IPv6 issues + port: port, + timeout: 10000 + }, (res) => { + // Server responded, connection successful + req.destroy(); + console.log(`✓ Successfully connected to port ${port} (status: ${res.statusCode})`); + resolve(); + }); + + req.on('error', (err) => { + if (currentAttempt >= maxRetries) { + reject(new Error(`Failed to connect to port ${port} after ${maxRetries} attempts: ${err.message}`)); + } else { + setTimeout(tryConnect, retryDelay); + } + }); + + req.on('timeout', () => { + req.destroy(); + if (currentAttempt >= maxRetries) { + reject(new Error(`Connection timeout on port ${port} after ${maxRetries} attempts`)); + } else { + setTimeout(tryConnect, retryDelay); + } + }); + }; + + tryConnect(); + }); +} + function startServer() { return new Promise((resolve, reject) => { - const binaryPath = getBinaryPath(); const isDev = process.env.NODE_ENV === 'development'; - - console.log('Starting server from:', binaryPath); - - const env = { ...process.env, PORT: PORT.toString() }; - - let dataDir; + if (isDev) { - dataDir = path.join(__dirname, '..', 'data'); - } else { - const userDataPath = app.getPath('userData'); - dataDir = path.join(userDataPath, 'data'); + // 开发模式:假设开发者手动启动了 Go 后端和前端开发服务器 + // 只需要等待前端开发服务器就绪 + console.log('Development mode: skipping server startup'); + console.log('Please make sure you have started:'); + console.log(' 1. Go backend: go run main.go (port 3000)'); + console.log(' 2. Frontend dev server: cd web && bun dev (port 5173)'); + console.log(''); + console.log('Checking if servers are running...'); + + // First check if both servers are accessible + checkServerAvailability(DEV_FRONTEND_PORT) + .then(() => { + console.log('✓ Frontend dev server is accessible on port 5173'); + resolve(); + }) + .catch((err) => { + console.error(`✗ Cannot connect to frontend dev server on port ${DEV_FRONTEND_PORT}`); + console.error('Please make sure the frontend dev server is running:'); + console.error(' cd web && bun dev'); + reject(err); + }); + return; } + // 生产模式:启动二进制服务器 + const env = { ...process.env, PORT: PORT.toString() }; + const userDataPath = app.getPath('userData'); + const dataDir = path.join(userDataPath, 'data'); + if (!fs.existsSync(dataDir)) { fs.mkdirSync(dataDir, { recursive: true }); } env.SQLITE_PATH = path.join(dataDir, 'new-api.db'); + + console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); + console.log('📁 您的数据存储位置:'); + console.log(' ' + dataDir); + console.log(' 💡 备份提示:复制此目录即可备份所有数据'); + console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); - const workingDir = isDev - ? path.join(__dirname, '..') - : process.resourcesPath; + const binaryPath = getBinaryPath(); + const workingDir = process.resourcesPath; + + console.log('Starting server from:', binaryPath); serverProcess = spawn(binaryPath, [], { env, @@ -299,32 +369,25 @@ function startServer() { } }); - waitForServer(resolve, reject); + checkServerAvailability(PORT) + .then(() => { + console.log('✓ Backend server is accessible on port 3000'); + resolve(); + }) + .catch((err) => { + console.error('✗ Failed to connect to backend server'); + reject(err); + }); }); } -function waitForServer(resolve, reject, retries = 30) { - if (retries === 0) { - reject(new Error('Server failed to start within timeout')); - return; - } - - const req = http.get(`http://localhost:${PORT}`, (res) => { - console.log('Server is ready'); - resolve(); - }); - - req.on('error', () => { - setTimeout(() => waitForServer(resolve, reject, retries - 1), 1000); - }); - - req.end(); -} - function createWindow() { + const isDev = process.env.NODE_ENV === 'development'; + const loadPort = isDev ? DEV_FRONTEND_PORT : PORT; + mainWindow = new BrowserWindow({ - width: 1400, - height: 900, + width: 1080, + height: 720, webPreferences: { preload: path.join(__dirname, 'preload.js'), nodeIntegration: false, @@ -334,9 +397,11 @@ function createWindow() { icon: path.join(__dirname, 'icon.png') }); - mainWindow.loadURL(`http://localhost:${PORT}`); + mainWindow.loadURL(`http://127.0.0.1:${loadPort}`); + + console.log(`Loading from: http://127.0.0.1:${loadPort}`); - if (process.env.NODE_ENV === 'development') { + if (isDev) { mainWindow.webContents.openDevTools(); } diff --git a/electron/package.json b/electron/package.json index 21c933560..4b5880ea0 100644 --- a/electron/package.json +++ b/electron/package.json @@ -4,8 +4,8 @@ "description": "New API - AI Model Gateway Desktop Application", "main": "main.js", "scripts": { - "start": "electron .", - "dev": "cross-env NODE_ENV=development electron .", + "start-app": "electron .", + "dev-app": "cross-env NODE_ENV=development electron .", "build": "electron-builder", "build:mac": "electron-builder --mac", "build:win": "electron-builder --win", diff --git a/electron/preload.js b/electron/preload.js index 217f5a410..e089bbb5a 100644 --- a/electron/preload.js +++ b/electron/preload.js @@ -1,8 +1,28 @@ const { contextBridge } = require('electron'); +// 获取数据目录路径(用于显示给用户) +// 使用字符串拼接而不是 path.join 避免模块依赖问题 +function getDataDirPath() { + const platform = process.platform; + const homeDir = process.env.HOME || process.env.USERPROFILE || ''; + + switch (platform) { + case 'darwin': + return `${homeDir}/Library/Application Support/New API/data`; + case 'win32': + const appData = process.env.APPDATA || `${homeDir}\\AppData\\Roaming`; + return `${appData}\\New API\\data`; + case 'linux': + return `${homeDir}/.config/New API/data`; + default: + return `${homeDir}/.new-api/data`; + } +} + contextBridge.exposeInMainWorld('electron', { isElectron: true, version: process.versions.electron, platform: process.platform, - versions: process.versions + versions: process.versions, + dataDir: getDataDirPath() }); \ No newline at end of file diff --git a/web/src/components/setup/components/steps/DatabaseStep.jsx b/web/src/components/setup/components/steps/DatabaseStep.jsx index 04dd76a3c..66923f445 100644 --- a/web/src/components/setup/components/steps/DatabaseStep.jsx +++ b/web/src/components/setup/components/steps/DatabaseStep.jsx @@ -25,29 +25,54 @@ import { Banner } from '@douyinfe/semi-ui'; * 显示当前数据库类型和相关警告信息 */ const DatabaseStep = ({ setupStatus, renderNavigationButtons, t }) => { + // 检测是否在 Electron 环境中运行 + const isElectron = typeof window !== 'undefined' && window.electron?.isElectron; + return ( <> {/* 数据库警告 */} {setupStatus.database_type === 'sqlite' && ( -

- {t( - '您正在使用 SQLite 数据库。如果您在容器环境中运行,请确保已正确设置数据库文件的持久化映射,否则容器重启后所有数据将丢失!', - )} -

-

- + isElectron ? ( +

+

{t( - '建议在生产环境中使用 MySQL 或 PostgreSQL 数据库,或确保 SQLite 数据库文件已映射到宿主机的持久化存储。', + '您的数据将安全地存储在本地计算机上。所有配置、用户信息和使用记录都会自动保存,关闭应用后不会丢失。', )} - -

-
+

+ {window.electron?.dataDir && ( +

+ {t('数据存储位置:')} +
+ + {window.electron.dataDir} + +

+ )} +

+ 💡 {t('提示:如需备份数据,只需复制上述目录即可')} +

+ + ) : ( +
+

+ {t( + '您正在使用 SQLite 数据库。如果您在容器环境中运行,请确保已正确设置数据库文件的持久化映射,否则容器重启后所有数据将丢失!', + )} +

+

+ + {t( + '建议在生产环境中使用 MySQL 或 PostgreSQL 数据库,或确保 SQLite 数据库文件已映射到宿主机的持久化存储。', + )} + +

+
+ ) } className='!rounded-lg' fullMode={false} From c1137027e657e890b2ec6f1aa98b1b0911011d31 Mon Sep 17 00:00:00 2001 From: CaIon Date: Sun, 5 Oct 2025 17:11:30 +0800 Subject: [PATCH 15/17] chore: update build workflows for Electron and Go, including version tagging and dependency management --- .github/workflows/electron-build.yml | 79 +++++++++++++++++---------- .github/workflows/linux-release.yml | 9 +-- .github/workflows/macos-release.yml | 5 +- .github/workflows/windows-release.yml | 5 +- 4 files changed, 61 insertions(+), 37 deletions(-) diff --git a/.github/workflows/electron-build.yml b/.github/workflows/electron-build.yml index b274db857..c3be05bf5 100644 --- a/.github/workflows/electron-build.yml +++ b/.github/workflows/electron-build.yml @@ -3,20 +3,31 @@ name: Build Electron App on: push: tags: - - 'v*.*.*' # Triggers on version tags like v1.0.0 + - '*' # Triggers on version tags like v1.0.0 workflow_dispatch: # Allows manual triggering jobs: build: strategy: matrix: - os: [macos-latest, windows-latest] + # os: [macos-latest, windows-latest] + os: [windows-latest] runs-on: ${{ matrix.os }} + defaults: + run: + shell: bash steps: - name: Checkout code uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest - name: Setup Node.js uses: actions/setup-node@v4 @@ -26,39 +37,49 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: '1.21' + go-version: '>=1.18.0' - name: Build frontend + env: + CI: "" + NODE_OPTIONS: "--max-old-space-size=4096" run: | cd web - npm install --legacy-peer-deps - npm run build - env: - DISABLE_ESLINT_PLUGIN: 'true' - NODE_OPTIONS: '--max_old_space_size=4096' + bun install + DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$(git describe --tags) bun run build + cd .. - - name: Build Go binary (macos/Linux) - if: runner.os != 'Windows' - run: | - go build -ldflags="-s -w" -o new-api + # - name: Build Go binary (macos/Linux) + # if: runner.os != 'Windows' + # run: | + # go mod download + # go build -ldflags "-s -w -X 'one-api/common.Version=$(git describe --tags)' -extldflags '-static'" -o new-api - name: Build Go binary (Windows) if: runner.os == 'Windows' run: | - go build -ldflags="-s -w" -o new-api.exe + go mod download + go build -ldflags "-s -w -X 'one-api/common.Version=$(git describe --tags)'" -o new-api.exe + + - name: Update Electron version + run: | + cd electron + VERSION=$(git describe --tags) + VERSION=${VERSION#v} # Remove 'v' prefix if present + npm version $VERSION --no-git-tag-version --allow-same-version - name: Install Electron dependencies run: | cd electron npm install - - name: Build Electron app (macOS) - if: runner.os == 'macOS' - run: | - cd electron - npm run build:mac - env: - CSC_IDENTITY_AUTO_DISCOVERY: false # Skip code signing + # - name: Build Electron app (macOS) + # if: runner.os == 'macOS' + # run: | + # cd electron + # npm run build:mac + # env: + # CSC_IDENTITY_AUTO_DISCOVERY: false # Skip code signing - name: Build Electron app (Windows) if: runner.os == 'Windows' @@ -66,14 +87,14 @@ jobs: cd electron npm run build:win - - name: Upload artifacts (macOS) - if: runner.os == 'macOS' - uses: actions/upload-artifact@v4 - with: - name: macos-build - path: | - electron/dist/*.dmg - electron/dist/*.zip + # - name: Upload artifacts (macOS) + # if: runner.os == 'macOS' + # uses: actions/upload-artifact@v4 + # with: + # name: macos-build + # path: | + # electron/dist/*.dmg + # electron/dist/*.zip - name: Upload artifacts (Windows) if: runner.os == 'Windows' @@ -96,7 +117,7 @@ jobs: uses: softprops/action-gh-release@v1 with: files: | - macos-build/* + # macos-build/* windows-build/* draft: false prerelease: false diff --git a/.github/workflows/linux-release.yml b/.github/workflows/linux-release.yml index 3e3ddc53b..d2039dced 100644 --- a/.github/workflows/linux-release.yml +++ b/.github/workflows/linux-release.yml @@ -38,21 +38,22 @@ jobs: - name: Build Backend (amd64) run: | go mod download - go build -ldflags "-s -w -X 'one-api/common.Version=$(git describe --tags)' -extldflags '-static'" -o new-api + VERSION=$(git describe --tags) + go build -ldflags "-s -w -X 'one-api/common.Version=$VERSION' -extldflags '-static'" -o new-api-$VERSION - name: Build Backend (arm64) run: | sudo apt-get update DEBIAN_FRONTEND=noninteractive sudo apt-get install -y gcc-aarch64-linux-gnu - CC=aarch64-linux-gnu-gcc CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build -ldflags "-s -w -X 'one-api/common.Version=$(git describe --tags)' -extldflags '-static'" -o new-api-arm64 + VERSION=$(git describe --tags) + CC=aarch64-linux-gnu-gcc CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build -ldflags "-s -w -X 'one-api/common.Version=$VERSION' -extldflags '-static'" -o new-api-arm64-$VERSION - name: Release uses: softprops/action-gh-release@v1 if: startsWith(github.ref, 'refs/tags/') with: files: | - new-api - new-api-arm64 + new-api-* draft: true generate_release_notes: true env: diff --git a/.github/workflows/macos-release.yml b/.github/workflows/macos-release.yml index 8eaf2d67a..135e46102 100644 --- a/.github/workflows/macos-release.yml +++ b/.github/workflows/macos-release.yml @@ -39,12 +39,13 @@ jobs: - name: Build Backend run: | go mod download - go build -ldflags "-X 'one-api/common.Version=$(git describe --tags)'" -o new-api-macos + VERSION=$(git describe --tags) + go build -ldflags "-X 'one-api/common.Version=$VERSION'" -o new-api-macos-$VERSION - name: Release uses: softprops/action-gh-release@v1 if: startsWith(github.ref, 'refs/tags/') with: - files: new-api-macos + files: new-api-macos-* draft: true generate_release_notes: true env: diff --git a/.github/workflows/windows-release.yml b/.github/workflows/windows-release.yml index 30e864f34..e6cc456ca 100644 --- a/.github/workflows/windows-release.yml +++ b/.github/workflows/windows-release.yml @@ -41,12 +41,13 @@ jobs: - name: Build Backend run: | go mod download - go build -ldflags "-s -w -X 'one-api/common.Version=$(git describe --tags)'" -o new-api.exe + VERSION=$(git describe --tags) + go build -ldflags "-s -w -X 'one-api/common.Version=$VERSION'" -o new-api-$VERSION.exe - name: Release uses: softprops/action-gh-release@v1 if: startsWith(github.ref, 'refs/tags/') with: - files: new-api.exe + files: new-api-*.exe draft: true generate_release_notes: true env: From 414be64d33ce5bc3a7114e33a1ac18c057342431 Mon Sep 17 00:00:00 2001 From: CaIon Date: Sun, 5 Oct 2025 17:15:10 +0800 Subject: [PATCH 16/17] fix: correct Windows path handling in preload.js and update .gitignore for consistency --- .gitignore | 3 +- electron/package-lock.json | 3677 ++++++++++++++++++++++++++++++++++++ electron/preload.js | 3 +- 3 files changed, 3680 insertions(+), 3 deletions(-) create mode 100644 electron/package-lock.json diff --git a/.gitignore b/.gitignore index bc0b14579..3e6020e83 100644 --- a/.gitignore +++ b/.gitignore @@ -15,5 +15,4 @@ tiktoken_cache .eslintcache electron/node_modules -electron/dist -electron/package-lock.json \ No newline at end of file +electron/dist \ No newline at end of file diff --git a/electron/package-lock.json b/electron/package-lock.json new file mode 100644 index 000000000..7b6ff0586 --- /dev/null +++ b/electron/package-lock.json @@ -0,0 +1,3677 @@ +{ + "name": "new-api-electron", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "new-api-electron", + "version": "1.0.0", + "devDependencies": { + "cross-env": "^7.0.3", + "electron": "28.3.3", + "electron-builder": "^24.9.1" + } + }, + "node_modules/@develar/schema-utils": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@electron/asar": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", + "integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "bin": { + "asar": "bin/asar.js" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/@electron/asar/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@electron/asar/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/@electron/notarize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.2.1.tgz", + "integrity": "sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/notarize/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/notarize/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/notarize/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/osx-sign": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz", + "integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "compare-version": "^0.1.2", + "debug": "^4.3.4", + "fs-extra": "^10.0.0", + "isbinaryfile": "^4.0.8", + "minimist": "^1.2.6", + "plist": "^3.0.5" + }, + "bin": { + "electron-osx-flat": "bin/electron-osx-flat.js", + "electron-osx-sign": "bin/electron-osx-sign.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@electron/osx-sign/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/@electron/osx-sign/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/osx-sign/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/universal": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.5.1.tgz", + "integrity": "sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@electron/asar": "^3.2.1", + "@malept/cross-spawn-promise": "^1.1.0", + "debug": "^4.3.1", + "dir-compare": "^3.0.0", + "fs-extra": "^9.0.1", + "minimatch": "^3.0.4", + "plist": "^3.0.4" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/@electron/universal/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@electron/universal/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/universal/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/universal/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@electron/universal/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@malept/cross-spawn-promise": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", + "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/malept" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" + } + ], + "license": "Apache-2.0", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@malept/flatpak-bundler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.0", + "lodash": "^4.17.15", + "tmp-promise": "^3.0.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "18.19.129", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.129.tgz", + "integrity": "sha512-hrmi5jWt2w60ayox3iIXwpMEnfUvOLJCRtrOPbHtH15nTjvO7uhnelvrdAs0dO0/zl5DZ3ZbahiaXEVb54ca/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/plist": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", + "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*", + "xmlbuilder": ">=11.0.1" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/verror": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", + "integrity": "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", + "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/7zip-bin": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", + "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/app-builder-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", + "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==", + "dev": true, + "license": "MIT" + }, + "node_modules/app-builder-lib": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.13.3.tgz", + "integrity": "sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@develar/schema-utils": "~2.6.5", + "@electron/notarize": "2.2.1", + "@electron/osx-sign": "1.0.5", + "@electron/universal": "1.5.1", + "@malept/flatpak-bundler": "^0.4.0", + "@types/fs-extra": "9.0.13", + "async-exit-hook": "^2.0.1", + "bluebird-lst": "^1.0.9", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chromium-pickle-js": "^0.2.0", + "debug": "^4.3.4", + "ejs": "^3.1.8", + "electron-publish": "24.13.1", + "form-data": "^4.0.0", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.0", + "is-ci": "^3.0.0", + "isbinaryfile": "^5.0.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "minimatch": "^5.1.1", + "read-config-file": "6.3.2", + "sanitize-filename": "^1.6.3", + "semver": "^7.3.8", + "tar": "^6.1.12", + "temp-file": "^3.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "dmg-builder": "24.13.3", + "electron-builder-squirrel-windows": "24.13.3" + } + }, + "node_modules/app-builder-lib/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/app-builder-lib/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/app-builder-lib/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/app-builder-lib/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/bluebird-lst": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", + "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bluebird": "^3.5.5" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", + "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/builder-util": { + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.13.1.tgz", + "integrity": "sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/debug": "^4.1.6", + "7zip-bin": "~5.2.0", + "app-builder-bin": "4.0.0", + "bluebird-lst": "^1.0.9", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "debug": "^4.3.4", + "fs-extra": "^10.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-ci": "^3.0.0", + "js-yaml": "^4.1.0", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0" + } + }, + "node_modules/builder-util-runtime": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz", + "integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/builder-util/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/builder-util/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/builder-util/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/config-file-ts": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.6.tgz", + "integrity": "sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^10.3.10", + "typescript": "^5.3.3" + } + }, + "node_modules/config-file-ts/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.1.0" + } + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/dir-compare": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", + "integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal": "^1.0.0", + "minimatch": "^3.0.4" + } + }, + "node_modules/dir-compare/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/dir-compare/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dmg-builder": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.13.3.tgz", + "integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "app-builder-lib": "24.13.3", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "fs-extra": "^10.1.0", + "iconv-lite": "^0.6.2", + "js-yaml": "^4.1.0" + }, + "optionalDependencies": { + "dmg-license": "^1.0.11" + } + }, + "node_modules/dmg-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dmg-builder/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/dmg-builder/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/dmg-license": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", + "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "@types/plist": "^3.0.1", + "@types/verror": "^1.10.3", + "ajv": "^6.10.0", + "crc": "^3.8.0", + "iconv-corefoundation": "^1.1.7", + "plist": "^3.0.4", + "smart-buffer": "^4.0.2", + "verror": "^1.10.0" + }, + "bin": { + "dmg-license": "bin/dmg-license.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "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/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron": { + "version": "28.3.3", + "resolved": "https://registry.npmjs.org/electron/-/electron-28.3.3.tgz", + "integrity": "sha512-ObKMLSPNhomtCOBAxFS8P2DW/4umkh72ouZUlUKzXGtYuPzgr1SYhskhFWgzAsPtUzhL2CzyV2sfbHcEW4CXqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^18.11.18", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "node_modules/electron-builder": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.13.3.tgz", + "integrity": "sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "app-builder-lib": "24.13.3", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "dmg-builder": "24.13.3", + "fs-extra": "^10.1.0", + "is-ci": "^3.0.0", + "lazy-val": "^1.0.5", + "read-config-file": "6.3.2", + "simple-update-notifier": "2.0.0", + "yargs": "^17.6.2" + }, + "bin": { + "electron-builder": "cli.js", + "install-app-deps": "install-app-deps.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/electron-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-builder/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-builder/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-publish": { + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.13.1.tgz", + "integrity": "sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^9.0.11", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "fs-extra": "^10.1.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + } + }, + "node_modules/electron-publish/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-publish/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-publish/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extsprintf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "optional": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-agent/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-corefoundation": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", + "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "cli-truncate": "^2.1.0", + "node-addon-api": "^1.6.3" + }, + "engines": { + "node": "^8.11.2 || >=10" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isbinaryfile": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.6.tgz", + "integrity": "sha512-I+NmIfBHUl+r2wcDd6JwE9yWje/PIVY/R5/CmV8dXLZd5K+L9X2klAOwfAHNnondLXkbHyTAleQAWonpTJBTtw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lazy-val": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/plist": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.8.8", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-config-file": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", + "integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "config-file-ts": "^0.2.4", + "dotenv": "^9.0.2", + "dotenv-expand": "^5.1.0", + "js-yaml": "^4.1.0", + "json5": "^2.2.0", + "lazy-val": "^1.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "dev": true, + "license": "WTFPL OR ISC", + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "dev": true, + "license": "ISC" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/stat-mode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/temp-file": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-exit-hook": "^2.0.1", + "fs-extra": "^10.0.0" + } + }, + "node_modules/temp-file/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/temp-file/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/temp-file/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tmp": "^0.2.0" + } + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "dev": true, + "license": "WTFPL", + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "license": "MIT" + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utf8-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "dev": true, + "license": "(WTFPL OR MIT)" + }, + "node_modules/verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} diff --git a/electron/preload.js b/electron/preload.js index e089bbb5a..b0579172c 100644 --- a/electron/preload.js +++ b/electron/preload.js @@ -9,9 +9,10 @@ function getDataDirPath() { switch (platform) { case 'darwin': return `${homeDir}/Library/Application Support/New API/data`; - case 'win32': + case 'win32': { const appData = process.env.APPDATA || `${homeDir}\\AppData\\Roaming`; return `${appData}\\New API\\data`; + } case 'linux': return `${homeDir}/.config/New API/data`; default: From 7074ea2ed6ae7ecfc25350e82882fe13af978391 Mon Sep 17 00:00:00 2001 From: CaIon Date: Sun, 5 Oct 2025 17:19:52 +0800 Subject: [PATCH 17/17] chore: upgrade action-gh-release to v2 in build workflows --- .github/workflows/electron-build.yml | 2 +- .github/workflows/linux-release.yml | 2 +- .github/workflows/macos-release.yml | 2 +- .github/workflows/windows-release.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/electron-build.yml b/.github/workflows/electron-build.yml index c3be05bf5..a58ad964d 100644 --- a/.github/workflows/electron-build.yml +++ b/.github/workflows/electron-build.yml @@ -114,7 +114,7 @@ jobs: uses: actions/download-artifact@v4 - name: Create Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: files: | # macos-build/* diff --git a/.github/workflows/linux-release.yml b/.github/workflows/linux-release.yml index d2039dced..9e270c2ab 100644 --- a/.github/workflows/linux-release.yml +++ b/.github/workflows/linux-release.yml @@ -49,7 +49,7 @@ jobs: CC=aarch64-linux-gnu-gcc CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build -ldflags "-s -w -X 'one-api/common.Version=$VERSION' -extldflags '-static'" -o new-api-arm64-$VERSION - name: Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 if: startsWith(github.ref, 'refs/tags/') with: files: | diff --git a/.github/workflows/macos-release.yml b/.github/workflows/macos-release.yml index 135e46102..ecd3a6708 100644 --- a/.github/workflows/macos-release.yml +++ b/.github/workflows/macos-release.yml @@ -42,7 +42,7 @@ jobs: VERSION=$(git describe --tags) go build -ldflags "-X 'one-api/common.Version=$VERSION'" -o new-api-macos-$VERSION - name: Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 if: startsWith(github.ref, 'refs/tags/') with: files: new-api-macos-* diff --git a/.github/workflows/windows-release.yml b/.github/workflows/windows-release.yml index e6cc456ca..a08c3648d 100644 --- a/.github/workflows/windows-release.yml +++ b/.github/workflows/windows-release.yml @@ -44,7 +44,7 @@ jobs: VERSION=$(git describe --tags) go build -ldflags "-s -w -X 'one-api/common.Version=$VERSION'" -o new-api-$VERSION.exe - name: Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 if: startsWith(github.ref, 'refs/tags/') with: files: new-api-*.exe