Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.tablepro.app/llms.txt

Use this file to discover all available pages before exploring further.

Architecture

TablePro is built with:
  • SwiftUI for the UI layer
  • AppKit for low-level macOS integration (windows, menus, native tabs)
  • Swift Concurrency (async/await, actors) for all async work
  • Native C libraries for database connectivity (linked as static .a files)

Design Patterns

MVVM

  • Models: structs (value types, Codable)
  • ViewModels: @Observable classes (Swift 5.9+)
  • Views: SwiftUI, with AppKit bridging where needed

Protocol-Oriented Drivers

All database connectivity goes through one protocol:
protocol DatabaseDriver: AnyObject {
    func connect() async throws
    func disconnect()
    func execute(query: String) async throws -> QueryResult
    func fetchTables() async throws -> [TableInfo]
    // ...
}
No switch statements on database type. No hardcoded driver list. Plugins register themselves, and the factory resolves them by DatabaseType.pluginTypeId.

Actor Isolation

Thread-safe shared state uses Swift actors:
actor SSHTunnelManager {
    private var tunnels: [UUID: SSHTunnel] = [:]
    func createTunnel(connectionId: UUID, ...) async throws -> Int { ... }
}

Dependencies

PackagePurpose
CodeEditSourceEditorTree-sitter SQL editor
Sparkle (2.8.1)Auto-update with EdDSA signing
OracleNIOOracle driver (SPM, used by OracleDriverPlugin)
CodeEditSourceEditor bundles a SwiftLint plugin, which is why -skipPackagePluginValidation is required for CLI builds.

Plugin System

All database drivers are .tableplugin bundles loaded at runtime. This keeps the app binary small and makes adding new databases a matter of dropping in a bundle. Key files:
ComponentLocationRole
TableProPluginKitPlugins/TableProPluginKit/Shared framework with DriverPlugin and PluginDatabaseDriver protocols
PluginManagerCore/Plugins/PluginManager.swiftDiscovers, loads, version-checks plugin bundles
PluginDriverAdapterCore/Plugins/PluginDriverAdapter.swiftBridges PluginDatabaseDriver to core DatabaseDriver
DatabaseDriverFactoryCore/Database/DatabaseDriver.swiftResolves DatabaseType to loaded plugin

Driver Plugins

PluginDatabase TypesC BridgeDistribution
MySQLDriverPluginMySQL, MariaDBCMariaDB (libmariadb)Built-in
PostgreSQLDriverPluginPostgreSQL, RedshiftCLibPQ (libpq)Built-in
SQLiteDriverPluginSQLiteFoundation sqlite3Built-in
ClickHouseDriverPluginClickHouseURLSession HTTPBuilt-in
MSSQLDriverPluginSQL ServerCFreeTDSBuilt-in
RedisDriverPluginRedisCRedisBuilt-in
MongoDBDriverPluginMongoDBCLibMongocRegistry
DuckDBDriverPluginDuckDBCDuckDBRegistry
OracleDriverPluginOracleOracleNIO (SPM)Registry
CassandraDriverPluginCassandra, ScyllaDBCCassandraRegistry
EtcdDriverPluginEtcdgRPC/HTTPRegistry
CloudflareD1PluginCloudflare D1URLSession HTTPRegistry
DynamoDBDriverPluginDynamoDBAWS SDKRegistry
BigQueryDriverPluginBigQueryURLSession RESTRegistry
Built-in plugins ship inside the app bundle. Registry plugins are downloaded on demand from the plugin registry.

Key Components

DatabaseManager

Connection pool and lifecycle management. Primary interface between UI and drivers. Handles connect, disconnect, reconnect, and session tracking.

ConnectionHealthMonitor

Pings active connections every 30 seconds. Auto-reconnects with exponential backoff on failure.

Autocomplete Engine

  • CompletionEngine: entry point, produces ranked suggestions
  • SQLContextAnalyzer: parses cursor position context (table ref, column ref, keyword)
  • SQLSchemaProvider: actor that caches and serves schema data

MCP Layer

The MCP server lives under Core/MCP/ and is split into five horizontal layers. Each layer talks only to the layer below it. Wire: pure Codable types, no I/O. JSON-RPC 2.0, strict-CRLF HTTP, SSE encoder/decoder. Transport: HTTP server uses NWListener and binds to 127.0.0.1:<port> by default. The stream endpoints (exchanges, listenerState) are bounded AsyncStreams consumed by MCPServerManager. The bridge’s client-side transport uses URLSession.bytes(for:) for incremental SSE. Session: MCPSessionStore is an actor that owns session lifecycle. Idle timeout is 15 minutes. Token revocation marks sessions with .tokenRevoked and the SSE stream emits a typed terminate comment so clients can distinguish revoke from network blip. Protocol: MCPProtocolDispatcher spawns a child Task per inbound exchange, so two concurrent tool calls run in parallel instead of queueing on the dispatcher actor. Per-request cancellation flows through MCPInflightRegistry. Long-running tools emit notifications/progress to clients that pass _meta.progressToken. Bridge: tablepro-mcp is a 50-line composition root. MCPStdioMessageTransport host-side, MCPStreamableHttpClientTransport upstream. Errors land in os_log and stderr. The host-facing transport writes only validated JsonRpcMessage bytes to stdout. The server accepts protocol versions 2025-03-26, 2025-06-18, and 2025-11-25. See Versioning for the negotiation rules and the additive-within-major-version stability policy.

Data Flow

Connection

Query Execution

State Management

PatternWhatWhere
@ObservableUI state, sessions, active tabViewModels
@AppStorageUser preferencesSettings
KeychainConnection passwordsConnectionStorage
SQLite FTS5Query history (full-text search)QueryHistoryStorage
JSON filesTab state persistenceTabStateStorage

Directory Structure

TablePro
Core
Autocomplete
SSH
ViewModels
Extensions
Theme
Resources
Plugins
TableProPluginKit
MySQLDriverPlugin
PostgreSQLDriverPlugin
SQLiteDriverPlugin
ClickHouseDriverPlugin
MSSQLDriverPlugin
RedisDriverPlugin
...
Libs
TableProTests
scripts