kysely-planetscale
Version:
Kysely dialect for PlanetScale Serverless
124 lines (123 loc) • 4 kB
JavaScript
// src/index.ts
import { Client, cast } from "@planetscale/database";
import { parseJSON } from "date-fns";
import {
MysqlAdapter,
MysqlIntrospector,
MysqlQueryCompiler
} from "kysely";
var PlanetScaleDialect = class {
#config;
constructor(config) {
this.#config = config;
}
createAdapter() {
return new MysqlAdapter();
}
createDriver() {
return new PlanetScaleDriver(this.#config);
}
createQueryCompiler() {
return new MysqlQueryCompiler();
}
createIntrospector(db) {
return new MysqlIntrospector(db);
}
};
var PlanetScaleDriver = class {
#client;
constructor(config) {
this.#client = new Client({ cast: inflateDates, ...config });
}
async init() {
}
async acquireConnection() {
return new PlanetScaleConnection(this.#client);
}
async beginTransaction(conn, settings) {
return await conn.beginTransaction(settings);
}
async commitTransaction(conn) {
return await conn.commitTransaction();
}
async rollbackTransaction(conn) {
return await conn.rollbackTransaction();
}
async releaseConnection(_conn) {
}
async destroy() {
}
};
var sharedConnections = /* @__PURE__ */ new WeakMap();
var PlanetScaleConnection = class {
#client;
#transactionConn;
#useSharedConnection;
get #config() {
return this.#client.config;
}
constructor(client, useSharedConnection = false, isForTransaction = false) {
this.#client = client;
this.#useSharedConnection = useSharedConnection && !isForTransaction;
if (this.#useSharedConnection) {
sharedConnections.set(this.#config, sharedConnections.get(this.#config) ?? this.#client.connection());
}
}
async executeQuery(compiledQuery) {
if (this.#transactionConn) return this.execute(compiledQuery, this.#transactionConn);
return this.#useSharedConnection ? this.execute(compiledQuery, sharedConnections.get(this.#config) || this.#client) : this.execute(compiledQuery, this.#client);
}
async execute(compiledQuery, conn) {
const parameters = this.#config.format ? compiledQuery.parameters : compiledQuery.parameters.map((param) => param instanceof Date ? formatDate(param) : param);
const results = await conn.execute(compiledQuery.sql, parameters);
if (results.error) {
throw results.error;
}
const numAffectedRows = results.rowsAffected == null ? void 0 : BigInt(results.rowsAffected);
return {
insertId: results.insertId !== null && results.insertId.toString() !== "0" ? BigInt(results.insertId) : void 0,
rows: results.rows,
// @ts-ignore replaces `QueryResult.numUpdatedOrDeletedRows` in kysely > 0.22
// following https://github.com/koskimas/kysely/pull/188
numAffectedRows
};
}
async beginTransaction(settings) {
this.#transactionConn = this.#transactionConn ?? this.#client.connection();
if (settings.isolationLevel) {
await this.#transactionConn.execute(`SET TRANSACTION ISOLATION LEVEL ${settings.isolationLevel}`);
}
await this.#transactionConn.execute("BEGIN");
}
async commitTransaction() {
if (!this.#transactionConn) throw new Error("No transaction to commit");
try {
await this.#transactionConn.execute("COMMIT");
} finally {
this.#transactionConn = void 0;
}
}
async rollbackTransaction() {
if (!this.#transactionConn) throw new Error("No transaction to rollback");
try {
await this.#transactionConn.execute("ROLLBACK");
} finally {
this.#transactionConn = void 0;
}
}
async *streamQuery(_compiledQuery, _chunkSize) {
throw new Error("PlanetScale Serverless Driver does not support streaming");
}
};
function inflateDates(field, value) {
if (field.type === "DATETIME" && value) return parseJSON(value);
if (field.type === "TIMESTAMP" && value) return parseJSON(value);
return cast(field, value);
}
function formatDate(date) {
return date.toISOString().replace(/[TZ]/g, " ").trim();
}
export {
PlanetScaleDialect,
inflateDates
};