Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions .github/workflows/build-multiplatform.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Multi-Platform Build

on:
workflow_dispatch:
push:
tags:
- "v*"

jobs:
build:
name: Build (${{ matrix.platform }})
runs-on: ${{ matrix.os }}
timeout-minutes: 30

strategy:
fail-fast: false
matrix:
include:
- platform: linux
os: ubuntu-22.04
- platform: macos
os: macos-latest
- platform: windows
os: windows-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Cache Bun dependencies
uses: actions/cache@v4
with:
path: |
node_modules
~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-

- name: Install frontend dependencies
run: bun install --frozen-lockfile

- name: Setup Rust toolchain
uses: dtolnay/rust-toolchain@stable

- name: Cache Rust build artifacts
uses: Swatinem/rust-cache@v2
with:
workspaces: src-tauri -> src-tauri/target

- name: Install Linux dependencies
if: matrix.platform == 'linux'
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev

- name: Build Tauri app
run: bun tauri build

- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: dbpaw-${{ matrix.platform }}
path: |
src-tauri/target/release/bundle/
retention-days: 7
Comment on lines +11 to +71

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 2 months ago

In general, the fix is to add a permissions: block to the workflow (either at the root level or for the specific job) specifying the minimal permissions the GITHUB_TOKEN needs. For a pure build-and-artifact-upload workflow like this, contents: read is typically sufficient, since no step pushes code, creates releases, or modifies issues or pull requests.

The single best way to fix this without changing functionality is to add a root-level permissions: block right after the name: declaration. This will apply to all jobs in the workflow that do not set their own permissions. Based on the shown steps (checkout, caching, installing dependencies, building, and uploading artifacts), the workflow only needs read access to repository contents, so we set:

permissions:
  contents: read

You only need to edit .github/workflows/build-multiplatform.yml, inserting these lines near the top; no imports or additional methods are required.

Suggested changeset 1
.github/workflows/build-multiplatform.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/build-multiplatform.yml b/.github/workflows/build-multiplatform.yml
--- a/.github/workflows/build-multiplatform.yml
+++ b/.github/workflows/build-multiplatform.yml
@@ -1,5 +1,8 @@
 name: Multi-Platform Build
 
+permissions:
+  contents: read
+
 on:
   workflow_dispatch:
   push:
EOF
@@ -1,5 +1,8 @@
name: Multi-Platform Build

permissions:
contents: read

on:
workflow_dispatch:
push:
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +65 to +71

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

actions/upload-artifact@v4 if-no-files-found parameter

💡 Result:

The if-no-files-found parameter in actions/upload-artifact@v4 controls the action's behavior when no files match the provided path. It is optional with a default value of warn. Available options: - warn: Outputs a warning but does not fail the action (default). - error: Fails the action with an error message. - ignore: Outputs no warnings or errors, and the action does not fail. Example usage: - uses: actions/upload-artifact@v4 with: name: my-artifact path: path/to/artifact/ if-no-files-found: error This feature allows customization of the response when no files are found for upload, improving workflow reliability.

Citations:


Fail the workflow when no bundle is uploaded.

actions/upload-artifact@v4 defaults to warn mode when files are missing, allowing the workflow to pass even if the bundle directory is empty. Add if-no-files-found: error to catch missing artifacts immediately instead of silently passing.

📦 Make missing artifacts fail fast
       - name: Upload artifacts
         uses: actions/upload-artifact@v4
         with:
           name: dbpaw-${{ matrix.platform }}
           path: |
             src-tauri/target/release/bundle/
+          if-no-files-found: error
           retention-days: 7
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: dbpaw-${{ matrix.platform }}
path: |
src-tauri/target/release/bundle/
retention-days: 7
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: dbpaw-${{ matrix.platform }}
path: |
src-tauri/target/release/bundle/
if-no-files-found: error
retention-days: 7
🧰 Tools
🪛 GitHub Check: CodeQL

[warning] 11-71: Workflow does not contain permissions
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {{contents: read}}

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build-multiplatform.yml around lines 65 - 71, The upload
step named "Upload artifacts" using actions/upload-artifact@v4 should fail when
no files are found; update that step (the "Upload artifacts" job step
referencing actions/upload-artifact@v4) to include the if-no-files-found: error
option so the workflow errors out instead of only warning when the
src-tauri/target/release/bundle/ path is empty.

