Skip to content
Open
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
16 changes: 16 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Environment variables for Open Data Diff

# Sidecar configuration
PORT=3001
LOG_LEVEL=info
NODE_ENV=development

# Database connection examples (for testing)
# MSSQL_HOST=localhost
# MSSQL_PORT=1433
# MSSQL_DATABASE=TestDB
# MSSQL_USERNAME=sa
# MSSQL_PASSWORD=YourPassword

# Plugin directory (optional)
# PLUGIN_DIRECTORY=./plugins
61 changes: 61 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

# Tauri
src-tauri/target

# Sidecar
sidecar/dist
sidecar/node_modules

# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# Database files
*.db
*.sqlite
*.sqlite3

# OS generated files
Thumbs.db
.DS_Store

# IDE
.vscode/
.idea/
*.swp
*.swo

# Rust
target/
Cargo.lock

# Build artifacts
build/
out/
114 changes: 112 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,115 @@
# open-data-diff
Open source database comparison tool
# Open Data Diff

An open-source database comparison tool built with Tauri, React, TypeScript, and Node.js. Compare database schemas and data across different database systems with an intuitive desktop interface.

## Features

- πŸ” **Schema Comparison**: Compare tables, columns, indexes, foreign keys, views, procedures, and functions
- πŸ“Š **Data Comparison**: Compare row counts and detect data mismatches
- πŸ”Œ **Plugin System**: Extensible architecture for adding new database drivers
- πŸ–₯️ **Desktop App**: Cross-platform desktop application built with Tauri
- πŸ›‘οΈ **Windows Authentication**: Built-in support for MS SQL Server with Windows authentication
- ⚑ **Fast Performance**: Rust backend with Node.js sidecar for database operations

## Supported Databases

### Built-in Support
- βœ… **Microsoft SQL Server** (with Windows Authentication)

### Coming Soon (Plugin System)
- πŸ”„ MySQL
- πŸ”„ PostgreSQL
- πŸ”„ SQLite
- πŸ”„ MongoDB

## Architecture

- **Frontend**: React + TypeScript + Tailwind CSS
- **Backend**: Tauri (Rust) + Node.js sidecar
- **Database Drivers**: Plugin-based architecture
- **Communication**: Tauri commands + REST API

## Prerequisites

