|
@@ -0,0 +1,155 @@
|
|
|
+import {
|
|
|
+ CompiledQuery,
|
|
|
+ DatabaseConnection,
|
|
|
+ DatabaseIntrospector,
|
|
|
+ Dialect,
|
|
|
+ Driver,
|
|
|
+ Kysely,
|
|
|
+ SqliteAdapter,
|
|
|
+ SqliteIntrospector,
|
|
|
+ SqliteQueryCompiler,
|
|
|
+ QueryCompiler,
|
|
|
+ QueryResult,
|
|
|
+} from 'kysely'
|
|
|
+import Database from '@tauri-apps/plugin-sql'
|
|
|
+
|
|
|
+/**
|
|
|
+ * Config for the D1 dialect. Pass your D1 instance to this object that you bound in `wrangler.toml`.
|
|
|
+ */
|
|
|
+export interface D1DialectConfig {
|
|
|
+ database: Database
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * D1 dialect that adds support for [Cloudflare D1][0] in [Kysely][1].
|
|
|
+ * The constructor takes the instance of your D1 database that you bound in `wrangler.toml`.
|
|
|
+ *
|
|
|
+ * ```typescript
|
|
|
+ * new D1Dialect({
|
|
|
+ * database: env.DB,
|
|
|
+ * })
|
|
|
+ * ```
|
|
|
+ *
|
|
|
+ * [0]: https://blog.cloudflare.com/introducing-d1/
|
|
|
+ * [1]: https://github.com/koskimas/kysely
|
|
|
+ */
|
|
|
+export class D1Dialect implements Dialect {
|
|
|
+ #config: D1DialectConfig
|
|
|
+
|
|
|
+ constructor(config: D1DialectConfig) {
|
|
|
+ this.#config = config
|
|
|
+ }
|
|
|
+
|
|
|
+ createAdapter() {
|
|
|
+ return new SqliteAdapter()
|
|
|
+ }
|
|
|
+
|
|
|
+ createDriver(): Driver {
|
|
|
+ return new D1Driver(this.#config)
|
|
|
+ }
|
|
|
+
|
|
|
+ createQueryCompiler(): QueryCompiler {
|
|
|
+ return new SqliteQueryCompiler()
|
|
|
+ }
|
|
|
+
|
|
|
+ createIntrospector(db: Kysely<any>): DatabaseIntrospector {
|
|
|
+ return new SqliteIntrospector(db)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class D1Driver implements Driver {
|
|
|
+ #config: D1DialectConfig
|
|
|
+
|
|
|
+ constructor(config: D1DialectConfig) {
|
|
|
+ this.#config = config
|
|
|
+ }
|
|
|
+
|
|
|
+ async init(): Promise<void> {}
|
|
|
+
|
|
|
+ async acquireConnection(): Promise<DatabaseConnection> {
|
|
|
+ return new D1Connection(this.#config)
|
|
|
+ }
|
|
|
+
|
|
|
+ async beginTransaction(conn: D1Connection): Promise<void> {
|
|
|
+ return await conn.beginTransaction()
|
|
|
+ }
|
|
|
+
|
|
|
+ async commitTransaction(conn: D1Connection): Promise<void> {
|
|
|
+ return await conn.commitTransaction()
|
|
|
+ }
|
|
|
+
|
|
|
+ async rollbackTransaction(conn: D1Connection): Promise<void> {
|
|
|
+ return await conn.rollbackTransaction()
|
|
|
+ }
|
|
|
+
|
|
|
+ async releaseConnection(_conn: D1Connection): Promise<void> {}
|
|
|
+
|
|
|
+ async destroy(): Promise<void> {}
|
|
|
+}
|
|
|
+
|
|
|
+class D1Connection implements DatabaseConnection {
|
|
|
+ #config: D1DialectConfig
|
|
|
+ // #transactionClient?: D1Connection
|
|
|
+
|
|
|
+ constructor(config: D1DialectConfig) {
|
|
|
+ this.#config = config
|
|
|
+ }
|
|
|
+
|
|
|
+ async executeQuery<O>(compiledQuery: CompiledQuery): Promise<QueryResult<O>> {
|
|
|
+ console.log('compiledQuery: ', compiledQuery)
|
|
|
+ // Transactions are not supported yet.
|
|
|
+ // if (this.#transactionClient) return this.#transactionClient.executeQuery(compiledQuery)
|
|
|
+
|
|
|
+ if (compiledQuery.sql.startsWith('select')) {
|
|
|
+ const results = await this.#config.database.select<O[]>(compiledQuery.sql, [
|
|
|
+ ...compiledQuery.parameters,
|
|
|
+ ])
|
|
|
+ return {
|
|
|
+ rows: results,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const results = await this.#config.database.execute(compiledQuery.sql, [
|
|
|
+ ...compiledQuery.parameters,
|
|
|
+ ])
|
|
|
+
|
|
|
+ const numAffectedRows = results.rowsAffected > 0 ? BigInt(results.rowsAffected) : undefined
|
|
|
+
|
|
|
+ return {
|
|
|
+ insertId:
|
|
|
+ results.lastInsertId === undefined || results.lastInsertId === null
|
|
|
+ ? undefined
|
|
|
+ : BigInt(results.lastInsertId),
|
|
|
+ rows: [],
|
|
|
+ numAffectedRows,
|
|
|
+ // @ts-ignore deprecated in kysely >= 0.23, keep for backward compatibility.
|
|
|
+ numUpdatedOrDeletedRows: numAffectedRows,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async beginTransaction() {
|
|
|
+ // this.#transactionClient = this.#transactionClient ?? new PlanetScaleConnection(this.#config)
|
|
|
+ // this.#transactionClient.#conn.execute('BEGIN')
|
|
|
+ throw new Error('Transactions are not supported yet.')
|
|
|
+ }
|
|
|
+
|
|
|
+ async commitTransaction() {
|
|
|
+ // if (!this.#transactionClient) throw new Error('No transaction to commit')
|
|
|
+ // this.#transactionClient.#conn.execute('COMMIT')
|
|
|
+ // this.#transactionClient = undefined
|
|
|
+ throw new Error('Transactions are not supported yet.')
|
|
|
+ }
|
|
|
+
|
|
|
+ async rollbackTransaction() {
|
|
|
+ // if (!this.#transactionClient) throw new Error('No transaction to rollback')
|
|
|
+ // this.#transactionClient.#conn.execute('ROLLBACK')
|
|
|
+ // this.#transactionClient = undefined
|
|
|
+ throw new Error('Transactions are not supported yet.')
|
|
|
+ }
|
|
|
+
|
|
|
+ async *streamQuery<O>(
|
|
|
+ _compiledQuery: CompiledQuery,
|
|
|
+ _chunkSize: number,
|
|
|
+ ): AsyncIterableIterator<QueryResult<O>> {
|
|
|
+ throw new Error('D1 Driver does not support streaming')
|
|
|
+ }
|
|
|
+}
|