100 changes: 83 additions & 17 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,129 @@
pull_request:
branches:
- main
push:
branches:
- main

jobs:
test:
# Fast smoke tests run first to fail fast
smoke:
name: Smoke Tests (typecheck, lint, unit)
runs-on: ubuntu-22.04
timeout-minutes: 40
timeout-minutes: 10
Comment on lines +7 to +16

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Locate and read the CI workflow file
fd 'ci\.yml' --type f

Repository: codeErrorSleep/dbpaw

Length of output: 46


🏁 Script executed:

# Read the full CI workflow file to understand structure and existing permissions
cat -n '.github/workflows/ci.yml'

Repository: codeErrorSleep/dbpaw

Length of output: 4280


Set explicit GITHUB_TOKEN permissions in this workflow.

Currently, the workflow lacks an explicit permissions block at the workflow level. This means it depends on the repository or organization's default token policy, which may grant excessive permissions. Adding permissions: contents: read at the workflow level ensures all jobs (smoke, integration, and ci-success) operate with least-privilege access, since the only GitHub API interaction is actions/checkout@v4, which requires only read access to repository contents.

🔐 Suggested hardening
 on:
   pull_request:
     branches:
       - main
   push:
     branches:
       - main
+
+permissions:
+  contents: read
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
push:
branches:
- main
jobs:
test:
# Fast smoke tests run first to fail fast
smoke:
name: Smoke Tests (typecheck, lint, unit)
runs-on: ubuntu-22.04
timeout-minutes: 40
timeout-minutes: 10
push:
branches:
- main
permissions:
contents: read
jobs:
# Fast smoke tests run first to fail fast
smoke:
name: Smoke Tests (typecheck, lint, unit)
runs-on: ubuntu-22.04
timeout-minutes: 10
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yml around lines 7 - 16, Add a workflow-level
permissions block to restrict the GITHUB_TOKEN to least privilege by adding
"permissions: contents: read" at the top-level of the YAML (so it applies to all
jobs: smoke, integration, ci-success); locate the root of the workflow (near the
existing "push" and "jobs:" keys) and insert the "permissions" stanza so
actions/checkout@v4 continues to work while preventing broader token access.


steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Cache Bun dependencies
uses: actions/cache@v4
with:
path: |
node_modules
~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-

- name: Install frontend dependencies
run: bun install --frozen-lockfile

- name: Setup Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt

- name: Cache Rust build artifacts
uses: Swatinem/rust-cache@v2
with:
workspaces: src-tauri -> src-tauri/target

- name: Run unit tests
run: bun run test:unit
- name: Run smoke tests
run: bun run test:smoke

# Parallel database integration tests
integration:
Comment on lines 14 to +54

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 2 months ago

In general, this is fixed by explicitly defining a permissions block for the workflow (or each job) that grants only the minimal required scopes to GITHUB_TOKEN. For pure CI (checkout, cache, build, test, diagnostics), contents: read is typically sufficient. Since nothing in the provided workflow needs to write to the repository or perform privileged GitHub API operations, we can safely set permissions: contents: read at the workflow root so it applies to all jobs.

The best minimal fix without changing existing functionality is to add a root-level permissions block between the on: section and the jobs: section in .github/workflows/ci.yml. Concretely, insert:

permissions:
  contents: read

after line 10 (the last line of the on: block). This will cause all jobs (smoke, integration, and ci-success) to run with a read-only GITHUB_TOKEN. No additional methods, imports, or definitions are needed, and no existing steps need modification.

Suggested changeset 1
.github/workflows/ci.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -8,6 +8,9 @@
     branches:
       - main
 
+permissions:
+  contents: read
+
 jobs:
   # Fast smoke tests run first to fail fast
   smoke:
EOF
@@ -8,6 +8,9 @@
branches:
- main

permissions:
contents: read

jobs:
# Fast smoke tests run first to fail fast
smoke:
Copilot is powered by AI and may make mistakes. Always verify output.
name: Integration Tests (${{ matrix.database }})
runs-on: ubuntu-22.04
needs: smoke
timeout-minutes: 15

- name: Run service tests
run: bun run test:service
strategy:
fail-fast: false
matrix:
database:
- mysql
- postgres
- mariadb
- clickhouse
- mssql
- sqlite
- duckdb

