shelving
Version:
Toolkit for using data in JavaScript.
57 lines (56 loc) • 1.98 kB
JavaScript
import { SQLiteProvider } from "../db/provider/SQLiteProvider.js";
import { ValueError } from "../error/ValueError.js";
import { isArray } from "../util/array.js";
import { isPlainObject } from "../util/object.js";
/**
* Cloudflare D1 database provider.
*
* Uses the D1 Worker API for execution and standard SQL from `SQLProvider`.
*/
export class CloudflareD1Provider extends SQLiteProvider {
_db;
constructor(db) {
super();
this._db = db;
}
async exec(strings, ...values) {
const { query, values: bindings } = _getD1Query(strings, values, this.exec);
const result = await this._db
.prepare(query)
.bind(...bindings)
.run();
return result.results ?? [];
}
}
function _getD1Query(strings, values, caller) {
let query = strings[0] ?? "";
const bindings = [];
for (const [index, value] of values.entries()) {
const part = _getD1Part(value, caller);
query += part.query;
bindings.push(...part.values);
query += strings[index + 1] ?? "";
}
return { query, values: bindings };
}
function _getD1Part(value, caller) {
if (_isSQLQuery(value))
return _getD1Query(value.strings, value.values, caller);
return { query: "?", values: [_getD1Value(value, caller)] };
}
function _getD1Value(value, caller) {
if (value === null || typeof value === "boolean" || typeof value === "string" || typeof value === "number")
return value;
if (isArray(value) || isPlainObject(value)) {
try {
return JSON.stringify(value);
}
catch (cause) {
throw new ValueError("Cannot convert value to D1 JSON value", { cause, received: value, caller });
}
}
throw new ValueError("Cannot convert value to D1 binding", { received: value, caller });
}
function _isSQLQuery(value) {
return typeof value === "object" && !!value && "strings" in value && "values" in value;
}