Skip to content

Commit 7f1b20e

Browse files
authored
feat: extract non-core plugins from app bundle to registry distribution (#317)
* Update Localizable.xcstrings * feat: extract MSSQL, MongoDB, Redis, XLSX, MQL, SQLImport plugins from app bundle * docs: update plugin distribution references across CI, docs, and skills * fix: remove SQLite from built-in plugins list in changelog * fix: make SQLite built-in, fix PR review feedback * fix: add per-plugin category to CI workflow, add missing DuckDB to plugin tables
1 parent 8d29ca8 commit 7f1b20e

11 files changed

Lines changed: 12354 additions & 12385 deletions

File tree

.claude/skills/release/SKILL.md

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,12 @@ and `CURRENT_PROJECT_VERSION = 1`:
8484
- **Test target** (TableProTests)
8585
- **TableProPluginKit** framework
8686
- **Bundled plugins** (included in app bundle): MySQLDriverPlugin,
87-
PostgreSQLDriverPlugin, MSSQLDriverPlugin, MongoDBDriverPlugin,
88-
RedisDriverPlugin, plus export/import plugins (CSV, JSON, SQL,
89-
XLSX, MQL export; SQL import)
87+
PostgreSQLDriverPlugin, SQLiteDriverPlugin, plus export plugins
88+
(CSV, JSON, SQL export)
9089
- **Separate plugin bundles** (not included in app bundle, distributed
9190
independently): OracleDriverPlugin, ClickHouseDriverPlugin,
92-
SQLiteDriverPlugin, DuckDBDriverPlugin
91+
DuckDBDriverPlugin, MSSQLDriverPlugin, MongoDBDriverPlugin,
92+
RedisDriverPlugin, XLSXExportPlugin, MQLExportPlugin, SQLImportPlugin
9393

9494
Use `replace_all: true` for each edit — the main app target's version
9595
values are always unique (e.g., `MARKETING_VERSION = 0.16.1` and
@@ -219,7 +219,8 @@ with the release in Step 3 — no separate commit needed.
219219
### Step 7: Check for Separate Plugin Changes
220220

221221
After the app release is pushed, check if any **separate plugin bundles**
222-
(Oracle, ClickHouse, SQLite, DuckDB) have changes since their last
222+
(Oracle, ClickHouse, DuckDB, MSSQL, MongoDB, Redis, XLSX, MQL,
223+
SQLImport) have changes since their last
223224
release. Also check `Plugins/TableProPluginKit/` — changes there affect
224225
all plugins.
225226

@@ -230,8 +231,13 @@ for commits:
230231
# Separate plugins and their directory + tag-name mappings:
231232
# Oracle: Plugins/OracleDriverPlugin/ plugin-oracle
232233
# ClickHouse: Plugins/ClickHouseDriverPlugin/ plugin-clickhouse
233-
# SQLite: Plugins/SQLiteDriverPlugin/ plugin-sqlite
234234
# DuckDB: Plugins/DuckDBDriverPlugin/ plugin-duckdb
235+
# MSSQL: Plugins/MSSQLDriverPlugin/ plugin-mssql
236+
# MongoDB: Plugins/MongoDBDriverPlugin/ plugin-mongodb
237+
# Redis: Plugins/RedisDriverPlugin/ plugin-redis
238+
# XLSX: Plugins/XLSXExportPlugin/ plugin-xlsx
239+
# MQL: Plugins/MQLExportPlugin/ plugin-mql
240+
# SQLImport: Plugins/SQLImportPlugin/ plugin-sqlimport
235241

236242
# For each plugin, find the latest tag:
237243
LAST_TAG=$(git tag -l "plugin-<name>-v*" --sort=-version:refname | head -1)
@@ -274,8 +280,9 @@ Plugin releases:
274280

275281
## Plugin Releases
276282

277-
Separate plugin bundles (Oracle, ClickHouse, SQLite, DuckDB) are released
278-
independently from the main app via a dedicated workflow
283+
Separate plugin bundles (Oracle, ClickHouse, DuckDB, MSSQL, MongoDB,
284+
Redis, XLSX, MQL, SQLImport) are released independently from the main
285+
app via a dedicated workflow
279286
(`.github/workflows/build-plugin.yml`). They are also checked
280287
automatically during app releases (Step 7 above).
281288

@@ -296,8 +303,8 @@ plugin-<name>-v<version>
296303
Examples: `plugin-oracle-v1.0.0`, `plugin-clickhouse-v1.2.0`
297304

298305
The `<name>` must match one of the cases in the workflow's mapping:
299-
`oracle`, `clickhouse` (sqlite and duckdb need to be added to the
300-
workflow's case statement when ready).
306+
`oracle`, `clickhouse`, `duckdb`, `cassandra`, `mssql`, `mongodb`,
307+
`redis`, `xlsx`, `mql`, `sqlimport`.
301308

302309
### Plugin Release Steps
303310

.github/workflows/build-plugin.yml

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,27 +57,57 @@ jobs:
5757
TARGET="OracleDriver"; BUNDLE_ID="com.TablePro.OracleDriver"
5858
DISPLAY_NAME="Oracle Driver"; SUMMARY="Oracle Database 12c+ driver via OracleNIO"
5959
DB_TYPE_IDS='["Oracle"]'; ICON="server.rack"; BUNDLE_NAME="OracleDriver"
60-
HOMEPAGE="https://docs.tablepro.app/databases/oracle" ;;
60+
CATEGORY="database-driver"; HOMEPAGE="https://docs.tablepro.app/databases/oracle" ;;
6161
clickhouse)
6262
TARGET="ClickHouseDriver"; BUNDLE_ID="com.TablePro.ClickHouseDriver"
6363
DISPLAY_NAME="ClickHouse Driver"; SUMMARY="ClickHouse OLAP database driver via HTTP interface"
6464
DB_TYPE_IDS='["ClickHouse"]'; ICON="chart.bar.xaxis"; BUNDLE_NAME="ClickHouseDriver"
65-
HOMEPAGE="https://docs.tablepro.app/databases/clickhouse" ;;
65+
CATEGORY="database-driver"; HOMEPAGE="https://docs.tablepro.app/databases/clickhouse" ;;
6666
sqlite)
6767
TARGET="SQLiteDriver"; BUNDLE_ID="com.TablePro.SQLiteDriver"
6868
DISPLAY_NAME="SQLite Driver"; SUMMARY="SQLite embedded database driver"
6969
DB_TYPE_IDS='["SQLite"]'; ICON="internaldrive"; BUNDLE_NAME="SQLiteDriver"
70-
HOMEPAGE="https://docs.tablepro.app/databases/sqlite" ;;
70+
CATEGORY="database-driver"; HOMEPAGE="https://docs.tablepro.app/databases/sqlite" ;;
7171
duckdb)
7272
TARGET="DuckDBDriver"; BUNDLE_ID="com.TablePro.DuckDBDriver"
7373
DISPLAY_NAME="DuckDB Driver"; SUMMARY="DuckDB analytical database driver"
7474
DB_TYPE_IDS='["DuckDB"]'; ICON="bird"; BUNDLE_NAME="DuckDBDriver"
75-
HOMEPAGE="https://docs.tablepro.app/databases/duckdb" ;;
75+
CATEGORY="database-driver"; HOMEPAGE="https://docs.tablepro.app/databases/duckdb" ;;
7676
cassandra)
7777
TARGET="CassandraDriver"; BUNDLE_ID="com.TablePro.CassandraDriver"
7878
DISPLAY_NAME="Cassandra Driver"; SUMMARY="Apache Cassandra and ScyllaDB driver via DataStax C driver"
7979
DB_TYPE_IDS='["Cassandra", "ScyllaDB"]'; ICON="cassandra-icon"; BUNDLE_NAME="CassandraDriver"
80-
HOMEPAGE="https://docs.tablepro.app/databases/cassandra" ;;
80+
CATEGORY="database-driver"; HOMEPAGE="https://docs.tablepro.app/databases/cassandra" ;;
81+
mssql)
82+
TARGET="MSSQLDriver"; BUNDLE_ID="com.TablePro.MSSQLDriver"
83+
DISPLAY_NAME="MSSQL Driver"; SUMMARY="Microsoft SQL Server driver via FreeTDS"
84+
DB_TYPE_IDS='["SQL Server"]'; ICON="mssql-icon"; BUNDLE_NAME="MSSQLDriver"
85+
CATEGORY="database-driver"; HOMEPAGE="https://docs.tablepro.app/databases/mssql" ;;
86+
mongodb)
87+
TARGET="MongoDBDriver"; BUNDLE_ID="com.TablePro.MongoDBDriver"
88+
DISPLAY_NAME="MongoDB Driver"; SUMMARY="MongoDB document database driver via libmongoc"
89+
DB_TYPE_IDS='["MongoDB"]'; ICON="mongodb-icon"; BUNDLE_NAME="MongoDBDriver"
90+
CATEGORY="database-driver"; HOMEPAGE="https://docs.tablepro.app/databases/mongodb" ;;
91+
redis)
92+
TARGET="RedisDriver"; BUNDLE_ID="com.TablePro.RedisDriver"
93+
DISPLAY_NAME="Redis Driver"; SUMMARY="Redis in-memory data store driver via hiredis"
94+
DB_TYPE_IDS='["Redis"]'; ICON="redis-icon"; BUNDLE_NAME="RedisDriver"
95+
CATEGORY="database-driver"; HOMEPAGE="https://docs.tablepro.app/databases/redis" ;;
96+
xlsx)
97+
TARGET="XLSXExport"; BUNDLE_ID="com.TablePro.XLSXExportPlugin"
98+
DISPLAY_NAME="XLSX Export"; SUMMARY="Export data to Microsoft Excel XLSX format"
99+
DB_TYPE_IDS='null'; ICON="doc.richtext"; BUNDLE_NAME="XLSXExport"
100+
CATEGORY="export-format"; HOMEPAGE="https://docs.tablepro.app/features/export" ;;
101+
mql)
102+
TARGET="MQLExport"; BUNDLE_ID="com.TablePro.MQLExportPlugin"
103+
DISPLAY_NAME="MQL Export"; SUMMARY="Export MongoDB data as MQL statements"
104+
DB_TYPE_IDS='null'; ICON="doc.text"; BUNDLE_NAME="MQLExport"
105+
CATEGORY="export-format"; HOMEPAGE="https://docs.tablepro.app/features/export" ;;
106+
sqlimport)
107+
TARGET="SQLImport"; BUNDLE_ID="com.TablePro.SQLImportPlugin"
108+
DISPLAY_NAME="SQL Import"; SUMMARY="Import data from SQL dump files"
109+
DB_TYPE_IDS='null'; ICON="square.and.arrow.down"; BUNDLE_NAME="SQLImport"
110+
CATEGORY="import-format"; HOMEPAGE="https://docs.tablepro.app/features/import" ;;
81111
*) echo "Unknown plugin: $plugin_name"; return 1 ;;
82112
esac
83113
}
@@ -157,7 +187,7 @@ jobs:
157187
"$BUNDLE_ID" "$DISPLAY_NAME" "$VERSION" "$SUMMARY" \
158188
"$DB_TYPE_IDS" "$ARM64_URL" "$ARM64_SHA" \
159189
"$X86_64_URL" "$X86_SHA" "$MIN_APP_VERSION" \
160-
"$ICON" "$HOMEPAGE" \
190+
"$ICON" "$HOMEPAGE" "$CATEGORY" \
161191
<<'PYTHON_SCRIPT'
162192
import json, sys
163193
@@ -166,6 +196,7 @@ jobs:
166196
arm64_url, arm64_sha = sys.argv[6], sys.argv[7]
167197
x86_64_url, x86_64_sha = sys.argv[8], sys.argv[9]
168198
min_app_version, icon, homepage = sys.argv[10], sys.argv[11], sys.argv[12]
199+
category = sys.argv[13] if len(sys.argv) > 13 else "database-driver"
169200
170201
with open("plugins.json", "r") as f:
171202
manifest = json.load(f)
@@ -174,7 +205,7 @@ jobs:
174205
"id": bundle_id, "name": name, "version": version,
175206
"summary": summary,
176207
"author": {"name": "TablePro", "url": "https://tablepro.app"},
177-
"homepage": homepage, "category": "database-driver",
208+
"homepage": homepage, "category": category,
178209
"databaseTypeIds": db_type_ids,
179210
"downloadURL": arm64_url, "sha256": arm64_sha,
180211
"binaries": [

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Changed
1111

12+
- Replaced fragmented Theme/DesignConstants/SQLEditorTheme/ToolbarDesignTokens with unified ThemeEngine
13+
- Moved editor and data grid font settings into the theme system (Settings > Appearance)
14+
- Extracted MSSQL, MongoDB, Redis, XLSX export, MQL export, and SQL import plugins from the app bundle into separately distributed plugins, downloadable from the plugin registry. MySQL, PostgreSQL, SQLite, CSV, JSON, and SQL export remain built-in
1215
- Redesigned Plugins settings tab with HSplitView master-detail layout: plugin list on the left, detail pane on the right, matching macOS conventions. Plugin rows now show version, author/capability, and install status at a glance
1316
- Download counts in browse tab now always fetch latest from GitHub API (5-minute in-memory cooldown per session)
1417
- Replaced ~40 hardcoded `DatabaseType` switches across ~20 UI files with dynamic plugin property lookups via `PluginManager`, so third-party plugins get correct UI behavior (colors, labels, editor language, feature toggles) automatically
@@ -28,6 +31,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2831

2932
### Added
3033

34+
- Full theme engine with 9 built-in presets (Default Light/Dark, Dracula, Solarized Light/Dark, One Dark, GitHub Light/Dark, Nord) and custom theme support
35+
- Theme browser with visual preview cards in Settings > Appearance
36+
- Per-theme customization of all colors (editor syntax, data grid, UI, sidebar, toolbar) and fonts
37+
- Theme import/export as JSON files for sharing
3138
- SSH TOTP/two-factor authentication support (auto-generate and prompt modes)
3239
- SSH host key verification with fingerprint confirmation
3340
- Keyboard Interactive SSH authentication method
@@ -47,7 +54,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4754
- SQL import options (wrap in transaction, disable FK checks) now persist across launches
4855
- `needsRestart` banner persists across app quit/relaunch after plugin uninstall
4956
- Copy as INSERT/UPDATE SQL statements from data grid context menu
50-
- Configurable font family and size for data grid (Settings > Data Grid > Font)
57+
- Configurable font family and size for data grid (now via theme customization in Settings > Appearance)
5158
- Plugin download count display in Browse Plugins — fetched from GitHub Releases API and cached for 1 hour
5259
- MSSQL query cancellation (`cancelQuery`) and lock timeout (`applyQueryTimeout`) support
5360
- `~/.pgpass` file support for PostgreSQL/Redshift connections with live validation in the connection form

CLAUDE.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
77
TablePro is a native macOS database client (SwiftUI + AppKit) — a fast, lightweight alternative to TablePlus. macOS 14.0+, Swift 5.9, Universal Binary (arm64 + x86_64).
88

99
- **Source**: `TablePro/``Core/` (business logic, services), `Views/` (UI), `Models/` (data structures), `ViewModels/`, `Extensions/`, `Theme/`
10-
- **Plugins**: `Plugins/`8 `.tableplugin` bundles (MySQL, PostgreSQL, SQLite, ClickHouse, MSSQL, MongoDB, Redis, Oracle) + `TableProPluginKit` shared framework
10+
- **Plugins**: `Plugins/``.tableplugin` bundles + `TableProPluginKit` shared framework. Built-in (bundled in app): MySQL, PostgreSQL, SQLite, CSV, JSON, SQL export. Separately distributed via plugin registry: ClickHouse, MSSQL, MongoDB, Redis, Oracle, DuckDB, XLSX, MQL, SQLImport
1111
- **C bridges**: Each plugin contains its own C bridge module (e.g., `Plugins/MySQLDriverPlugin/CMariaDB/`, `Plugins/PostgreSQLDriverPlugin/CLibPQ/`)
1212
- **Static libs**: `Libs/` — pre-built `libmariadb*.a`, `libpq*.a`, etc. (Git LFS tracked)
1313
- **SPM deps**: CodeEditSourceEditor (`main` branch, tree-sitter editor), Sparkle (2.8.1, auto-update), OracleNIO. Managed via Xcode, no `Package.swift`.
@@ -55,16 +55,17 @@ All database drivers are `.tableplugin` bundles loaded at runtime by `PluginMana
5555

5656
Plugin bundles under `Plugins/`:
5757

58-
| Plugin | Database Types | C Bridge |
59-
| ---------------------- | -------------------- | -------------------- |
60-
| MySQLDriverPlugin | MySQL, MariaDB | CMariaDB |
61-
| PostgreSQLDriverPlugin | PostgreSQL, Redshift | CLibPQ |
62-
| SQLiteDriverPlugin | SQLite | (Foundation sqlite3) |
63-
| ClickHouseDriverPlugin | ClickHouse | (URLSession HTTP) |
64-
| MSSQLDriverPlugin | SQL Server | CFreeTDS |
65-
| MongoDBDriverPlugin | MongoDB | CLibMongoc |
66-
| RedisDriverPlugin | Redis | CRedis |
67-
| OracleDriverPlugin | Oracle | OracleNIO (SPM) |
58+
| Plugin | Database Types | C Bridge | Distribution |
59+
| ---------------------- | -------------------- | -------------------- | ------------ |
60+
| MySQLDriverPlugin | MySQL, MariaDB | CMariaDB | Built-in |
61+
| PostgreSQLDriverPlugin | PostgreSQL, Redshift | CLibPQ | Built-in |
62+
| SQLiteDriverPlugin | SQLite | (Foundation sqlite3) | Built-in |
63+
| ClickHouseDriverPlugin | ClickHouse | (URLSession HTTP) | Registry |
64+
| MSSQLDriverPlugin | SQL Server | CFreeTDS | Registry |
65+
| MongoDBDriverPlugin | MongoDB | CLibMongoc | Registry |
66+
| RedisDriverPlugin | Redis | CRedis | Registry |
67+
| DuckDBDriverPlugin | DuckDB | CDuckDB | Registry |
68+
| OracleDriverPlugin | Oracle | OracleNIO (SPM) | Registry |
6869

6970
When adding a new driver: create a new plugin bundle under `Plugins/`, implement `DriverPlugin` + `PluginDatabaseDriver`, add target to pbxproj. See `docs/development/plugin-system/` for details.
7071

0 commit comments

Comments
 (0)