- name: Run rust unit tests
run: bun run test:rust:unit
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Run integration tests (MySQL + Postgres with testcontainers)
run: IT_DB=all bun run test:integration
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Cache Bun dependencies
uses: actions/cache@v4
with:
path: |
node_modules
~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-

- name: Install frontend dependencies
run: bun install --frozen-lockfile

- name: Setup Rust toolchain
uses: dtolnay/rust-toolchain@stable

- name: Cache Rust build artifacts
uses: Swatinem/rust-cache@v2
with:
workspaces: src-tauri -> src-tauri/target
key: ${{ matrix.database }}

- name: Run ${{ matrix.database }} integration tests
run: IT_DB=${{ matrix.database }} bun run test:integration

- name: Docker diagnostics on failure
if: failure()
run: |
echo "==== docker ps -a ===="
docker ps -a || true
echo "==== recent mysql/postgres logs ===="
for image in mysql:8.0 postgres:16-alpine; do
for id in $(docker ps -aq --filter "ancestor=${image}"); do
echo "--- logs for $id (${image}) ---"
docker logs "$id" || true
done
done
echo "==== Container logs ===="
docker ps -aq | xargs -I {} sh -c 'echo "--- Container {} ---" && docker logs {} 2>&1 | tail -50' || true

# Summary job to check all tests passed
ci-success:
Comment on lines 55 to 115

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 2 months ago

In general, the fix is to add an explicit permissions block that grants only the minimal required scopes to the GITHUB_TOKEN. For a pure CI workflow that only reads the repository contents and runs tests, contents: read is typically sufficient. Adding this at the workflow root means all jobs (including integration) inherit these restricted permissions unless overridden.

The single best fix here without changing existing functionality is to add a root-level permissions section after the on: block and before jobs::

permissions:
  contents: read

This documents that the workflow needs only read access to repository contents and constrains GITHUB_TOKEN for smoke, integration, and ci-success. No other scopes appear needed given the current steps: all jobs only use actions/checkout, caching, language toolchains, and shell commands; none interact with issues, PRs, or packages. All modifications are within .github/workflows/ci.yml around the top of the file; no additional methods, imports, or definitions are required.

Suggested changeset 1
.github/workflows/ci.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -8,6 +8,9 @@
     branches:
       - main
 
+permissions:
+  contents: read
+
 jobs:
   # Fast smoke tests run first to fail fast
   smoke:
EOF
@@ -8,6 +8,9 @@
branches:
- main

permissions:
contents: read

jobs:
# Fast smoke tests run first to fail fast
smoke:
Copilot is powered by AI and may make mistakes. Always verify output.
name: CI Success
runs-on: ubuntu-22.04
needs: [smoke, integration]
if: always()

steps:
- name: Check all jobs succeeded
run: |
if [ "${{ needs.smoke.result }}" != "success" ]; then
echo "Smoke tests failed"
exit 1
fi
if [ "${{ needs.integration.result }}" != "success" ]; then
echo "Integration tests failed"
exit 1
fi
echo "All CI checks passed!"
Comment on lines 116 to 132

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {}

Copilot Autofix

AI 2 months ago

In general, the problem is fixed by explicitly specifying a permissions block in the workflow, limiting the GITHUB_TOKEN to only what is needed. For a pure CI workflow that just checks out code, uses caches, runs tests, and prints logs, contents: read is typically sufficient. Since none of the jobs perform write operations against the GitHub API (no pushes, PR writes, or issue updates), we can safely set read-only permissions at the workflow root, which then apply to all jobs (smoke, integration, and ci-success).

The best fix with minimal functional change is to add a top-level permissions section right after the name: CI (or anywhere at the root level) in .github/workflows/ci.yml and set contents: read. This documents the intended permissions and ensures that the workflow remains constrained even if organization defaults change. No additional imports, methods, or other changes are needed: only that YAML addition. All existing steps (checkout, cache, bun, rust, Docker diagnostics, and shell checks) will continue to work with read-only repository contents permissions.

Concretely:

  • Edit .github/workflows/ci.yml.
  • Insert:
permissions:
  contents: read
  • Place it at the root level, between name: CI and on:, keeping existing indentation and structure unchanged.
