Skip to content

Commit 2b08c39

Browse files
authored
feat: enhance Docker container management with advanced creation options, connection snippets, compose export, and database seeding (#26)
1 parent 88a6727 commit 2b08c39

File tree

211 files changed

+6038
-14741
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

211 files changed

+6038
-14741
lines changed

.agent/workflows/build-linux.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
description: Build Linux packages (Debian, Snap, AppImage)
3+
---
4+
5+
To build the application for Linux distributions, run the following command:
6+
7+
```bash
8+
# Builds .deb, .snap, and .AppImage packages
9+
npm run tauri build --prefix apps/desktop
10+
# OR
11+
cd apps/desktop && npm run tauri build
12+
```
13+
14+
This will output the artifacts to:
15+
`apps/desktop/src-tauri/target/release/bundle/`
16+
17+
- **Debian/Ubuntu**: `bundle/deb/*.deb`
18+
- **Snap**: `bundle/snap/*.snap`
19+
- **AppImage**: `bundle/appimage/*.AppImage`

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,10 @@ It is a single binary that works on any OS without any prerequisites. If you wan
7878
2. **Build the CLI**
7979
<small><i>Only needed if you want to modify the CLI</i></small>
8080
`bash
81-
cd tools/dora-cli
82-
go build -o ../../dora . # Outputs binary named 'dora' to root
83-
cd ../..
84-
`
81+
cd tools/dora-cli
82+
go build -o ../../dora . # Outputs binary named 'dora' to root
83+
cd ../..
84+
`
8585
This will output a binary named 'dora' to the root directory.
8686

8787
### Option 2: Manual Setup

apps/desktop/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"@radix-ui/react-aspect-ratio": "^1.1.7",
2424
"@radix-ui/react-avatar": "^1.1.10",
2525
"@radix-ui/react-checkbox": "^1.3.2",
26-
"@radix-ui/react-collapsible": "^1.1.11",
26+
"@radix-ui/react-collapsible": "^1.1.12",
2727
"@radix-ui/react-context-menu": "^2.2.16",
2828
"@radix-ui/react-dialog": "^1.1.14",
2929
"@radix-ui/react-dropdown-menu": "^2.1.15",
@@ -47,6 +47,7 @@
4747
"@radix-ui/react-tooltip": "^1.2.7",
4848
"@tanstack/react-query": "^5.83.0",
4949
"@tauri-apps/api": "^2.9.1",
50+
"@tauri-apps/plugin-fs": "^2.4.5",
5051
"@tauri-apps/plugin-shell": "^2.3.4",
5152
"class-variance-authority": "^0.7.1",
5253
"clsx": "^2.1.1",

apps/desktop/src-tauri/src/database/commands.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
use std::sync::Arc;
21
use uuid::Uuid;
32
use tauri::State;
4-
use serde_json::value::RawValue;
53

64
use crate::{
75
database::{
@@ -817,7 +815,7 @@ pub async fn duplicate_row(
817815
table_name: String,
818816
schema_name: Option<String>,
819817
primary_key_column: String,
820-
primary_key_value: serde_json::Value,
818+
_primary_key_value: serde_json::Value,
821819
state: State<'_, AppState>,
822820
) -> Result<MutationResult, Error> {
823821
// Fetch existing row data via a query

apps/desktop/src-tauri/src/database/postgres/execute.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ async fn execute_query_with_results(
4141
Ok(stmt) => stmt,
4242
Err(e) => {
4343
log::error!("Query preparation failed: {:?}", e);
44-
let error_msg = format!("Query failed: {}", e);
44+
let error_msg = if let Some(db_error) = e.as_db_error() {
45+
format!("Database error: {}", db_error.message())
46+
} else {
47+
format!("Query preparation failed: {}", e)
48+
};
4549

4650
sender.send(QueryExecEvent::Finished {
4751
elapsed_ms: started_at.elapsed().as_millis() as u64,
@@ -125,7 +129,11 @@ async fn execute_query_with_results(
125129
}
126130
Err(e) => {
127131
log::error!("Query execution failed: {:?}", e);
128-
let error_msg = format!("Query failed: {}", e);
132+
let error_msg = if let Some(db_error) = e.as_db_error() {
133+
format!("Database error: {}", db_error.message())
134+
} else {
135+
format!("Query execution failed: {}", e)
136+
};
129137

130138
sender.send(QueryExecEvent::Finished {
131139
elapsed_ms: started_at.elapsed().as_millis() as u64,
@@ -158,7 +166,11 @@ async fn execute_modification_query(
158166
}
159167
Err(e) => {
160168
log::error!("Modification query failed: {:?}", e);
161-
let error_msg = format!("Query failed: {}", e);
169+
let error_msg = if let Some(db_error) = e.as_db_error() {
170+
format!("Database error: {}", db_error.message())
171+
} else {
172+
format!("Modification query failed: {}", e)
173+
};
162174

163175
sender.send(QueryExecEvent::Finished {
164176
elapsed_ms: started_at.elapsed().as_millis() as u64,

apps/desktop/src-tauri/src/database/services/connection.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use uuid::Uuid;
66
use crate::{
77
credentials,
88
database::{
9-
postgres::{self, connect::connect},
9+
postgres::connect::connect,
1010
types::{
1111
ConnectionInfo, Database, DatabaseConnection, DatabaseInfo,
1212
},
@@ -172,6 +172,14 @@ impl<'a> ConnectionService<'a> {
172172
}
173173
}
174174

175+
// Check if already connected to avoid reconnection loops
176+
if let Some(connection_entry) = self.connections.get(&connection_id) {
177+
if connection_entry.connected {
178+
log::debug!("Already connected to database: {}", connection_id);
179+
return Ok(true);
180+
}
181+
}
182+
175183
let mut connection_entry = self
176184
.connections
177185
.get_mut(&connection_id)

apps/desktop/src-tauri/src/database/services/schema_export.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use anyhow::Context;
1111
use serde::{Deserialize, Serialize};
1212

1313
use crate::{
14-
database::types::{ColumnInfo, DatabaseSchema, ForeignKeyInfo, TableInfo},
14+
database::types::{ColumnInfo, DatabaseSchema, TableInfo},
1515
Error,
1616
};
1717

apps/desktop/src-tauri/src/database/services/seeding.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::sync::Arc;
22
use dashmap::DashMap;
33
use uuid::Uuid;
44
use serde::Serialize;
5-
use fake::{Fake, Faker};
5+
use fake::Fake;
66
use fake::faker::lorem::en::Sentence;
77
use fake::faker::name::en::{FirstName, LastName, Name};
88
use fake::faker::internet::en::{FreeEmail, Username};

apps/desktop/src-tauri/tauri.conf.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
33
"productName": "Dora",
4-
"version": "0.0.9",
4+
"version": "0.0.92",
55
"identifier": "com.Dora.dev",
66
"build": {
77
"frontendDist": "../dist",
@@ -20,7 +20,7 @@
2020
"height": 900,
2121
"resizable": true,
2222
"fullscreen": false,
23-
"decorations": true,
23+
"decorations": false,
2424
"transparent": true
2525
}
2626
],
@@ -31,7 +31,10 @@
3131
},
3232
"bundle": {
3333
"active": true,
34-
"targets": "all",
34+
"targets": ["deb", "snap", "appimage"],
35+
"shortDescription": "A modern database client",
36+
"longDescription": "Dora is a modern, fast, and efficient database client for PostgreSQL, SQLite, and more.",
37+
"category": "Development",
3538
"icon": [
3639
"icons/32x32.png",
3740
"icons/128x128.png",

apps/desktop/src/App.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
2-
import { BrowserRouter, Routes, Route } from "react-router-dom";
3-
import { DemoBanner } from "@/components/demo-banner";
4-
import { Toaster as Sonner } from "@/components/ui/sonner";
5-
import { Toaster } from "@/components/ui/toaster";
6-
import { DataProvider } from "@/core/data-provider";
7-
import { PendingEditsProvider } from "@/core/pending-edits";
8-
import { RecordingProvider, RecordingOverlay } from "@/core/recording";
9-
import { SettingsProvider, useSettings } from "@/core/settings";
10-
import { ThemeSync } from "@/features/sidebar/components/theme-sync";
11-
import Index from "./pages/Index";
12-
import NotFound from "./pages/NotFound";
1+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
2+
import { BrowserRouter, Routes, Route } from 'react-router-dom'
3+
import { DemoBanner } from '@/components/demo-banner'
4+
import { Toaster as Sonner } from '@/components/ui/sonner'
5+
import { Toaster } from '@/components/ui/toaster'
6+
import { DataProvider } from '@/core/data-provider'
7+
import { PendingEditsProvider } from '@/core/pending-edits'
8+
import { RecordingProvider, RecordingOverlay } from '@/core/recording'
9+
import { SettingsProvider, useSettings } from '@/core/settings'
10+
import { ThemeSync } from '@/features/sidebar/components/theme-sync'
11+
import Index from './pages/Index'
12+
import NotFound from './pages/NotFound'
1313

1414
const queryClient = new QueryClient()
1515

0 commit comments

Comments
 (0)