- [Node.js](https://nodejs.org/) (v18 or later)
- [Rust](https://rustup.rs/) (latest stable)
- [Tauri CLI](https://tauri.app/v1/guides/getting-started/prerequisites)

## Installation

1. **Clone the repository**
```bash
git clone https://github.com/your-username/open-data-diff.git
cd open-data-diff
```

2. **Install dependencies**
```bash
# Install main project dependencies
npm install

# Install sidecar dependencies
cd sidecar
npm install
cd ..
```

3. **Build the sidecar**
```bash
npm run sidecar:build
```

4. **Run in development mode**
```bash
npm run tauri:dev
```

## Building for Production

```bash
# Build the sidecar first
npm run sidecar:build

# Build the Tauri application
npm run tauri:build
```

## Usage

1. **Launch the application**
2. **Configure source database connection**
- Enter connection details (host, port, database name)
- Choose authentication method (Windows Auth or SQL Auth)
- Test the connection
3. **Configure target database connection**
4. **Click "Compare Databases"**
5. **Review the comparison results**
- Schema differences (tables, columns, indexes, etc.)
- Data differences (row counts, data mismatches)

## Plugin Development

Create custom database drivers by implementing the `DatabaseDriver` interface:

```typescript
interface DatabaseDriver {
name: string;
testConnection(connection: any): Promise<boolean>;
getSchema(connection: any): Promise<DatabaseSchema>;
executeQuery(connection: any, query: string): Promise<any[]>;
disconnect(): Promise<void>;
}
```

See the [Plugin Development Guide](docs/plugin-development.md) for detailed instructions.

## Contributing

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## License

Expand Down
174 changes: 174 additions & 0 deletions docs/plugin-development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# Plugin Development Guide

This guide explains how to create custom database drivers for Open Data Diff.

## Plugin Structure

A plugin is a Node.js module that exports a function returning a `DatabaseDriver` implementation.

### Directory Structure
```
my-plugin/
β”œβ”€β”€ package.json
β”œβ”€β”€ index.js (or index.ts)
└── README.md
```

### package.json Requirements
```json
{
"name": "my-database-plugin",
"version": "1.0.0",
"description": "Custom database driver for MyDB",
"main": "index.js",
"databaseDriver": "mydb",
"author": "Your Name",
"keywords": ["database", "open-data-diff", "plugin"]
}
```

The `databaseDriver` field is required and specifies the driver name.

## DatabaseDriver Interface

```typescript
interface DatabaseDriver {
name: string;
testConnection(connection: any): Promise<boolean>;
getSchema(connection: any): Promise<DatabaseSchema>;
executeQuery(connection: any, query: string): Promise<any[]>;
disconnect(): Promise<void>;
}
```

### Methods

#### `testConnection(connection)`
Tests if a connection can be established to the database.
- **Parameters**: Connection configuration object
- **Returns**: `Promise<boolean>` - true if connection successful

#### `getSchema(connection)`
Retrieves the complete database schema.
- **Parameters**: Connection configuration object
- **Returns**: `Promise<DatabaseSchema>` - schema object with tables, views, etc.

#### `executeQuery(connection, query)`
Executes a SQL query and returns results.
- **Parameters**:
- `connection`: Connection configuration object
- `query`: SQL query string
- **Returns**: `Promise<any[]>` - array of result rows

#### `disconnect()`
Closes all connections and cleans up resources.
- **Returns**: `Promise<void>`

## Example Plugin

```javascript
// index.js
const mysql = require('mysql2/promise');

class MySQLDriver {
constructor() {
this.name = 'mysql';
this.pools = new Map();
}

async testConnection(connection) {
try {
const pool = await this.getPool(connection);
const [rows] = await pool.execute('SELECT 1 as test');
return rows.length > 0;
} catch (error) {
return false;
}
}

async getSchema(connection) {
const pool = await this.getPool(connection);

// Implement schema retrieval logic
const tables = await this.getTables(pool);
const views = await this.getViews(pool);

return {
tables,
views,
procedures: [],
functions: []
};
}

async executeQuery(connection, query) {
const pool = await this.getPool(connection);
const [rows] = await pool.execute(query);
return rows;
}

async disconnect() {
for (const pool of this.pools.values()) {
await pool.end();
}
this.pools.clear();
}

async getPool(connection) {
const key = `${connection.host}:${connection.port}:${connection.database}`;

if (!this.pools.has(key)) {
const pool = mysql.createPool({
host: connection.host,
port: connection.port || 3306,
user: connection.username,
password: connection.password,
database: connection.database,
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});

this.pools.set(key, pool);
}

return this.pools.get(key);
}

// Implement getTables, getViews, etc.
}

module.exports = function() {
return new MySQLDriver();
};
```

## Installation

1. Place your plugin directory in the `plugins/` folder of the application
2. The plugin will be automatically discovered on startup
3. Load the plugin through the UI or API

## Best Practices

- Always handle connection errors gracefully
- Implement proper connection pooling
- Clean up resources in the `disconnect()` method
- Use parameterized queries to prevent SQL injection
- Follow the schema format exactly as defined in the types
- Test your plugin thoroughly with different connection scenarios

## Schema Format

Ensure your `getSchema()` method returns data in the correct format:

```typescript
interface DatabaseSchema {
tables: TableSchema[];
views: ViewSchema[];
procedures: ProcedureSchema[];
functions: FunctionSchema[];
}
```

See the TypeScript definitions in `src/types/database.ts` for complete schema structure.
13 changes: 13 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Open Data Diff</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading