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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Confirmation dialogs for deep link queries, connection imports, and pre-connect scripts

## [0.25.0] - 2026-03-27

### Added
Expand Down
30 changes: 25 additions & 5 deletions TablePro/AppDelegate+FileOpen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ extension AppDelegate {
let deeplinks = urls.filter { $0.scheme == "tablepro" }
if !deeplinks.isEmpty {
Task { @MainActor in
for url in deeplinks { self.handleDeeplink(url) }
for url in deeplinks { await self.handleDeeplink(url) }
}
}

Expand Down Expand Up @@ -115,7 +115,7 @@ extension AppDelegate {

// MARK: - Deeplink Handling

private func handleDeeplink(_ url: URL) {
private func handleDeeplink(_ url: URL) async {
guard let action = DeeplinkHandler.parse(url) else { return }

switch action {
Expand All @@ -129,14 +129,23 @@ extension AppDelegate {
}

case .openQuery(let name, let sql):
let preview = (sql as NSString).length > 300 ? String(sql.prefix(300)) + "…" : sql
let confirmed = await AlertHelper.confirmDestructive(
title: String(localized: "Open Query from Link"),
message: String(localized: "An external link wants to open a query on connection \"\(name)\":\n\n\(preview)"),
confirmButton: String(localized: "Open Query"),
cancelButton: String(localized: "Cancel"),
window: NSApp.keyWindow
)
guard confirmed else { return }
connectViaDeeplink(connectionName: name) { connectionId in
EditorTabPayload(connectionId: connectionId, tabType: .query,
initialQuery: sql)
}

case .importConnection(let name, let host, let port, let type, let username, let database):
handleImportDeeplink(name: name, host: host, port: port, type: type,
username: username, database: database)
await handleImportDeeplink(name: name, host: host, port: port, type: type,
username: username, database: database)
}
}

Expand Down Expand Up @@ -193,7 +202,18 @@ extension AppDelegate {
private func handleImportDeeplink(
name: String, host: String, port: Int,
type: DatabaseType, username: String, database: String
) {
) async {
let userPart = username.isEmpty ? "" : "\(username)@"
let details = "\(type.rawValue)://\(userPart)\(host):\(port)/\(database)"
let confirmed = await AlertHelper.confirmDestructive(
title: String(localized: "Import Connection from Link"),
message: String(localized: "An external link wants to add a database connection:\n\nName: \(name)\n\(details)"),
confirmButton: String(localized: "Add Connection"),
cancelButton: String(localized: "Cancel"),
window: NSApp.keyWindow
)
guard confirmed else { return }

let connection = DatabaseConnection(
name: name, host: host, port: port,
database: database, username: username, type: type
Expand Down
17 changes: 17 additions & 0 deletions TablePro/Core/Database/DatabaseManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Created by Ngo Quoc Dat on 16/12/25.
//

import AppKit
import Foundation
import Observation
import os
Expand Down Expand Up @@ -123,6 +124,22 @@ final class DatabaseManager {
if let script = resolvedConnection.preConnectScript,
!script.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
{
let confirmed = await AlertHelper.confirmDestructive(
title: String(localized: "Pre-Connect Script"),
message: String(localized: "Connection \"\(connection.name)\" has a script that will run before connecting:\n\n\(script)"),
confirmButton: String(localized: "Run Script"),
cancelButton: String(localized: "Cancel"),
window: NSApp.keyWindow
)

guard confirmed else {
removeSessionEntry(for: connection.id)
currentSessionId = nil
throw PreConnectHookRunner.HookError.scriptFailed(
exitCode: 1, stderr: "User cancelled pre-connect script"
)
}

do {
try await PreConnectHookRunner.run(script: script)
} catch {
Expand Down
4 changes: 2 additions & 2 deletions docs/features/deep-links.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ open "tablepro://connect/Production/database/analytics/table/events"
tablepro://connect/{name}/query?sql={encoded_sql}
```

Connects and opens a new query tab with the SQL pre-filled. The SQL must be percent-encoded.
Connects and opens a new query tab with the SQL pre-filled. The SQL must be percent-encoded. A confirmation dialog shows the SQL before opening, so you can verify the query is safe.

```bash
open "tablepro://connect/Production/query?sql=SELECT%20*%20FROM%20users%20LIMIT%2010"
Expand All @@ -123,7 +123,7 @@ open "tablepro://connect/Production/query?sql=SELECT%20*%20FROM%20users%20LIMIT%
tablepro://import?name={n}&host={h}&port={p}&type={t}&username={u}&database={db}
```

Creates a new saved connection and opens the connection form for review. You can add a password before connecting.
Creates a new saved connection and opens the connection form for review. A confirmation dialog shows the connection details before adding, so you can reject unexpected imports. You can add a password before connecting.

```bash
open "tablepro://import?name=Staging&host=db.example.com&port=5432&type=postgresql&username=admin&database=mydb"
Expand Down
Loading