Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
9 changes: 7 additions & 2 deletions .github/workflows/build-plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ jobs:
DISPLAY_NAME="Redis Driver"; SUMMARY="Redis in-memory data store driver via hiredis"
DB_TYPE_IDS='["Redis"]'; ICON="redis-icon"; BUNDLE_NAME="RedisDriver"
CATEGORY="database-driver"; HOMEPAGE="https://docs.tablepro.app/databases/redis" ;;
cloudflare-d1)
TARGET="CloudflareD1DriverPlugin"; BUNDLE_ID="com.TablePro.CloudflareD1DriverPlugin"
DISPLAY_NAME="Cloudflare D1 Driver"; SUMMARY="Cloudflare D1 serverless SQLite-compatible database driver via REST API"
DB_TYPE_IDS='["Cloudflare D1"]'; ICON="cloudflare-d1-icon"; BUNDLE_NAME="CloudflareD1DriverPlugin"
CATEGORY="database-driver"; HOMEPAGE="https://docs.tablepro.app/databases/cloudflare-d1" ;;
xlsx)
TARGET="XLSXExport"; BUNDLE_ID="com.TablePro.XLSXExportPlugin"
DISPLAY_NAME="XLSX Export"; SUMMARY="Export data to Microsoft Excel XLSX format"
Expand All @@ -174,8 +179,8 @@ jobs:
esac
}

PLUGIN_NAME=$(echo "$TAG" | sed -E 's/^plugin-([a-z]+)-v.*$/\1/')
VERSION=$(echo "$TAG" | sed -E 's/^plugin-[a-z]+-v(.*)$/\1/')
PLUGIN_NAME=$(echo "$TAG" | sed -E 's/^plugin-([a-z0-9-]+)-v([0-9].*)$/\1/')
VERSION=$(echo "$TAG" | sed -E 's/^plugin-([a-z0-9-]+)-v([0-9].*)$/\2/')

resolve_plugin_info "$PLUGIN_NAME"

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Cloudflare D1 database support
- Match highlighting in autocomplete suggestions (matched characters shown in bold)
- Loading spinner in autocomplete popup while fetching column metadata

Expand Down
105 changes: 105 additions & 0 deletions Plugins/CloudflareD1DriverPlugin/CloudflareD1Plugin.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
//
// CloudflareD1Plugin.swift
// TablePro
//

import Foundation
import os
import TableProPluginKit

final class CloudflareD1Plugin: NSObject, TableProPlugin, DriverPlugin {
static let pluginName = "Cloudflare D1 Driver"
static let pluginVersion = "1.0.0"
static let pluginDescription = "Cloudflare D1 serverless SQLite-compatible database support via REST API"
static let capabilities: [PluginCapability] = [.databaseDriver]

static let databaseTypeId = "Cloudflare D1"
static let databaseDisplayName = "Cloudflare D1"
static let iconName = "cloudflare-d1-icon"
static let defaultPort = 0

// MARK: - UI/Capability Metadata

static let connectionMode: ConnectionMode = .apiOnly
static let supportsSSH = false
static let supportsSSL = false
static let isDownloadable = true
static let supportsImport = false
static let supportsSchemaEditing = false
static let databaseGroupingStrategy: GroupingStrategy = .flat
static let brandColorHex = "#F6821F"
static let urlSchemes: [String] = ["d1"]

static let explainVariants: [ExplainVariant] = [
ExplainVariant(id: "plan", label: "Query Plan", sqlPrefix: "EXPLAIN QUERY PLAN")
]

static let structureColumnFields: [StructureColumnField] = [.name, .type, .nullable, .defaultValue]

static let columnTypesByCategory: [String: [String]] = [
"Integer": ["INTEGER", "INT", "TINYINT", "SMALLINT", "MEDIUMINT", "BIGINT"],
"Float": ["REAL", "DOUBLE", "FLOAT", "NUMERIC", "DECIMAL"],
"String": ["TEXT", "VARCHAR", "CHARACTER", "CHAR", "CLOB", "NVARCHAR", "NCHAR"],
"Date": ["DATE", "TIME", "DATETIME", "TIMESTAMP"],
"Binary": ["BLOB"],
"Boolean": ["BOOLEAN"]
]

static let sqlDialect: SQLDialectDescriptor? = SQLDialectDescriptor(
identifierQuote: "\"",
keywords: [
"SELECT", "FROM", "WHERE", "JOIN", "INNER", "LEFT", "RIGHT", "OUTER", "CROSS",
"ON", "AND", "OR", "NOT", "IN", "LIKE", "GLOB", "BETWEEN", "AS",
"ORDER", "BY", "GROUP", "HAVING", "LIMIT", "OFFSET",
"INSERT", "INTO", "VALUES", "UPDATE", "SET", "DELETE",
"CREATE", "ALTER", "DROP", "TABLE", "INDEX", "VIEW", "TRIGGER",
"PRIMARY", "KEY", "FOREIGN", "REFERENCES", "UNIQUE", "CONSTRAINT",
"ADD", "COLUMN", "RENAME",
"NULL", "IS", "ASC", "DESC", "DISTINCT", "ALL",
"CASE", "WHEN", "THEN", "ELSE", "END", "COALESCE", "IFNULL", "NULLIF",
"UNION", "INTERSECT", "EXCEPT",
"AUTOINCREMENT", "WITHOUT", "ROWID", "PRAGMA",
"REPLACE", "ABORT", "FAIL", "IGNORE", "ROLLBACK",
"TEMP", "TEMPORARY", "VACUUM", "EXPLAIN", "QUERY", "PLAN"
],
functions: [
"COUNT", "SUM", "AVG", "MAX", "MIN", "GROUP_CONCAT", "TOTAL",
"LENGTH", "SUBSTR", "SUBSTRING", "LOWER", "UPPER", "TRIM", "LTRIM", "RTRIM",
"REPLACE", "INSTR", "PRINTF",
"DATE", "TIME", "DATETIME", "JULIANDAY", "STRFTIME",
"ABS", "ROUND", "RANDOM",
"CAST", "TYPEOF",
"COALESCE", "IFNULL", "NULLIF", "HEX", "QUOTE"
],
dataTypes: [
"INTEGER", "REAL", "TEXT", "BLOB", "NUMERIC",
"INT", "TINYINT", "SMALLINT", "MEDIUMINT", "BIGINT",
"UNSIGNED", "BIG", "INT2", "INT8",
"CHARACTER", "VARCHAR", "VARYING", "NCHAR", "NATIVE",
"NVARCHAR", "CLOB",
"DOUBLE", "PRECISION", "FLOAT",
"DECIMAL", "BOOLEAN", "DATE", "DATETIME"
],
tableOptions: [
"WITHOUT ROWID", "STRICT"
],
regexSyntax: .unsupported,
booleanLiteralStyle: .numeric,
likeEscapeStyle: .explicit,
paginationStyle: .limit
)

static let additionalConnectionFields: [ConnectionField] = [
ConnectionField(
id: "cfAccountId",
label: String(localized: "Account ID"),
placeholder: "Cloudflare Account ID",
required: true,
section: .authentication
)
]

func createDriver(config: DriverConnectionConfig) -> any PluginDatabaseDriver {
CloudflareD1PluginDriver(config: config)
}
}
Loading
Loading