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
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