flint-orm
Version:
Type-safe SQLite ORM for JavaScript
1,690 lines (1,669 loc) • 119 kB
JavaScript
// @bun
var __create = Object.create;
var __getProtoOf = Object.getPrototypeOf;
var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
function __accessProp(key) {
return this[key];
}
var __toESMCache_node;
var __toESMCache_esm;
var __toESM = (mod, isNodeMode, target) => {
var canCache = mod != null && typeof mod === "object";
if (canCache) {
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
var cached = cache.get(mod);
if (cached)
return cached;
}
target = mod != null ? __create(__getProtoOf(mod)) : {};
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
for (let key of __getOwnPropNames(mod))
if (!__hasOwnProp.call(to, key))
__defProp(to, key, {
get: __accessProp.bind(mod, key),
enumerable: true
});
if (canCache)
cache.set(mod, to);
return to;
};
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
var __returnValue = (v) => v;
function __exportSetter(name, newValue) {
this[name] = __returnValue.bind(null, newValue);
}
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, {
get: all[name],
enumerable: true,
configurable: true,
set: __exportSetter.bind(all, name)
});
};
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
var __require = import.meta.require;
// node_modules/@tursodatabase/database-common/dist/bind.js
function bindParams(stmt, params) {
const len = params?.length;
if (len === 0) {
return;
}
if (len === 1) {
const param = params[0];
if (isPlainObject(param)) {
bindNamedParams(stmt, param);
return;
}
if (Array.isArray(param)) {
bindPositionalParams(stmt, [param]);
return;
}
bindValue(stmt, 1, param);
return;
}
bindPositionalParams(stmt, params);
}
function isPlainObject(obj) {
if (!obj || typeof obj !== "object")
return false;
const proto = Object.getPrototypeOf(obj);
return proto === Object.prototype || proto === null;
}
function bindNamedParams(stmt, paramObj) {
const paramCount = stmt.parameterCount();
for (let i = 1;i <= paramCount; i++) {
const paramName = stmt.parameterName(i);
if (paramName) {
const key = paramName.substring(1);
const value = paramObj[key];
if (value !== undefined) {
bindValue(stmt, i, value);
}
}
}
}
function bindPositionalParams(stmt, params) {
let bindIndex = 1;
for (let i = 0;i < params.length; i++) {
const param = params[i];
if (Array.isArray(param)) {
for (let j = 0;j < param.length; j++) {
bindValue(stmt, bindIndex++, param[j]);
}
} else {
bindValue(stmt, bindIndex++, param);
}
}
}
function bindValue(stmt, index, value) {
stmt.bindAt(index, value);
}
// node_modules/@tursodatabase/database-common/dist/sqlite-error.js
var SqliteError;
var init_sqlite_error = __esm(() => {
SqliteError = class SqliteError extends Error {
name;
code;
rawCode;
constructor(message, code, rawCode) {
super(message);
this.name = "SqliteError";
this.code = code;
this.rawCode = rawCode;
Error.captureStackTrace(this, SqliteError);
}
};
});
// node_modules/@tursodatabase/database-common/dist/types.js
var STEP_ROW = 1, STEP_DONE = 2, STEP_IO = 3;
// node_modules/@tursodatabase/database-common/dist/compat.js
var init_compat = __esm(() => {
init_sqlite_error();
});
// node_modules/@tursodatabase/database-common/dist/async-lock.js
class AsyncLock {
locked;
queue;
constructor() {
this.locked = false;
this.queue = [];
}
async acquire() {
if (!this.locked) {
this.locked = true;
return Promise.resolve();
} else {
const block = new Promise((resolve) => {
this.queue.push(resolve);
});
return block;
}
}
release() {
if (this.locked == false) {
throw new Error("invalid state: lock was already unlocked");
}
const item = this.queue.shift();
if (item != null) {
this.locked = true;
item();
} else {
this.locked = false;
}
}
}
// node_modules/@tursodatabase/database-common/dist/promise.js
function convertError(err) {
if ((err.code ?? "").startsWith(CONVERTIBLE_ERROR_PREFIX)) {
return createErrorByName(err.code.substring(CONVERTIBLE_ERROR_PREFIX.length), err.message);
}
return new SqliteError(err.message, err.code, err.rawCode);
}
function createErrorByName(name, message) {
const ErrorConstructor = convertibleErrorTypes[name];
if (!ErrorConstructor) {
throw new Error(`unknown error type ${name} from Turso`);
}
return new ErrorConstructor(message);
}
function isQueryOptions(value) {
return value != null && typeof value === "object" && !Array.isArray(value) && Object.prototype.hasOwnProperty.call(value, "queryTimeout");
}
function splitBindParameters(bindParameters) {
if (bindParameters.length === 0) {
return { params: undefined, queryOptions: undefined };
}
if (bindParameters.length > 1 && isQueryOptions(bindParameters[bindParameters.length - 1])) {
return {
params: bindParameters.length === 2 ? bindParameters[0] : bindParameters.slice(0, -1),
queryOptions: bindParameters[bindParameters.length - 1]
};
}
return { params: bindParameters.length === 1 ? bindParameters[0] : bindParameters, queryOptions: undefined };
}
function toBindArgs(params) {
if (params === undefined) {
return [];
}
return [params];
}
class Database {
name;
readonly;
open;
memory;
inTransaction;
db;
ioStep;
execLock;
_inTransaction = false;
connected = false;
constructor(db, ioStep) {
this.db = db;
this.execLock = new AsyncLock;
this.ioStep = ioStep ?? (async () => {});
Object.defineProperties(this, {
name: { get: () => this.db.path },
readonly: { get: () => this.db.readonly },
open: { get: () => this.db.open },
memory: { get: () => this.db.memory },
inTransaction: { get: () => this._inTransaction }
});
}
async connect() {
if (this.connected) {
return;
}
await this.db.connectAsync();
this.connected = true;
}
prepare(sql) {
if (this.connected && !this.open) {
throw new TypeError("The database connection is not open");
}
if (!sql) {
throw new RangeError("The supplied SQL string contains no statements");
}
try {
if (this.connected) {
return new Statement(maybeValue(this.db.prepare(sql)), this.db, this.execLock, this.ioStep);
} else {
return new Statement(maybePromise(() => this.connect().then(() => this.db.prepare(sql))), this.db, this.execLock, this.ioStep);
}
} catch (err) {
throw convertError(err);
}
}
transaction(fn) {
if (typeof fn !== "function")
throw new TypeError("Expected first argument to be a function");
const db = this;
const wrapTxn = (mode) => {
return async (...bindParameters) => {
await db.exec("BEGIN " + mode);
db._inTransaction = true;
try {
const result = await fn(...bindParameters);
await db.exec("COMMIT");
db._inTransaction = false;
return result;
} catch (err) {
await db.exec("ROLLBACK");
db._inTransaction = false;
throw err;
}
};
};
const properties = {
default: { value: wrapTxn("") },
deferred: { value: wrapTxn("DEFERRED") },
immediate: { value: wrapTxn("IMMEDIATE") },
exclusive: { value: wrapTxn("EXCLUSIVE") },
database: { value: this, enumerable: true }
};
Object.defineProperties(properties.default.value, properties);
Object.defineProperties(properties.deferred.value, properties);
Object.defineProperties(properties.immediate.value, properties);
Object.defineProperties(properties.exclusive.value, properties);
return properties.default.value;
}
async run(sql, ...bindParameters) {
const stmt = await this.prepare(sql);
try {
return await stmt.run(...bindParameters);
} finally {
await stmt.close();
}
}
async get(sql, ...bindParameters) {
const stmt = await this.prepare(sql);
try {
return await stmt.get(...bindParameters);
} finally {
await stmt.close();
}
}
async all(sql, ...bindParameters) {
const stmt = await this.prepare(sql);
try {
return await stmt.all(...bindParameters);
} finally {
await stmt.close();
}
}
async* iterate(sql, ...bindParameters) {
const stmt = await this.prepare(sql);
try {
yield* stmt.iterate(...bindParameters);
} finally {
await stmt.close();
}
}
async pragma(source, options) {
if (options == null)
options = {};
if (typeof source !== "string")
throw new TypeError("Expected first argument to be a string");
if (typeof options !== "object")
throw new TypeError("Expected second argument to be an options object");
const pragma = `PRAGMA ${source}`;
const stmt = await this.prepare(pragma);
try {
const results = await stmt.all();
return results;
} finally {
await stmt.close();
}
}
backup(filename, options) {
throw new Error("not implemented");
}
serialize(options) {
throw new Error("not implemented");
}
function(name, options, fn) {
throw new Error("not implemented");
}
aggregate(name, options) {
throw new Error("not implemented");
}
table(name, factory) {
throw new Error("not implemented");
}
loadExtension(path) {
throw new Error("not implemented");
}
maxWriteReplicationIndex() {
throw new Error("not implemented");
}
async exec(sql, queryOptions) {
if (!this.open) {
throw new TypeError("The database connection is not open");
}
await this.execLock.acquire();
const exec = this.db.executor(sql, queryOptions);
try {
while (true) {
const stepResult = exec.stepSync();
if (stepResult === STEP_IO) {
await this.io();
continue;
}
if (stepResult === STEP_DONE) {
break;
}
if (stepResult === STEP_ROW) {
continue;
}
}
} finally {
exec.reset();
this.execLock.release();
}
}
interrupt() {
throw new Error("not implemented");
}
defaultSafeIntegers(toggle) {
this.db.defaultSafeIntegers(toggle);
}
async close() {
this.db.close();
}
async io() {
await this.ioStep();
}
}
function maybePromise(arg) {
let lazy = arg;
let promise = null;
let value = null;
return {
apply(fn) {
let previous = lazy;
lazy = async () => {
const result = await previous();
fn(result);
return result;
};
},
async resolve() {
if (promise != null) {
return await promise;
}
let valueResolve, valueReject;
promise = new Promise((resolve, reject) => {
valueResolve = (x) => {
resolve(x);
value = x;
};
valueReject = reject;
});
await lazy().then(valueResolve, valueReject);
return await promise;
},
must() {
if (value == null) {
throw new Error(`database must be connected before execution the function`);
}
return value;
}
};
}
function maybeValue(value) {
return {
apply(fn) {
fn(value);
},
resolve() {
return Promise.resolve(value);
},
must() {
return value;
}
};
}
class Statement {
stmt;
db;
execLock;
ioStep;
constructor(stmt, db, execLock, ioStep) {
this.stmt = stmt;
this.db = db;
this.execLock = execLock;
this.ioStep = ioStep;
}
raw(raw) {
this.stmt.apply((s) => s.raw(raw));
return this;
}
pluck(pluckMode) {
this.stmt.apply((s) => s.pluck(pluckMode));
return this;
}
safeIntegers(toggle) {
this.stmt.apply((s) => s.safeIntegers(toggle));
return this;
}
columns() {
return this.stmt.must().columns();
}
get source() {
throw new Error("not implemented");
}
get reader() {
return this.stmt.must().columns().length > 0;
}
get database() {
return this.db;
}
async run(...bindParameters) {
let stmt = await this.stmt.resolve();
const { params, queryOptions } = splitBindParameters(bindParameters);
stmt.setQueryTimeout(queryOptions);
bindParams(stmt, toBindArgs(params));
const totalChangesBefore = this.db.totalChanges();
await this.execLock.acquire();
try {
while (true) {
const stepResult = await stmt.stepSync();
if (stepResult === STEP_IO) {
await this.io();
continue;
}
if (stepResult === STEP_DONE) {
break;
}
if (stepResult === STEP_ROW) {
continue;
}
}
const lastInsertRowid = this.db.lastInsertRowid();
const changes = this.db.totalChanges() === totalChangesBefore ? 0 : this.db.changes();
return { changes, lastInsertRowid };
} finally {
stmt.reset();
this.execLock.release();
}
}
async get(...bindParameters) {
let stmt = await this.stmt.resolve();
const { params, queryOptions } = splitBindParameters(bindParameters);
stmt.setQueryTimeout(queryOptions);
bindParams(stmt, toBindArgs(params));
await this.execLock.acquire();
let row = undefined;
try {
while (true) {
const stepResult = await stmt.stepSync();
if (stepResult === STEP_IO) {
await this.io();
continue;
}
if (stepResult === STEP_DONE) {
break;
}
if (stepResult === STEP_ROW && row === undefined) {
row = stmt.row();
continue;
}
}
return row;
} finally {
stmt.reset();
this.execLock.release();
}
}
async* iterate(...bindParameters) {
let stmt = await this.stmt.resolve();
const { params, queryOptions } = splitBindParameters(bindParameters);
stmt.setQueryTimeout(queryOptions);
bindParams(stmt, toBindArgs(params));
await this.execLock.acquire();
try {
while (true) {
const stepResult = await stmt.stepSync();
if (stepResult === STEP_IO) {
await this.io();
continue;
}
if (stepResult === STEP_DONE) {
break;
}
if (stepResult === STEP_ROW) {
yield stmt.row();
}
}
} finally {
stmt.reset();
this.execLock.release();
}
}
async all(...bindParameters) {
let stmt = await this.stmt.resolve();
const { params, queryOptions } = splitBindParameters(bindParameters);
stmt.setQueryTimeout(queryOptions);
bindParams(stmt, toBindArgs(params));
const rows = [];
await this.execLock.acquire();
try {
while (true) {
const stepResult = await stmt.stepSync();
if (stepResult === STEP_IO) {
await this.io();
continue;
}
if (stepResult === STEP_DONE) {
break;
}
if (stepResult === STEP_ROW) {
rows.push(stmt.row());
}
}
return rows;
} finally {
stmt.reset();
this.execLock.release();
}
}
async io() {
await this.ioStep();
}
interrupt() {
throw new Error("not implemented");
}
bind(...bindParameters) {
try {
bindParams(this.stmt, bindParameters);
return this;
} catch (err) {
throw convertError(err);
}
}
close() {
let stmt;
try {
stmt = this.stmt.must();
} catch (e) {
return;
}
stmt.finalize();
}
}
var convertibleErrorTypes, CONVERTIBLE_ERROR_PREFIX = "[TURSO_CONVERT_TYPE]";
var init_promise = __esm(() => {
init_sqlite_error();
convertibleErrorTypes = { TypeError };
});
// node_modules/@tursodatabase/database-common/dist/index.js
var init_dist = __esm(() => {
init_compat();
init_promise();
init_sqlite_error();
});
// node_modules/@tursodatabase/sync-common/dist/run.js
function trackPromise(p) {
let status = { promise: null, finished: false };
status.promise = p.finally(() => status.finished = true);
return status;
}
function timeoutMs(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function normalizeUrl(url) {
return url.replace(/^libsql:\/\//, "https://");
}
async function process2(opts, io, request) {
const requestType = request.request();
const completion = request.completion();
if (requestType.type == "Http") {
let url = requestType.url;
if (typeof opts.url == "function") {
url = opts.url();
} else {
url = opts.url;
}
if (url == null) {
completion.poison(`url is empty - sync is paused`);
return;
}
url = normalizeUrl(url);
try {
let headers = typeof opts.headers === "function" ? await opts.headers() : opts.headers;
if (requestType.headers != null && requestType.headers.length > 0) {
headers = { ...headers };
for (let header of requestType.headers) {
headers[header[0]] = header[1];
}
}
const fetchImpl = opts.fetch ?? fetch;
const response = await fetchImpl(`${url}${requestType.path}`, {
method: requestType.method,
headers,
body: requestType.body != null ? new Uint8Array(requestType.body) : null
});
completion.status(response.status);
const reader = response.body?.getReader();
if (reader == null) {
throw new Error("reader is null");
}
while (true) {
const { done, value } = await reader.read();
if (done) {
completion.done();
break;
}
completion.pushBuffer(value);
}
} catch (error) {
completion.poison(`fetch error: ${error}`);
}
} else if (requestType.type == "FullRead") {
try {
const metadata = await io.read(requestType.path);
if (metadata != null) {
completion.pushBuffer(metadata);
}
completion.done();
} catch (error) {
completion.poison(`metadata read error: ${error}`);
}
} else if (requestType.type == "FullWrite") {
try {
await io.write(requestType.path, requestType.content);
completion.done();
} catch (error) {
completion.poison(`metadata write error: ${error}`);
}
} else if (requestType.type == "Transform") {
if (opts.transform == null) {
completion.poison("transform is not set");
return;
}
const results = [];
for (const mutation of requestType.mutations) {
const result = opts.transform(mutation);
if (result == null) {
results.push({ type: "Keep" });
} else if (result.operation == "skip") {
results.push({ type: "Skip" });
} else if (result.operation == "rewrite") {
results.push({ type: "Rewrite", stmt: result.stmt });
} else {
completion.poison("unexpected transform operation");
return;
}
}
completion.pushTransform(results);
completion.done();
}
}
function retryFetch(opts = {}) {
const attempts = opts.attempts ?? 3;
const baseDelay = opts.delayMs ?? 500;
const backoff = opts.backoff ?? 2;
const underlying = opts.fetch ?? ((input, init) => fetch(input, init));
if (!Number.isFinite(attempts) || attempts < 1) {
throw new Error(`retryFetch: attempts must be a finite integer >= 1, got ${attempts}`);
}
return async (input, init) => {
let lastError = null;
let lastResponse = null;
let delay = baseDelay;
for (let i = 0;i < attempts; i++) {
try {
const response = await underlying(input, init);
if (response.status < 500 && response.status !== 429) {
return response;
}
lastResponse = response;
lastError = null;
} catch (error) {
lastError = error;
lastResponse = null;
}
if (i + 1 < attempts) {
await timeoutMs(delay);
delay *= backoff;
}
}
if (lastResponse != null) {
return lastResponse;
}
throw lastError ?? new Error("retryFetch: exhausted with no response");
};
}
function runner(opts, io, engine) {
let tasks = [];
return {
async wait() {
for (let request = engine.protocolIo();request != null; request = engine.protocolIo()) {
tasks.push(trackPromise(process2(opts, io, request)));
}
const tasksRace = tasks.length == 0 ? Promise.resolve() : Promise.race([timeoutMs(opts.preemptionMs), ...tasks.map((t) => t.promise)]);
await Promise.all([engine.ioLoopAsync(), tasksRace]);
tasks = tasks.filter((t) => !t.finished);
engine.protocolIoStep();
}
};
}
async function run(runner2, generator) {
while (true) {
const { type, ...rest } = await generator.resumeAsync(null);
if (type == "Done") {
return null;
}
if (type == "SyncEngineStats") {
return rest;
}
if (type == "SyncEngineChanges") {
return rest.changes;
}
await runner2.wait();
}
}
class SyncEngineGuards {
waitLock;
pushLock;
pullLock;
checkpointLock;
constructor() {
this.waitLock = new AsyncLock;
this.pushLock = new AsyncLock;
this.pullLock = new AsyncLock;
this.checkpointLock = new AsyncLock;
}
async wait(f) {
try {
await this.waitLock.acquire();
return await f();
} finally {
this.waitLock.release();
}
}
async push(f) {
try {
await this.pushLock.acquire();
await this.pullLock.acquire();
await this.checkpointLock.acquire();
return await f();
} finally {
this.pushLock.release();
this.pullLock.release();
this.checkpointLock.release();
}
}
async apply(f) {
try {
await this.waitLock.acquire();
await this.pushLock.acquire();
await this.pullLock.acquire();
await this.checkpointLock.acquire();
return await f();
} finally {
this.waitLock.release();
this.pushLock.release();
this.pullLock.release();
this.checkpointLock.release();
}
}
async checkpoint(f) {
try {
await this.waitLock.acquire();
await this.pushLock.acquire();
await this.pullLock.acquire();
await this.checkpointLock.acquire();
return await f();
} finally {
this.waitLock.release();
this.pushLock.release();
this.pullLock.release();
this.checkpointLock.release();
}
}
}
var init_run = __esm(() => {
init_dist();
});
// node_modules/@tursodatabase/serverless/dist/error.js
var DatabaseError;
var init_error = __esm(() => {
DatabaseError = class DatabaseError extends Error {
constructor(message, code, rawCode, cause) {
super(message);
this.name = "DatabaseError";
this.code = code;
this.rawCode = rawCode;
this.cause = cause;
Object.setPrototypeOf(this, DatabaseError.prototype);
}
};
});
// node_modules/@tursodatabase/serverless/dist/protocol.js
function encodeValue(value) {
if (value === null || value === undefined) {
return { type: "null" };
}
if (typeof value === "number") {
if (!Number.isFinite(value)) {
throw new Error("Only finite numbers (not Infinity or NaN) can be passed as arguments");
}
return { type: "float", value };
}
if (typeof value === "bigint") {
return { type: "integer", value: value.toString() };
}
if (typeof value === "boolean") {
return { type: "integer", value: value ? "1" : "0" };
}
if (typeof value === "string") {
return { type: "text", value };
}
if (value instanceof ArrayBuffer || value instanceof Uint8Array) {
const base64 = btoa(String.fromCharCode(...new Uint8Array(value)));
return { type: "blob", base64 };
}
return { type: "text", value: String(value) };
}
function decodeValue(value, safeIntegers = false) {
switch (value.type) {
case "null":
return null;
case "integer":
if (safeIntegers) {
return BigInt(value.value);
}
return parseInt(value.value, 10);
case "float":
return value.value;
case "text":
return value.value;
case "blob":
if (value.base64) {
const binaryString = atob(value.base64);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0;i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return Buffer.from(bytes);
}
return null;
default:
return null;
}
}
async function executeCursor(url, authToken, request, remoteEncryptionKey) {
const headers = {
"Content-Type": "application/json"
};
if (authToken) {
headers["Authorization"] = `Bearer ${authToken}`;
}
if (remoteEncryptionKey) {
headers[ENCRYPTION_KEY_HEADER] = remoteEncryptionKey;
}
const response = await fetch(`${url}/v3/cursor`, {
method: "POST",
headers,
body: JSON.stringify(request)
});
if (!response.ok) {
let errorMessage = `HTTP error! status: ${response.status}`;
try {
const errorBody = await response.text();
const errorData = JSON.parse(errorBody);
if (errorData.message) {
errorMessage = errorData.message;
}
} catch {}
throw new DatabaseError(errorMessage);
}
const reader = response.body?.getReader();
if (!reader) {
throw new DatabaseError("No response body");
}
const decoder = new TextDecoder;
let buffer = "";
let cursorResponse;
while (!cursorResponse) {
const { done, value } = await reader.read();
if (done)
break;
buffer += decoder.decode(value, { stream: true });
const newlineIndex = buffer.indexOf(`
`);
if (newlineIndex !== -1) {
const line = buffer.slice(0, newlineIndex).trim();
buffer = buffer.slice(newlineIndex + 1);
if (line) {
cursorResponse = JSON.parse(line);
break;
}
}
}
if (!cursorResponse) {
throw new DatabaseError("No cursor response received");
}
async function* parseEntries() {
try {
let newlineIndex;
while ((newlineIndex = buffer.indexOf(`
`)) !== -1) {
const line = buffer.slice(0, newlineIndex).trim();
buffer = buffer.slice(newlineIndex + 1);
if (line) {
yield JSON.parse(line);
}
}
while (true) {
const { done, value } = await reader.read();
if (done)
break;
buffer += decoder.decode(value, { stream: true });
while ((newlineIndex = buffer.indexOf(`
`)) !== -1) {
const line = buffer.slice(0, newlineIndex).trim();
buffer = buffer.slice(newlineIndex + 1);
if (line) {
yield JSON.parse(line);
}
}
}
if (buffer.trim()) {
yield JSON.parse(buffer.trim());
}
} finally {
reader.releaseLock();
}
}
return { response: cursorResponse, entries: parseEntries() };
}
async function executePipeline(url, authToken, request, remoteEncryptionKey) {
const headers = {
"Content-Type": "application/json"
};
if (authToken) {
headers["Authorization"] = `Bearer ${authToken}`;
}
if (remoteEncryptionKey) {
headers[ENCRYPTION_KEY_HEADER] = remoteEncryptionKey;
}
const response = await fetch(`${url}/v3/pipeline`, {
method: "POST",
headers,
body: JSON.stringify(request)
});
if (!response.ok) {
throw new DatabaseError(`HTTP error! status: ${response.status}`);
}
return response.json();
}
var ENCRYPTION_KEY_HEADER = "x-turso-encryption-key";
var init_protocol = __esm(() => {
init_error();
});
// node_modules/@tursodatabase/serverless/dist/session.js
function normalizeUrl2(url) {
return url.replace(/^libsql:\/\//, "https://");
}
function isValidIdentifier(str) {
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(str);
}
class Session {
constructor(config) {
this.baton = null;
this.config = config;
this.baseUrl = normalizeUrl2(config.url);
}
async describe(sql) {
const request = {
baton: this.baton,
requests: [{
type: "describe",
sql
}]
};
const response = await executePipeline(this.baseUrl, this.config.authToken, request, this.config.remoteEncryptionKey);
this.baton = response.baton;
if (response.base_url) {
this.baseUrl = response.base_url;
}
if (response.results && response.results[0]) {
const result = response.results[0];
if (result.type === "error") {
throw new DatabaseError(result.error?.message || "Describe execution failed", result.error?.code);
}
if (result.response?.type === "describe" && result.response.result) {
return result.response.result;
}
}
throw new DatabaseError("Unexpected describe response");
}
async execute(sql, args = [], safeIntegers = false) {
const { response, entries } = await this.executeRaw(sql, args);
const result = await this.processCursorEntries(entries, safeIntegers);
return result;
}
async executeRaw(sql, args = []) {
let positionalArgs = [];
let namedArgs = [];
if (Array.isArray(args)) {
positionalArgs = args.map(encodeValue);
} else {
const keys = Object.keys(args);
const isNumericKeys = keys.length > 0 && keys.every((key) => /^\d+$/.test(key));
if (isNumericKeys) {
const sortedKeys = keys.sort((a, b) => parseInt(a) - parseInt(b));
const maxIndex = parseInt(sortedKeys[sortedKeys.length - 1]);
positionalArgs = new Array(maxIndex);
for (const key of sortedKeys) {
const index = parseInt(key) - 1;
positionalArgs[index] = encodeValue(args[key]);
}
for (let i = 0;i < positionalArgs.length; i++) {
if (positionalArgs[i] === undefined) {
positionalArgs[i] = { type: "null" };
}
}
} else {
namedArgs = Object.entries(args).map(([name, value]) => ({
name,
value: encodeValue(value)
}));
}
}
const request = {
baton: this.baton,
batch: {
steps: [{
stmt: {
sql,
args: positionalArgs,
named_args: namedArgs,
want_rows: true
}
}]
}
};
const { response, entries } = await executeCursor(this.baseUrl, this.config.authToken, request, this.config.remoteEncryptionKey);
this.baton = response.baton;
if (response.base_url) {
this.baseUrl = response.base_url;
}
return { response, entries };
}
async processCursorEntries(entries, safeIntegers = false) {
let columns = [];
let columnTypes = [];
let rows = [];
let rowsAffected = 0;
let lastInsertRowid;
for await (const entry of entries) {
switch (entry.type) {
case "step_begin":
if (entry.cols) {
columns = entry.cols.map((col) => col.name);
columnTypes = entry.cols.map((col) => col.decltype || "");
}
break;
case "row":
if (entry.row) {
const decodedRow = entry.row.map((value) => decodeValue(value, safeIntegers));
const rowObject = this.createRowObject(decodedRow, columns);
rows.push(rowObject);
}
break;
case "step_end":
if (entry.affected_row_count !== undefined) {
rowsAffected = entry.affected_row_count;
}
if (entry.last_insert_rowid) {
lastInsertRowid = parseInt(entry.last_insert_rowid, 10);
}
break;
case "step_error":
case "error":
throw new DatabaseError(entry.error?.message || "SQL execution failed", entry.error?.code);
}
}
return {
columns,
columnTypes,
rows,
rowsAffected,
lastInsertRowid
};
}
createRowObject(values, columns) {
const row = [...values];
columns.forEach((column, index) => {
if (column && isValidIdentifier(column)) {
Object.defineProperty(row, column, {
value: values[index],
enumerable: false,
writable: false,
configurable: true
});
}
});
return row;
}
async batch(statements) {
const request = {
baton: this.baton,
batch: {
steps: statements.map((sql) => ({
stmt: {
sql,
args: [],
named_args: [],
want_rows: false
}
}))
}
};
const { response, entries } = await executeCursor(this.baseUrl, this.config.authToken, request, this.config.remoteEncryptionKey);
this.baton = response.baton;
if (response.base_url) {
this.baseUrl = response.base_url;
}
let totalRowsAffected = 0;
let lastInsertRowid;
for await (const entry of entries) {
switch (entry.type) {
case "step_end":
if (entry.affected_row_count !== undefined) {
totalRowsAffected += entry.affected_row_count;
}
if (entry.last_insert_rowid) {
lastInsertRowid = parseInt(entry.last_insert_rowid, 10);
}
break;
case "step_error":
case "error":
throw new DatabaseError(entry.error?.message || "Batch execution failed", entry.error?.code);
}
}
return {
rowsAffected: totalRowsAffected,
lastInsertRowid
};
}
async sequence(sql) {
const request = {
baton: this.baton,
requests: [{
type: "sequence",
sql
}]
};
const response = await executePipeline(this.baseUrl, this.config.authToken, request, this.config.remoteEncryptionKey);
this.baton = response.baton;
if (response.base_url) {
this.baseUrl = response.base_url;
}
if (response.results && response.results[0]) {
const result = response.results[0];
if (result.type === "error") {
throw new DatabaseError(result.error?.message || "Sequence execution failed", result.error?.code);
}
}
}
async close() {
if (this.baton) {
try {
const request = {
baton: this.baton,
requests: [{
type: "close"
}]
};
await executePipeline(this.baseUrl, this.config.authToken, request, this.config.remoteEncryptionKey);
} catch (error) {
console.error("Error closing session:", error);
}
}
this.baton = null;
this.baseUrl = "";
}
}
var init_session = __esm(() => {
init_protocol();
init_error();
});
// node_modules/@tursodatabase/serverless/dist/statement.js
var init_statement = __esm(() => {
init_protocol();
init_session();
init_error();
});
// node_modules/@tursodatabase/serverless/dist/connection.js
var init_connection = __esm(() => {
init_session();
init_statement();
});
// node_modules/@tursodatabase/serverless/dist/index.js
var init_dist2 = __esm(() => {
init_connection();
init_statement();
init_session();
init_error();
init_protocol();
});
// node_modules/@tursodatabase/sync-common/dist/remote-writer.js
class RemoteWriter {
session = null;
_inRemoteTxn = false;
config;
constructor(config) {
this.config = config;
}
async resolveAuthToken() {
if (typeof this.config.authToken === "function") {
return await this.config.authToken();
}
return this.config.authToken;
}
async createSession() {
const authToken = await this.resolveAuthToken();
const sessionConfig = {
url: this.config.url,
authToken,
remoteEncryptionKey: this.config.remoteEncryptionKey
};
return new Session(sessionConfig);
}
async execute(sql, args = []) {
if (this._inRemoteTxn) {
return await this.session.execute(sql, args);
}
const session = await this.createSession();
try {
return await session.execute(sql, args);
} finally {
await session.close();
}
}
async sequence(sql) {
if (this._inRemoteTxn) {
await this.session.sequence(sql);
return;
}
const session = await this.createSession();
try {
await session.sequence(sql);
} finally {
await session.close();
}
}
async beginTransaction(mode) {
this.session = await this.createSession();
await this.session.sequence("BEGIN " + mode);
this._inRemoteTxn = true;
}
async commitTransaction() {
if (!this.session) {
throw new Error("No active remote transaction");
}
try {
await this.session.sequence("COMMIT");
} finally {
this._inRemoteTxn = false;
await this.session.close();
this.session = null;
}
}
async rollbackTransaction() {
if (!this.session) {
throw new Error("No active remote transaction");
}
try {
await this.session.sequence("ROLLBACK");
} finally {
this._inRemoteTxn = false;
await this.session.close();
this.session = null;
}
}
async execRemote(sql, category) {
if (category === "begin") {
this.session = await this.createSession();
await this.session.sequence(sql);
this._inRemoteTxn = true;
return { shouldPull: false };
}
if (category === "commit") {
if (!this.session)
throw new Error("No active remote transaction");
try {
await this.session.sequence(sql);
} finally {
this._inRemoteTxn = false;
await this.session.close();
this.session = null;
}
return { shouldPull: true };
}
if (category === "rollback") {
if (!this.session)
throw new Error("No active remote transaction");
try {
await this.session.sequence(sql);
} finally {
this._inRemoteTxn = false;
await this.session.close();
this.session = null;
}
return { shouldPull: false };
}
await this.sequence(sql);
return { shouldPull: !this._inRemoteTxn };
}
get isInTransaction() {
return this._inRemoteTxn;
}
async close() {
if (this.session) {
try {
if (this._inRemoteTxn) {
await this.session.sequence("ROLLBACK");
}
} catch {}
await this.session.close();
this.session = null;
this._inRemoteTxn = false;
}
}
}
var init_remote_writer = __esm(() => {
init_dist2();
});
// node_modules/@tursodatabase/sync-common/dist/remote-write-statement.js
class RemoteWriteStatement {
localStmt;
sql;
isStmtReadonly;
remoteWriter;
pullFn;
_boundArgs = [];
constructor(localStmt, sql, isStmtReadonly, remoteWriter, pullFn) {
this.localStmt = localStmt;
this.sql = sql;
this.isStmtReadonly = isStmtReadonly;
this.remoteWriter = remoteWriter;
this.pullFn = pullFn;
}
shouldGoRemote() {
return this.remoteWriter.isInTransaction || !this.isStmtReadonly;
}
shouldPullAfter() {
return !this.isStmtReadonly && !this.remoteWriter.isInTransaction;
}
raw(toggle) {
this.localStmt.raw(toggle);
return this;
}
pluck(toggle) {
this.localStmt.pluck(toggle);
return this;
}
safeIntegers(toggle) {
this.localStmt.safeIntegers(toggle);
return this;
}
columns() {
return this.localStmt.columns();
}
get reader() {
return this.localStmt.reader;
}
bind(...bindParameters) {
this._boundArgs = flattenArgs(bindParameters);
this.localStmt.bind(...bindParameters);
return this;
}
async run(...bindParameters) {
if (!this.shouldGoRemote()) {
return await this.localStmt.run(...bindParameters);
}
const args = bindParameters.length > 0 ? flattenArgs(bindParameters) : this._boundArgs;
const result = await this.remoteWriter.execute(this.sql, args);
if (this.shouldPullAfter()) {
await this.pullFn();
}
return {
changes: result.rowsAffected,
lastInsertRowid: result.lastInsertRowid
};
}
async get(...bindParameters) {
if (!this.shouldGoRemote()) {
return await this.localStmt.get(...bindParameters);
}
const args = bindParameters.length > 0 ? flattenArgs(bindParameters) : this._boundArgs;
const result = await this.remoteWriter.execute(this.sql, args);
if (this.shouldPullAfter()) {
await this.pullFn();
}
return result.rows.length > 0 ? result.rows[0] : undefined;
}
async all(...bindParameters) {
if (!this.shouldGoRemote()) {
return await this.localStmt.all(...bindParameters);
}
const args = bindParameters.length > 0 ? flattenArgs(bindParameters) : this._boundArgs;
const result = await this.remoteWriter.execute(this.sql, args);
if (this.shouldPullAfter()) {
await this.pullFn();
}
return result.rows;
}
async* iterate(...bindParameters) {
if (!this.shouldGoRemote()) {
yield* this.localStmt.iterate(...bindParameters);
return;
}
const args = bindParameters.length > 0 ? flattenArgs(bindParameters) : this._boundArgs;
const result = await this.remoteWriter.execute(this.sql, args);
if (this.shouldPullAfter()) {
await this.pullFn();
}
for (const row of result.rows) {
yield row;
}
}
close() {
this.localStmt.close();
}
}
function flattenArgs(bindParameters) {
if (bindParameters.length === 1 && Array.isArray(bindParameters[0])) {
return bindParameters[0];
}
return bindParameters;
}
// node_modules/@tursodatabase/sync-common/dist/index.js
var init_dist3 = __esm(() => {
init_run();
init_remote_writer();
});
// node_modules/@tursodatabase/sync/index.js
import { createRequire } from "module";
function requireNative() {
if (process.env.NAPI_RS_NATIVE_LIBRARY_PATH) {
try {
nativeBinding = require2(process.env.NAPI_RS_NATIVE_LIBRARY_PATH);
} catch (err) {
loadErrors.push(err);
}
} else if (process.platform === "android") {
if (process.arch === "arm64") {
try {
return require2("./sync.android-arm64.node");
} catch (e) {
loadErrors.push(e);
}
try {
const binding = require2("@tursodatabase/sync-android-arm64");
const bindingPackageVersion = require2("@tursodatabase/sync-android-arm64/package.json").version;
if (bindingPackageVersion !== "0.6.0-pre.22" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") {
throw new Error(`Native binding package version mismatch, expected 0.6.0-pre.22 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
}
return binding;
} catch (e) {
loadErrors.push(e);
}
} else if (process.arch === "arm") {
try {
return require2("./sync.android-arm-eabi.node");
} catch (e) {
loadErrors.push(e);
}
try {
const binding = require2("@tursodatabase/sync-android-arm-eabi");
const bindingPackageVersion = require2("@tursodatabase/sync-android-arm-eabi/package.json").version;
if (bindingPackageVersion !== "0.6.0-pre.22" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") {
throw new Error(`Native binding package version mismatch, expected 0.6.0-pre.22 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
}
return binding;
} catch (e) {
loadErrors.push(e);
}
} else {
loadErrors.push(new Error(`Unsupported architecture on Android ${process.arch}`));
}
} else if (process.platform === "win32") {
if (process.arch === "x64") {
try {
return require2("./sync.win32-x64-msvc.node");
} catch (e) {
loadErrors.push(e);
}
try {
const binding = require2("@tursodatabase/sync-win32-x64-msvc");
const bindingPackageVersion = require2("@tursodatabase/sync-win32-x64-msvc/package.json").version;
if (bindingPackageVersion !== "0.6.0-pre.22" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") {
throw new Error(`Native binding package version mismatch, expected 0.6.0-pre.22 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
}
return binding;
} catch (e) {
loadErrors.push(e);
}
} else if (process.arch === "ia32") {
try {
return require2("./sync.win32-ia32-msvc.node");
} catch (e) {
loadErrors.push(e);
}
try {
const binding = require2("@tursodatabase/sync-win32-ia32-msvc");
const bindingPackageVersion = require2("@tursodatabase/sync-win32-ia32-msvc/package.json").version;
if (bindingPackageVersion !== "0.6.0-pre.22" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") {
throw new Error(`Native binding package version mismatch, expected 0.6.0-pre.22 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
}
return binding;
} catch (e) {
loadErrors.push(e);
}
} else if (process.arch === "arm64") {
try {
return require2("./sync.win32-arm64-msvc.node");
} catch (e) {
loadErrors.push(e);
}
try {
const binding = require2("@tursodatabase/sync-win32-arm64-msvc");
const bindingPackageVersion = require2("@tursodatabase/sync-win32-arm64-msvc/package.json").version;
if (bindingPackageVersion !== "0.6.0-pre.22" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") {
throw new Error(`Native binding package version mismatch, expected 0.6.0-pre.22 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
}
return binding;
} catch (e) {
loadErrors.push(e);
}
} else {
loadErrors.push(new Error(`Unsupported architecture on Windows: ${process.arch}`));
}
} else if (process.platform === "darwin") {
try {
return require2("./sync.darwin-universal.node");
} catch (e) {
loadErrors.push(e);
}
try {
const binding = require2("@tursodatabase/sync-darwin-universal");
const bindingPackageVersion = require2("@tursodatabase/sync-darwin-universal/package.json").version;
if (bindingPackageVersion !== "0.6.0-pre.22" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") {
throw new Error(`Native binding package version mismatch, expected 0.6.0-pre.22 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
}
return binding;
} catch (e) {
loadErrors.push(e);
}
if (process.arch === "x64") {
try {
return require2("./sync.darwin-x64.node");
} catch (e) {
loadErrors.push(e);
}
try {
const binding = require2("@tursodatabase/sync-darwin-x64");
const bindingPackageVersion = require2("@tursodatabase/sync-darwin-x64/package.json").version;
if (bindingPackageVersion !== "0.6.0-pre.22" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") {
throw new Error(`Native binding package version mismatch, expected 0.6.0-pre.22 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
}
return binding;
} catch (e) {
loadErrors.push(e);
}
} else if (process.arch === "arm64") {
try {
return require2("./sync.darwin-arm64.node");
} catch (e) {
loadErrors.push(e);
}
try {
const binding = require2("@tursodatabase/sync-darwin-arm64");
const bindingPackageVersion = require2("@tursodatabase/sync-darwin-arm64/package.json").version;
if (bindingPackageVersion !== "0.6.0-pre.22" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") {
throw new Error(`Native binding package version mismatch, expected 0.6.0-pre.22 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
}
return binding;
} catch (e) {
loadErrors.push(e);
}
} else {
loadErrors.push(new Error(`Unsupported architecture on macOS: ${process.arch}`));
}
} else if (process.platform === "freebsd") {
if (process.arch === "x64") {
try {
return require2("./sync.freebsd-x64.node");
} catch (e) {
loadErrors.push(e);
}
try {
const binding = require2("@tursodatabase/sync-freebsd-x64");
const bindingPackageVersion = require2("@tursodatabase/sync-freebsd-x64/package.json").version;
if (bindingPackageVersion !== "0.6.0-pre.22" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") {
throw new Error(`Native binding package version mismatch, expected 0.6.0-pre.22 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
}
return binding;
} catch (e) {
loadErrors.push(e);
}
} else if (process.arch === "arm64") {
try {
return require2("./sync.freebsd-arm64.node");
} catch (e) {
loadErrors.push(e);
}
try {
const binding = require2("@tursodatabase/sync-freebsd-arm64");
const bindingPackageVersion = require2("@tursodatabase/sync-freebsd-arm64/package.json").version;
if (bindingPackageVersion !== "0.6.0-pre.22" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") {
throw new Err