Suggested changeset 1
.github/workflows/ci.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,5 +1,8 @@
 name: CI
 
+permissions:
+  contents: read
+
 on:
   pull_request:
     branches:
EOF
@@ -1,5 +1,8 @@
name: CI

permissions:
contents: read

on:
pull_request:
branches:
Copilot is powered by AI and may make mistakes. Always verify output.
185 changes: 185 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

DbPaw is a cross-platform database client built with Tauri v2, supporting PostgreSQL, MySQL, MariaDB, TiDB, SQLite, SQL Server, ClickHouse, and DuckDB. The architecture separates frontend (React/TypeScript) from backend (Rust) with communication via Tauri commands.

## Essential Commands

### Development
- `bun install` - Install dependencies
- `bun dev:mock` - Frontend-only development with mock data (recommended for UI work)
- `bun tauri dev` - Full Tauri app with Rust backend (for end-to-end testing)
- `bun tauri build` - Production build

### Testing
For comprehensive testing documentation, see [TESTING.md](TESTING.md).

Quick reference:
- `bun run test:all` - Run all tests (unit, service, Rust, integration)
- `bun run test:unit` - Run TypeScript unit tests (files: `*.unit.test.ts`)
- `bun run test:service` - Run service layer tests (files: `*.service.test.ts`)
- `bun run test:rust:unit` - Run Rust unit tests (`cargo test --lib`)
- `bun run test:integration` - Run database integration tests (requires Docker)
- `IT_DB=mysql bun run test:integration` - Test specific database
- `IT_DB=all bun run test:integration` - Test all databases
- `IT_REUSE_LOCAL_DB=1` - Reuse existing local database containers
- `bun run test:smoke` - Quick validation (typecheck, lint, unit tests)
- `bun run test:ci` - Full CI test suite

### Code Quality
- `bun run typecheck` - TypeScript type checking
- `bun run lint` - Lint TypeScript/JSON files with Prettier
- `bun run lint:rust` - Check Rust code (`cargo check`)
- `bun run format` - Format TypeScript files with Prettier

### Website
- `bun run website:dev` - Run Astro marketing site locally
- `bun run website:build` - Build marketing site

## Architecture

### Frontend (React + TypeScript)

**Directory Structure:**
- `src/components/ui/` - Shadcn/UI components (base UI primitives)
- `src/components/business/` - Business logic components:
- `Editor/` - SQL editor (Monaco/CodeMirror)
- `DataGrid/` - Query results and table data display
- `Sidebar/` - Connection/database tree navigation
- `Metadata/` - Table structure and schema views
- `SqlLogs/` - Query execution history
- `src/components/settings/` - Settings dialogs
- `src/services/` - Tauri API wrapper and mocks
- `src/lib/` - Utilities (i18n, keyboard shortcuts, validation)
- `src/theme/` - Theme registry and management

**Key Patterns:**
- All Tauri backend calls go through `src/services/api.ts` which provides:
- Mock mode (`VITE_USE_MOCK=true`) for frontend-only development
- Type-safe wrappers around Tauri `invoke()` commands
- Runtime detection (`isTauri()`) to handle non-Tauri environments
- Path alias: `@/` maps to `./src/`
- i18n: Files in `src/lib/i18n/locales/` (en, zh, ja supported)

### Backend (Rust + Tauri)

**Core Modules:**
- `src-tauri/src/commands/` - Tauri command handlers (exposed to frontend):
- `connection.rs` - Connection CRUD and testing
- `query.rs` - Query execution and cancellation
- `metadata.rs` - Schema inspection (tables, structures, DDL)
- `storage.rs` - Saved queries persistence
- `ai.rs` - AI provider management and chat
- `transfer.rs` - Import/export operations
- `src-tauri/src/db/` - Database layer:
- `drivers/` - Per-database implementations (postgres, mysql, clickhouse, mssql, sqlite, duckdb)
- `pool_manager.rs` - Connection pooling with bb8
- `local.rs` - SQLite database for app metadata
- `src-tauri/src/state.rs` - Global app state (local DB + pool manager)
- `src-tauri/src/ssh.rs` - SSH tunnel support
- `src-tauri/src/ai/` - AI provider integration (OpenAI-compatible APIs)
- `src-tauri/src/models/` - Shared data types
- `src-tauri/src/error.rs` - Error handling

