chore: bump version to 0.4.5 (#346)

* chore: bump version to 0.4.5 and add desktop app to README

* style: auto-format with Biome

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Dayuan Jiang
2025-12-22 10:39:28 +09:00
committed by GitHub
parent f58274bb84
commit fc5eca877a
6 changed files with 82 additions and 35 deletions

View File

@@ -33,6 +33,7 @@ https://github.com/user-attachments/assets/9d60a3e8-4a1c-4b5e-acbb-26af2d3eabd1
- [MCP Server (Preview)](#mcp-server-preview)
- [Getting Started](#getting-started)
- [Try it Online](#try-it-online)
- [Desktop Application](#desktop-application)
- [Run with Docker (Recommended)](#run-with-docker-recommended)
- [Installation](#installation)
- [Deployment](#deployment)
@@ -135,6 +136,28 @@ No installation needed! Try the app directly on our demo site:
> **Bring Your Own API Key**: You can use your own API key to bypass usage limits on the demo site. Click the Settings icon in the chat panel to configure your provider and API key. Your key is stored locally in your browser and is never stored on the server.
### Desktop Application
Download the native desktop app for your platform from the [Releases page](https://github.com/DayuanJiang/next-ai-draw-io/releases):
| Platform | Download |
|----------|----------|
| macOS | `.dmg` (Intel & Apple Silicon) |
| Windows | `.exe` installer (x64 & ARM64) |
| Linux | `.AppImage` or `.deb` (x64 & ARM64) |
**Features:**
- **Secure API key storage**: Credentials encrypted using OS keychain
- **Configuration presets**: Save and switch between AI providers via menu
- **Native file dialogs**: Open/save `.drawio` files directly
- **Offline capable**: Works without internet after first launch
**Quick Setup:**
1. Download and install for your platform
2. Open the app → **Menu → Configuration → Manage Presets**
3. Add your AI provider credentials
4. Start creating diagrams!
### Run with Docker (Recommended)
If you just want to run it locally, the best way is to use Docker.

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "next-ai-draw-io",
"version": "0.4.4",
"version": "0.4.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "next-ai-draw-io",
"version": "0.4.4",
"version": "0.4.5",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/amazon-bedrock": "^3.0.70",

View File

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

View File

@@ -6,19 +6,19 @@
const { cpSync, existsSync } = require("fs")
const path = require("path")
module.exports = async function (context) {
module.exports = async (context) => {
const appOutDir = context.appOutDir
const resourcesDir = path.join(
appOutDir,
context.packager.platform.name === "mac"
? `${context.packager.appInfo.productFilename}.app/Contents/Resources`
: "resources"
: "resources",
)
const standaloneDir = path.join(resourcesDir, "standalone")
const sourceNodeModules = path.join(
context.packager.projectDir,
"electron-standalone",
"node_modules"
"node_modules",
)
const targetNodeModules = path.join(standaloneDir, "node_modules")
@@ -29,11 +29,15 @@ module.exports = async function (context) {
console.log("[afterPack] node_modules copied successfully")
} else {
console.error("[afterPack] Source or target directory not found!")
console.error(` Source: ${sourceNodeModules} exists: ${existsSync(sourceNodeModules)}`)
console.error(` Target dir: ${standaloneDir} exists: ${existsSync(standaloneDir)}`)
console.error(
` Source: ${sourceNodeModules} exists: ${existsSync(sourceNodeModules)}`,
)
console.error(
` Target dir: ${standaloneDir} exists: ${existsSync(standaloneDir)}`,
)
throw new Error(
"[afterPack] Failed: Required directories not found. " +
"Ensure 'npm run electron:prepare' was run before building."
"Ensure 'npm run electron:prepare' was run before building.",
)
}
}

View File

@@ -11,10 +11,10 @@
*/
import { spawn } from "node:child_process"
import { fileURLToPath } from "node:url"
import { existsSync, readFileSync, watch } from "node:fs"
import path from "node:path"
import os from "node:os"
import path from "node:path"
import { fileURLToPath } from "node:url"
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const rootDir = path.join(__dirname, "..")
@@ -29,9 +29,18 @@ function getUserDataPath() {
const appName = "next-ai-draw-io"
switch (process.platform) {
case "darwin":
return path.join(os.homedir(), "Library", "Application Support", appName)
return path.join(
os.homedir(),
"Library",
"Application Support",
appName,
)
case "win32":
return path.join(process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming"), appName)
return path.join(
process.env.APPDATA ||
path.join(os.homedir(), "AppData", "Roaming"),
appName,
)
default:
return path.join(os.homedir(), ".config", appName)
}
@@ -57,7 +66,7 @@ function loadPresetConfig() {
return null
}
const preset = data.presets.find(p => p.id === data.currentPresetId)
const preset = data.presets.find((p) => p.id === data.currentPresetId)
if (!preset) {
console.log("📋 Active preset not found, using .env.local")
return null
@@ -207,16 +216,21 @@ async function main() {
}
try {
configWatcher = watch(configPath, { persistent: false }, async (eventType) => {
configWatcher = watch(
configPath,
{ persistent: false },
async (eventType) => {
if (eventType === "change" && !restartPending) {
restartPending = true
console.log("\n🔄 Preset configuration changed, restarting Next.js server...")
console.log(
"\n🔄 Preset configuration changed, restarting Next.js server...",
)
// Kill current Next.js process
nextProcess.kill()
// Wait a bit for process to die
await new Promise(r => setTimeout(r, 1000))
await new Promise((r) => setTimeout(r, 1000))
// Reload preset and restart
const newPresetEnv = loadPresetConfig()
@@ -224,14 +238,20 @@ async function main() {
try {
await waitForServer(NEXT_URL)
console.log("✅ Next.js server restarted with new configuration\n")
console.log(
"✅ Next.js server restarted with new configuration\n",
)
} catch (err) {
console.error("❌ Failed to restart Next.js:", err.message)
console.error(
"❌ Failed to restart Next.js:",
err.message,
)
}
restartPending = false
}
})
},
)
console.log("👀 Watching for preset configuration changes...")
} catch (err) {
// File might not exist yet, that's ok

View File

@@ -6,7 +6,7 @@
* that electron-builder can properly include
*/
import { cpSync, rmSync, existsSync, mkdirSync } from "node:fs"
import { cpSync, existsSync, mkdirSync, rmSync } from "node:fs"
import { join } from "node:path"
import { fileURLToPath } from "node:url"