Compare commits

..

1 Commits

Author SHA1 Message Date
renovate[bot]
53a2b8a0be fix(deps): update dependency zod to v4 2026-01-08 16:32:43 +00:00
13 changed files with 16 additions and 316 deletions

View File

@@ -3,7 +3,6 @@
import { Github, Info, Moon, Sun, Tag } from "lucide-react" import { Github, Info, Moon, Sun, Tag } from "lucide-react"
import { usePathname, useRouter, useSearchParams } from "next/navigation" import { usePathname, useRouter, useSearchParams } from "next/navigation"
import { Suspense, useEffect, useState } from "react" import { Suspense, useEffect, useState } from "react"
import { toast } from "sonner"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { import {
Dialog, Dialog,
@@ -104,11 +103,6 @@ function SettingsContent({
) )
const [currentLang, setCurrentLang] = useState("en") const [currentLang, setCurrentLang] = useState("en")
// Proxy settings state (Electron only)
const [httpProxy, setHttpProxy] = useState("")
const [httpsProxy, setHttpsProxy] = useState("")
const [isApplyingProxy, setIsApplyingProxy] = useState(false)
useEffect(() => { useEffect(() => {
// Only fetch if not cached in localStorage // Only fetch if not cached in localStorage
if (getStoredAccessCodeRequired() !== null) return if (getStoredAccessCodeRequired() !== null) return
@@ -156,14 +150,6 @@ function SettingsContent({
setCloseProtection(storedCloseProtection !== "false") setCloseProtection(storedCloseProtection !== "false")
setError("") setError("")
// Load proxy settings (Electron only)
if (window.electronAPI?.getProxy) {
window.electronAPI.getProxy().then((config) => {
setHttpProxy(config.httpProxy || "")
setHttpsProxy(config.httpsProxy || "")
})
}
} }
}, [open]) }, [open])
@@ -222,46 +208,6 @@ function SettingsContent({
} }
} }
const handleApplyProxy = async () => {
if (!window.electronAPI?.setProxy) return
// Validate proxy URLs (must start with http:// or https://)
const validateProxyUrl = (url: string): boolean => {
if (!url) return true // Empty is OK
return url.startsWith("http://") || url.startsWith("https://")
}
const trimmedHttp = httpProxy.trim()
const trimmedHttps = httpsProxy.trim()
if (trimmedHttp && !validateProxyUrl(trimmedHttp)) {
toast.error("HTTP Proxy must start with http:// or https://")
return
}
if (trimmedHttps && !validateProxyUrl(trimmedHttps)) {
toast.error("HTTPS Proxy must start with http:// or https://")
return
}
setIsApplyingProxy(true)
try {
const result = await window.electronAPI.setProxy({
httpProxy: trimmedHttp || undefined,
httpsProxy: trimmedHttps || undefined,
})
if (result.success) {
toast.success(dict.settings.proxyApplied)
} else {
toast.error(result.error || "Failed to apply proxy settings")
}
} catch {
toast.error("Failed to apply proxy settings")
} finally {
setIsApplyingProxy(false)
}
}
return ( return (
<DialogContent className="sm:max-w-lg p-0 gap-0"> <DialogContent className="sm:max-w-lg p-0 gap-0">
{/* Header */} {/* Header */}
@@ -424,54 +370,6 @@ function SettingsContent({
</span> </span>
</div> </div>
</SettingItem> </SettingItem>
{/* Proxy Settings - Electron only */}
{typeof window !== "undefined" &&
window.electronAPI?.isElectron && (
<div className="py-4 space-y-3">
<div className="space-y-0.5">
<Label className="text-sm font-medium">
{dict.settings.proxy}
</Label>
<p className="text-xs text-muted-foreground">
{dict.settings.proxyDescription}
</p>
</div>
<div className="space-y-2">
<Input
id="http-proxy"
type="text"
value={httpProxy}
onChange={(e) =>
setHttpProxy(e.target.value)
}
placeholder={`${dict.settings.httpProxy}: http://proxy:8080`}
className="h-9"
/>
<Input
id="https-proxy"
type="text"
value={httpsProxy}
onChange={(e) =>
setHttpsProxy(e.target.value)
}
placeholder={`${dict.settings.httpsProxy}: http://proxy:8080`}
className="h-9"
/>
</div>
<Button
onClick={handleApplyProxy}
disabled={isApplyingProxy}
className="h-9 px-4 rounded-xl w-full"
>
{isApplyingProxy
? "..."
: dict.settings.applyProxy}
</Button>
</div>
)}
</div> </div>
</div> </div>

View File

@@ -25,19 +25,6 @@ interface ApplyPresetResult {
env?: Record<string, string> env?: Record<string, string>
} }
/** Proxy configuration interface */
interface ProxyConfig {
httpProxy?: string
httpsProxy?: string
}
/** Result of setting proxy */
interface SetProxyResult {
success: boolean
error?: string
devMode?: boolean
}
declare global { declare global {
interface Window { interface Window {
/** Main window Electron API */ /** Main window Electron API */
@@ -58,10 +45,6 @@ declare global {
openFile: () => Promise<string | null> openFile: () => Promise<string | null>
/** Save data to file via save dialog */ /** Save data to file via save dialog */
saveFile: (data: string) => Promise<boolean> saveFile: (data: string) => Promise<boolean>
/** Get proxy configuration */
getProxy: () => Promise<ProxyConfig>
/** Set proxy configuration (saves and restarts server) */
setProxy: (config: ProxyConfig) => Promise<SetProxyResult>
} }
/** Settings window Electron API */ /** Settings window Electron API */
@@ -88,4 +71,4 @@ declare global {
} }
} }
export { ConfigPreset, ApplyPresetResult, ProxyConfig, SetProxyResult } export { ConfigPreset, ApplyPresetResult }

View File

@@ -4,7 +4,6 @@ import { getCurrentPresetEnv } from "./config-manager"
import { loadEnvFile } from "./env-loader" import { loadEnvFile } from "./env-loader"
import { registerIpcHandlers } from "./ipc-handlers" import { registerIpcHandlers } from "./ipc-handlers"
import { startNextServer, stopNextServer } from "./next-server" import { startNextServer, stopNextServer } from "./next-server"
import { applyProxyToEnv } from "./proxy-manager"
import { registerSettingsWindowHandlers } from "./settings-window" import { registerSettingsWindowHandlers } from "./settings-window"
import { createWindow, getMainWindow } from "./window-manager" import { createWindow, getMainWindow } from "./window-manager"
@@ -25,9 +24,6 @@ if (!gotTheLock) {
// Load environment variables from .env files // Load environment variables from .env files
loadEnvFile() loadEnvFile()
// Apply proxy settings from saved config
applyProxyToEnv()
// Apply saved preset environment variables (overrides .env) // Apply saved preset environment variables (overrides .env)
const presetEnv = getCurrentPresetEnv() const presetEnv = getCurrentPresetEnv()
for (const [key, value] of Object.entries(presetEnv)) { for (const [key, value] of Object.entries(presetEnv)) {

View File

@@ -11,12 +11,6 @@ import {
updatePreset, updatePreset,
} from "./config-manager" } from "./config-manager"
import { restartNextServer } from "./next-server" import { restartNextServer } from "./next-server"
import {
applyProxyToEnv,
getProxyConfig,
type ProxyConfig,
saveProxyConfig,
} from "./proxy-manager"
/** /**
* Allowed configuration keys for presets * Allowed configuration keys for presets
@@ -215,40 +209,4 @@ export function registerIpcHandlers(): void {
return setCurrentPreset(id) return setCurrentPreset(id)
}, },
) )
// ==================== Proxy Settings ====================
ipcMain.handle("get-proxy", () => {
return getProxyConfig()
})
ipcMain.handle("set-proxy", async (_event, config: ProxyConfig) => {
try {
// Save config to file
saveProxyConfig(config)
// Apply to current process environment
applyProxyToEnv()
const isDev = process.env.NODE_ENV === "development"
if (isDev) {
// In development, env vars are already applied
// Next.js dev server may need manual restart
return { success: true, devMode: true }
}
// Production: restart Next.js server to pick up new env vars
await restartNextServer()
return { success: true }
} catch (error) {
return {
success: false,
error:
error instanceof Error
? error.message
: "Failed to apply proxy settings",
}
}
})
} }

View File

@@ -69,8 +69,6 @@ export async function startNextServer(): Promise<string> {
NODE_ENV: "production", NODE_ENV: "production",
PORT: String(port), PORT: String(port),
HOSTNAME: "localhost", HOSTNAME: "localhost",
// Enable Node.js built-in proxy support for fetch (Node.js 24+)
NODE_USE_ENV_PROXY: "1",
} }
// Set cache directory to a writable location (user's app data folder) // Set cache directory to a writable location (user's app data folder)
@@ -87,13 +85,6 @@ export async function startNextServer(): Promise<string> {
} }
} }
// Debug: log proxy-related env vars
console.log("Proxy env vars being passed to server:", {
HTTP_PROXY: env.HTTP_PROXY || env.http_proxy || "not set",
HTTPS_PROXY: env.HTTPS_PROXY || env.https_proxy || "not set",
NODE_USE_ENV_PROXY: env.NODE_USE_ENV_PROXY || "not set",
})
// Use Electron's utilityProcess API for running Node.js in background // Use Electron's utilityProcess API for running Node.js in background
// This is the recommended way to run Node.js code in Electron // This is the recommended way to run Node.js code in Electron
serverProcess = utilityProcess.fork(serverPath, [], { serverProcess = utilityProcess.fork(serverPath, [], {
@@ -123,41 +114,13 @@ export async function startNextServer(): Promise<string> {
} }
/** /**
* Stop the Next.js server process and wait for it to exit * Stop the Next.js server process
*/ */
export async function stopNextServer(): Promise<void> { export function stopNextServer(): void {
if (serverProcess) { if (serverProcess) {
console.log("Stopping Next.js server...") console.log("Stopping Next.js server...")
// Create a promise that resolves when the process exits
const exitPromise = new Promise<void>((resolve) => {
const proc = serverProcess
if (!proc) {
resolve()
return
}
const onExit = () => {
resolve()
}
proc.once("exit", onExit)
// Timeout after 5 seconds
setTimeout(() => {
proc.removeListener("exit", onExit)
resolve()
}, 5000)
})
serverProcess.kill() serverProcess.kill()
serverProcess = null serverProcess = null
// Wait for process to exit
await exitPromise
// Additional wait for OS to release port
await new Promise((resolve) => setTimeout(resolve, 500))
} }
} }
@@ -187,8 +150,8 @@ async function waitForServerStop(timeout = 5000): Promise<void> {
export async function restartNextServer(): Promise<string> { export async function restartNextServer(): Promise<string> {
console.log("Restarting Next.js server...") console.log("Restarting Next.js server...")
// Stop the current server and wait for it to exit // Stop the current server
await stopNextServer() stopNextServer()
// Wait for the port to be released // Wait for the port to be released
await waitForServerStop() await waitForServerStop()

View File

@@ -1,75 +0,0 @@
import { app } from "electron"
import * as fs from "fs"
import * as path from "path"
import type { ProxyConfig } from "../electron.d"
export type { ProxyConfig }
const CONFIG_FILE = "proxy-config.json"
function getConfigPath(): string {
return path.join(app.getPath("userData"), CONFIG_FILE)
}
/**
* Load proxy configuration from JSON file
*/
export function loadProxyConfig(): ProxyConfig {
try {
const configPath = getConfigPath()
if (fs.existsSync(configPath)) {
const data = fs.readFileSync(configPath, "utf-8")
return JSON.parse(data) as ProxyConfig
}
} catch (error) {
console.error("Failed to load proxy config:", error)
}
return {}
}
/**
* Save proxy configuration to JSON file
*/
export function saveProxyConfig(config: ProxyConfig): void {
try {
const configPath = getConfigPath()
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8")
} catch (error) {
console.error("Failed to save proxy config:", error)
throw error
}
}
/**
* Apply proxy configuration to process.env
* Must be called BEFORE starting the Next.js server
*/
export function applyProxyToEnv(): void {
const config = loadProxyConfig()
if (config.httpProxy) {
process.env.HTTP_PROXY = config.httpProxy
process.env.http_proxy = config.httpProxy
} else {
delete process.env.HTTP_PROXY
delete process.env.http_proxy
}
if (config.httpsProxy) {
process.env.HTTPS_PROXY = config.httpsProxy
process.env.https_proxy = config.httpsProxy
} else {
delete process.env.HTTPS_PROXY
delete process.env.https_proxy
}
}
/**
* Get current proxy configuration (from process.env)
*/
export function getProxyConfig(): ProxyConfig {
return {
httpProxy: process.env.HTTP_PROXY || process.env.http_proxy || "",
httpsProxy: process.env.HTTPS_PROXY || process.env.https_proxy || "",
}
}

View File

@@ -21,9 +21,4 @@ contextBridge.exposeInMainWorld("electronAPI", {
// File operations // File operations
openFile: () => ipcRenderer.invoke("dialog-open-file"), openFile: () => ipcRenderer.invoke("dialog-open-file"),
saveFile: (data: string) => ipcRenderer.invoke("dialog-save-file", data), saveFile: (data: string) => ipcRenderer.invoke("dialog-save-file", data),
// Proxy settings
getProxy: () => ipcRenderer.invoke("get-proxy"),
setProxy: (config: { httpProxy?: string; httpsProxy?: string }) =>
ipcRenderer.invoke("set-proxy", config),
}) })

View File

@@ -107,13 +107,7 @@
"diagramActions": "Diagram Actions", "diagramActions": "Diagram Actions",
"diagramActionsDescription": "Manage diagram history and exports", "diagramActionsDescription": "Manage diagram history and exports",
"history": "History", "history": "History",
"download": "Download", "download": "Download"
"proxy": "Proxy Settings",
"proxyDescription": "Configure HTTP/HTTPS proxy for API requests (Desktop only)",
"httpProxy": "HTTP Proxy",
"httpsProxy": "HTTPS Proxy",
"applyProxy": "Apply",
"proxyApplied": "Proxy settings applied"
}, },
"save": { "save": {
"title": "Save Diagram", "title": "Save Diagram",

View File

@@ -107,13 +107,7 @@
"diagramActions": "ダイアグラム操作", "diagramActions": "ダイアグラム操作",
"diagramActionsDescription": "ダイアグラムの履歴とエクスポートを管理", "diagramActionsDescription": "ダイアグラムの履歴とエクスポートを管理",
"history": "履歴", "history": "履歴",
"download": "ダウンロード", "download": "ダウンロード"
"proxy": "プロキシ設定",
"proxyDescription": "API リクエスト用の HTTP/HTTPS プロキシを設定(デスクトップ版のみ)",
"httpProxy": "HTTP プロキシ",
"httpsProxy": "HTTPS プロキシ",
"applyProxy": "適用",
"proxyApplied": "プロキシ設定が適用されました"
}, },
"save": { "save": {
"title": "ダイアグラムを保存", "title": "ダイアグラムを保存",

View File

@@ -107,13 +107,7 @@
"diagramActions": "图表操作", "diagramActions": "图表操作",
"diagramActionsDescription": "管理图表历史记录和导出", "diagramActionsDescription": "管理图表历史记录和导出",
"history": "历史记录", "history": "历史记录",
"download": "下载", "download": "下载"
"proxy": "代理设置",
"proxyDescription": "配置 API 请求的 HTTP/HTTPS 代理(仅桌面版)",
"httpProxy": "HTTP 代理",
"httpsProxy": "HTTPS 代理",
"applyProxy": "应用",
"proxyApplied": "代理设置已应用"
}, },
"save": { "save": {
"title": "保存图表", "title": "保存图表",

View File

@@ -1,6 +1,6 @@
{ {
"name": "next-ai-draw-io", "name": "next-ai-draw-io",
"version": "0.4.10", "version": "0.4.9",
"license": "Apache-2.0", "license": "Apache-2.0",
"private": true, "private": true,
"main": "dist-electron/main/index.js", "main": "dist-electron/main/index.js",

View File

@@ -1,18 +1,18 @@
{ {
"name": "@next-ai-drawio/mcp-server", "name": "@next-ai-drawio/mcp-server",
"version": "0.1.6", "version": "0.1.12",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@next-ai-drawio/mcp-server", "name": "@next-ai-drawio/mcp-server",
"version": "0.1.6", "version": "0.1.12",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@modelcontextprotocol/sdk": "^1.0.4", "@modelcontextprotocol/sdk": "^1.0.4",
"linkedom": "^0.18.0", "linkedom": "^0.18.0",
"open": "^11.0.0", "open": "^11.0.0",
"zod": "^3.24.0" "zod": "^4.0.0"
}, },
"bin": { "bin": {
"next-ai-drawio-mcp": "dist/index.js" "next-ai-drawio-mcp": "dist/index.js"
@@ -2051,9 +2051,9 @@
} }
}, },
"node_modules/zod": { "node_modules/zod": {
"version": "3.25.76", "version": "4.3.5",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.5.tgz",
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==",
"license": "MIT", "license": "MIT",
"peer": true, "peer": true,
"funding": { "funding": {

View File

@@ -39,7 +39,7 @@
"@modelcontextprotocol/sdk": "^1.0.4", "@modelcontextprotocol/sdk": "^1.0.4",
"linkedom": "^0.18.0", "linkedom": "^0.18.0",
"open": "^11.0.0", "open": "^11.0.0",
"zod": "^3.24.0" "zod": "^4.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^24.0.0", "@types/node": "^24.0.0",