**Key Patterns:**
- All database drivers implement `DatabaseDriver` trait (see `src-tauri/src/db/drivers/mod.rs`)
- Connection pooling: Each database connection gets a managed pool via `PoolManager`
- State management: `AppState` holds `local_db` (SQLite) and `pool_manager`
- SSH tunneling: Transparent port forwarding for remote database access
- Error messages: Use `conn_failed_error()` to provide context-aware hints (TLS issues, auth failures, network problems)

### Testing Strategy

DbPaw uses a **3-layer testing approach** (see [TESTING.md](TESTING.md) for full details):

```
Frontend Layer → Unit tests (*.unit.test.ts) + Service tests (*.service.test.ts)
Tauri Commands → Command integration tests (*_command_integration.rs)
Database Drivers → Driver integration tests (*_integration.rs)
```

**Test Coverage by Database:**
- ✅ **MySQL & PostgreSQL**: Complete (driver + command + stateful tests)
- 🟢 **MariaDB, MSSQL, ClickHouse, SQLite, DuckDB**: Driver + command tests (stateful tests pending)

**TypeScript Tests:**
- Unit tests: `*.unit.test.ts` - Pure logic, no external dependencies
- Service tests: `*.service.test.ts` - Mock-based service layer tests
- Test runner: Bun's built-in test runner

**Rust Tests:**
- Unit tests: `#[test]` in source files, run with `cargo test --lib`
- Driver integration tests: `src-tauri/tests/<db>_integration.rs` - Direct driver method testing
- Command integration tests: `src-tauri/tests/<db>_command_integration.rs` - Ephemeral connection commands
- Stateful command tests: `src-tauri/tests/<db>_stateful_command_integration.rs` - Saved connection workflows
- All integration tests:
- Use testcontainers for real database instances
- Marked with `#[ignore]` (only run explicitly)
- Environment: `IT_DB` (mysql/postgres/mariadb/clickhouse/mssql/sqlite/duckdb/all)
- Helpers in `src-tauri/tests/common/` provide database context setup

### Database Driver Development

When adding/modifying database drivers:
1. Implement `DatabaseDriver` trait in `src-tauri/src/db/drivers/<driver>.rs`
2. Add to driver enum in `src-tauri/src/db/drivers/mod.rs`
3. Handle driver-specific connection strings and options
4. Use `conn_failed_error()` for user-friendly connection error messages
5. Add integration tests in `src-tauri/tests/<driver>_integration.rs`
6. Update `scripts/test-integration.sh` to include new driver

### Common Patterns

**Frontend-Backend Communication:**
```typescript
// Frontend
import { api } from '@/services/api';
const result = await api.execute_query(connectionId, database, sql);
```

```rust
// Backend
#[tauri::command]
async fn execute_query(
state: State<'_, AppState>,
connection_id: i64,
database: Option<String>,
sql: String,
) -> Result<QueryResult, String> {
// Implementation
}
```

**Mock Development:**
- Use `bun dev:mock` for rapid UI iteration without Rust compilation
- Mocks defined in `src/services/mocks.ts`
- Useful for working on: themes, UI components, layouts, i18n

**SSH Tunneling:**
- Handled transparently in connection layer
- SSH config in connection form, tunnel established before database connection
- Port forwarding lifetime managed with connection pool

## Build System

- Frontend: Vite with React plugin and TailwindCSS
- Backend: Cargo with sqlx (compile-time SQL checking disabled), tiberius (SQL Server), bb8 (pooling)
- Platform toolchain: Follows Tauri v2 prerequisites (see https://tauri.app/start/prerequisites/)
- Package manager: Bun (preferred) or npm/pnpm

## CI/GitHub Actions

- `.github/workflows/ci.yml` - Main CI pipeline
- Tests run on: Ubuntu (Linux), macOS, Windows
- Integration tests use Docker containers (testcontainers)
- Release builds triggered on tags

## Translation/i18n

- Framework: i18next + react-i18next
- Locale files: `src/lib/i18n/locales/*.ts` (TypeScript, not JSON)
- Supported: English (en), Chinese (zh), Japanese (ja)
- To add language: Create locale file and register in `src/lib/i18n/index.ts`
Loading
Loading