alinea
Version:
Headless git-based CMS
1,799 lines (1,769 loc) • 72.1 kB
JavaScript
import {
and,
asc,
eq,
gt,
isNotNull,
isNull,
like,
not,
or,
when
} from "../../chunks/chunk-TO6JVYUN.js";
import {
Field,
Functions,
callFunction,
column,
jsonAggregateArray,
jsonArray,
table
} from "../../chunks/chunk-H54PGW2N.js";
import {
Sql,
getData,
getField,
getQuery,
getResolver,
getSelection,
getSql,
getTable,
getTarget,
hasField,
hasQuery,
hasSelection,
hasSql,
hasTable,
hasTarget,
input,
internalData,
internalQuery,
internalResolver,
internalSelection,
internalSql,
internalTarget,
sql
} from "../../chunks/chunk-PNILF4WM.js";
import {
__export
} from "../../chunks/chunk-NZLE2WMY.js";
// src/backend/api/CreateBackend.ts
import { assert } from "alinea/core/util/Assert";
// node_modules/rado/dist/driver.js
var driver_exports = {};
__export(driver_exports, {
"@electric-sql/pglite": () => connect7,
"@libsql/client": () => connect4,
"@neondatabase/serverless": () => connect6,
"@vercel/postgres": () => connect6,
"better-sqlite3": () => connect,
"bun:sqlite": () => connect2,
d1: () => connect3,
mysql2: () => connect5,
pg: () => connect6,
"sql.js": () => connect8
});
// node_modules/rado/dist/universal/functions.js
var insertId = sql.universal({
sqlite: Functions.last_insert_rowid(),
postgres: Functions.lastval(),
mysql: Functions.last_insert_id()
}).mapWith(Number);
function concat(...slices) {
return sql.universal({
mysql: Functions.concat(...slices),
default: sql.join(slices.map(input), sql` || `)
});
}
// node_modules/rado/dist/universal/transactions.js
function txGenerator(create) {
function run(tx) {
const iter = create(tx);
const next = (inner) => {
if (inner instanceof Promise)
return inner.then(iter.next.bind(iter)).catch(iter.throw.bind(iter)).then(handle);
try {
return handle(iter.next(inner));
} catch (err) {
return handle(iter.throw(err));
}
};
const handle = ({ done, value }) => {
if (done) return value;
return next(typeof value === "function" ? tx.transaction(value) : value);
};
return next();
}
return Object.assign(run, {
*[Symbol.iterator]() {
return yield run;
}
});
}
// node_modules/rado/dist/core/Virtual.js
function virtual(alias, source) {
const target = { [internalTarget]: sql.identifier(alias) };
if (source && hasSql(source)) {
const expr = getSql(source);
const name = expr.alias;
if (!name) throw new Error("Cannot alias a virtual field without a name");
return Object.assign(new Field(alias, name, expr), target);
}
return new Proxy(target, {
get(target2, field) {
if (field in target2) return target2[field];
const from = source?.[field];
if (typeof field !== "string") return from;
return target2[field] = new Field(
alias,
field,
from ? getSql(from) : void 0
);
}
});
}
// node_modules/rado/dist/core/Selection.js
var SqlColumn = class {
constructor(sql2, targetName) {
this.sql = sql2;
this.targetName = targetName;
}
result(ctx) {
const value = ctx.values[ctx.index++];
if (!this.sql.mapFromDriverValue) return value;
return this.sql.mapFromDriverValue(value, ctx.specs);
}
};
var ObjectColumn = class {
constructor(nullable, entries) {
this.nullable = nullable;
this.entries = entries;
}
result(ctx) {
const result = {};
let isNullable = this.nullable.size > 0;
for (const entry of this.entries) {
const name = entry[0];
const col = entry[1];
const value = col.result(ctx);
result[name] = value;
if (isNullable) {
if (value === null) {
if (col.targetName && !this.nullable.has(col.targetName))
isNullable = false;
} else {
isNullable = false;
}
}
}
if (isNullable) return null;
return result;
}
};
var Selection = class {
constructor(input2, nullable) {
this.input = input2;
this.nullable = nullable;
const root = this.#defineColumn(nullable, input2);
this.mapRow = root.result.bind(root);
}
mapRow;
makeVirtual(name) {
return virtual(name, this.input);
}
#defineColumn(nullable, input2) {
const expr = getSql(input2);
if (expr) return new SqlColumn(expr, getField(input2)?.targetName);
return new ObjectColumn(
nullable,
Object.entries(input2).map(([name, value]) => [
name,
this.#defineColumn(nullable, value)
])
);
}
fieldNames() {
return this.#fieldNames(this.input, /* @__PURE__ */ new Set());
}
#fieldNames(input2, names, name) {
const expr = getSql(input2);
if (expr) {
let exprName = name ?? expr.alias;
if (!exprName) throw new Error("Missing field name");
while (names.has(exprName)) exprName = `${exprName}_`;
return [exprName];
}
return Object.entries(input2).flatMap(
([name2, value]) => this.#fieldNames(value, names, name2)
);
}
#selectionToSql(input2, names, name) {
const expr = getSql(input2);
if (expr) {
let exprName = name ?? expr.alias;
if (exprName) {
while (names.has(exprName)) exprName = `${exprName}_`;
names.add(exprName);
if (hasField(input2)) {
const field = getField(input2);
if (field.fieldName === exprName) return [expr];
}
return [sql`${expr.forSelection()} as ${sql.identifier(exprName)}`];
}
return [expr];
}
return Object.entries(input2).flatMap(
([name2, value]) => this.#selectionToSql(value, names, name2)
);
}
get [internalSql]() {
return sql.join(this.#selectionToSql(this.input, /* @__PURE__ */ new Set()), sql`, `);
}
join(right, operator) {
return this;
}
};
var TableSelection = class extends Selection {
constructor(table2) {
super(table2, /* @__PURE__ */ new Set());
this.table = table2;
}
join(right, operator) {
const leftTable = getTable(this.table);
const rightTable = getTable(right);
const nullable = new Set(this.nullable);
if (operator === "right" || operator === "full")
nullable.add(leftTable.aliased);
if (operator === "left" || operator === "full")
nullable.add(rightTable.aliased);
return new JoinSelection([this.table, right], nullable);
}
};
var JoinSelection = class _JoinSelection extends Selection {
constructor(tables, nullable) {
super(
Object.fromEntries(tables.map((table2) => [getTable(table2).aliased, table2])),
nullable
);
this.tables = tables;
}
join(right, operator) {
const rightTable = getTable(right);
const nullable = new Set(this.nullable);
if (operator === "right" || operator === "full")
this.tables.map((table2) => getTable(table2).aliased).forEach(nullable.add, nullable);
if (operator === "left" || operator === "full")
nullable.add(rightTable.aliased);
return new _JoinSelection([...this.tables, right], nullable);
}
};
function selection(input2, nullable = []) {
return new Selection(input2, new Set(nullable));
}
((selection2) => {
function table2(table22) {
return new TableSelection(table22);
}
selection2.table = table2;
})(selection || (selection = {}));
// node_modules/rado/dist/core/Query.js
var Executable = class {
#execute;
constructor(exec) {
this.#execute = exec;
}
*[Symbol.iterator]() {
const interim = this.#execute();
const isAsync = interim instanceof Promise;
if (!isAsync) return interim;
let result;
yield interim.then((v) => result = v);
return result;
}
run() {
return this.#execute();
}
// biome-ignore lint/suspicious/noThenProperty:
async then(onfulfilled, onrejected) {
try {
const result = await this.#execute();
return onfulfilled ? onfulfilled(result) : result;
} catch (error) {
return onrejected ? onrejected(error) : Promise.reject(error);
}
}
catch(onrejected) {
return this.then().catch(onrejected);
}
finally(onfinally) {
return this.then().finally(onfinally);
}
};
var QueryBatch = class extends Executable {
constructor(queryResolver, queries) {
super(() => {
return queryResolver.batch(queries).execute();
});
}
};
var Query = class extends Executable {
[internalData];
constructor(data) {
super(() => this.#exec(void 0));
this[internalData] = data;
}
#exec(method, db) {
const data = getData(this);
const resolver = db ? getResolver(db) : data.resolver;
const isSelection = hasSelection(this);
const prepared = resolver.prepare(this, "");
const resultType = method ?? (isSelection ? "all" : "run");
try {
const result = prepared[resultType]();
if (result instanceof Promise)
return result.then((res) => res ?? null).finally(prepared.free.bind(prepared));
prepared.free();
return result ?? null;
} catch (error) {
prepared.free();
throw error;
}
}
all(db) {
return this.#exec("all", db);
}
get(db) {
return this.#exec("get", db);
}
run(db) {
return this.#exec("run", db);
}
prepare(name) {
return getData(this).resolver.prepare(this, name);
}
toSQL(db) {
const resolver = db ? getResolver(db) : getData(this).resolver;
if (!resolver) throw new Error("Query has no resolver");
return resolver.toSQL(this);
}
};
// node_modules/rado/dist/core/query/Delete.js
var Delete = class extends Query {
[internalData];
constructor(data) {
super(data);
this[internalData] = data;
if (data.returning) this[internalSelection] = data.returning;
}
get [internalQuery]() {
return sql.chunk("emitDelete", this);
}
};
var DeleteFrom = class _DeleteFrom extends Delete {
where(...where) {
return new _DeleteFrom({ ...getData(this), where: and(...where) });
}
returning(returning) {
const data = getData(this);
return new Delete({
...data,
returning: returning ? selection(returning) : selection.table(data.from)
});
}
};
// node_modules/rado/dist/core/query/Insert.js
var Insert = class extends Query {
[internalData];
constructor(data) {
super(data);
this[internalData] = data;
if (data.returning) this[internalSelection] = data.returning;
}
get [internalQuery]() {
return sql.chunk("emitInsert", this);
}
};
var InsertCanReturn = class extends Insert {
returning(returning) {
const data = getData(this);
return new Insert({
...data,
returning: returning ? selection(returning) : selection.table(data.into)
});
}
};
var InsertCanConflict = class extends InsertCanReturn {
onConflictDoNothing(onConflict) {
return this.#onConflict(onConflict ?? {});
}
onConflictDoUpdate(onConflict) {
return this.#onConflict(onConflict);
}
onDuplicateKeyUpdate(update) {
return new InsertCanReturn({
...getData(this),
onDuplicateKeyUpdate: this.#updateFields(update.set)
});
}
#updateFields(update) {
return sql.join(
Object.entries(update).map(
([key, value]) => sql`${sql.identifier(key)} = ${input(value)}`
),
sql`, `
);
}
#onConflict({
target,
targetWhere,
set,
setWhere
}) {
const update = set && this.#updateFields(set);
return new InsertCanReturn({
...getData(this),
onConflict: sql.join([
target && sql`(${Array.isArray(target) ? sql.join(target, sql`, `) : target})`,
targetWhere && sql`where ${targetWhere}`,
update ? sql.join([
sql`do update set ${update}`,
setWhere && sql`where ${setWhere}`
]) : sql`do nothing`
])
});
}
};
var defaultKeyword = sql.universal({
sqlite: sql`null`,
default: sql`default`
});
var InsertInto = class {
[internalData];
constructor(data) {
this[internalData] = data;
}
values(insert) {
const { into } = getData(this);
const rows = Array.isArray(insert) ? insert : [insert];
const table2 = getTable(into);
const values = sql.join(
rows.map((row) => {
return sql`(${sql.join(
Object.entries(table2.columns).map(([key, column2]) => {
const value = row[key];
const { $default, mapToDriverValue } = getData(column2);
if (value !== void 0) {
if (value && typeof value === "object" && hasSql(value))
return value;
return input(mapToDriverValue?.(value) ?? value);
}
if ($default) return $default();
return defaultKeyword;
}),
sql`, `
)})`;
}),
sql`, `
);
return new InsertCanConflict({ ...getData(this), values });
}
select(query) {
return new InsertCanConflict({
...getData(this),
select: getQuery(query)
});
}
};
// node_modules/rado/dist/core/query/Union.js
var UnionBase = class extends Query {
[internalData];
#makeSelf() {
const { select } = getData(this);
return select.makeVirtual(Sql.SELF_TARGET);
}
union(right) {
return new Union({
...getData(this),
left: this,
operator: sql`union`,
right: typeof right === "function" ? right(this.#makeSelf()) : right
});
}
unionAll(right) {
return new Union({
...getData(this),
left: this,
operator: sql`union all`,
right: typeof right === "function" ? right(this.#makeSelf()) : right
});
}
intersect(right) {
return new Union({
...getData(this),
left: this,
operator: sql`intersect`,
right: typeof right === "function" ? right(this.#makeSelf()) : right
});
}
intersectAll(right) {
return new Union({
...getData(this),
left: this,
operator: sql`intersect all`,
right: typeof right === "function" ? right(this.#makeSelf()) : right
});
}
except(right) {
return new Union({
...getData(this),
left: this,
operator: sql`except`,
right: typeof right === "function" ? right(this.#makeSelf()) : right
});
}
exceptAll(right) {
return new Union({
...getData(this),
left: this,
operator: sql`except all`,
right: typeof right === "function" ? right(this.#makeSelf()) : right
});
}
};
var Union = class extends UnionBase {
[internalData];
[internalSelection];
constructor(data) {
super(data);
this[internalData] = data;
this[internalSelection] = data.select;
}
get [internalQuery]() {
return sql.chunk("emitUnion", getData(this));
}
};
// node_modules/rado/dist/core/query/Select.js
var Select = class _Select extends UnionBase {
[internalData];
constructor(data) {
super(data);
this[internalData] = data;
}
as(alias) {
const fields = getSelection(this).makeVirtual(alias);
return Object.assign(fields, {
[internalTarget]: sql`(${getQuery(this)}) as ${sql.identifier(
alias
)}`.inlineFields(true)
});
}
from(target) {
const { select: current } = getData(this);
const from = hasTarget(target) ? getTarget(target) : getSql(target);
const isTable = hasTable(target);
const selected = current ?? (isTable ? selection.table(target) : selection(sql`*`));
return new _Select({
...getData(this),
select: selected,
from
});
}
#join(operator, right, on) {
const { from, select: current } = getData(this);
return new _Select({
...getData(this),
select: hasTable(right) ? current?.join(right, operator) : current,
from: sql.join([
from,
sql.unsafe(`${operator} join`),
getTarget(right),
sql`on ${on}`
])
});
}
leftJoin(right, on) {
return this.#join("left", right, on);
}
rightJoin(right, on) {
return this.#join("right", right, on);
}
innerJoin(right, on) {
return this.#join("inner", right, on);
}
fullJoin(right, on) {
return this.#join("full", right, on);
}
where(...where) {
return new _Select({ ...getData(this), where: and(...where) });
}
groupBy(...exprs) {
return new _Select({
...getData(this),
groupBy: sql.join(exprs, sql.unsafe(", "))
});
}
having(having) {
return new _Select({
...getData(this),
having: typeof having === "function" ? having(getSelection(this).input) : having
});
}
orderBy(...exprs) {
return new _Select({
...getData(this),
orderBy: sql.join(exprs, sql.unsafe(", "))
});
}
limit(limit) {
return new _Select({ ...getData(this), limit: input(limit) });
}
offset(offset) {
return new _Select({
...getData(this),
offset: input(offset)
});
}
get [internalSelection]() {
const { select } = getData(this);
if (!select) throw new Error("No selection defined");
return select;
}
get [internalQuery]() {
return sql.chunk("emitSelect", getData(this));
}
get [internalSql]() {
return sql`(${getQuery(this)})`;
}
};
// node_modules/rado/dist/core/query/Update.js
var Update = class extends Query {
[internalData];
constructor(data) {
super(data);
this[internalData] = data;
if (data.returning) this[internalSelection] = data.returning;
}
get [internalQuery]() {
return sql.chunk("emitUpdate", this);
}
};
var UpdateTable = class _UpdateTable extends Update {
set(values) {
const { table: table2 } = getData(this);
const set = sql.join(
Object.entries(values).map(([key, value]) => {
const column2 = getTable(table2).columns[key];
const { mapToDriverValue } = getData(column2);
const expr = value && typeof value === "object" && hasSql(value) ? value : input(mapToDriverValue?.(value) ?? value);
return sql`${sql.identifier(key)} = ${expr}`;
}),
sql`, `
);
return new _UpdateTable({ ...getData(this), set });
}
where(...where) {
return new _UpdateTable({
...getData(this),
where: and(...where)
});
}
returning(returning) {
const data = getData(this);
return new Update({
...data,
returning: returning ? selection(returning) : selection.table(data.table)
});
}
};
// node_modules/rado/dist/core/Builder.js
var BuilderBase = class {
[internalData];
constructor(data = {}) {
this[internalData] = data;
}
select(input2) {
return new Select({
...getData(this),
select: input2 && selection(input2)
});
}
selectDistinct(input2) {
return new Select({
...getData(this),
select: input2 && selection(input2),
distinct: true
});
}
selectDistinctOn(columns, input2) {
return new Select({
...getData(this),
select: input2 && selection(input2),
distinctOn: columns
});
}
update(table2) {
return new UpdateTable({ ...getData(this), table: table2 });
}
insert(into) {
return new InsertInto({ ...getData(this), into });
}
delete(from) {
return new DeleteFrom({ ...getData(this), from });
}
};
var Builder = class extends BuilderBase {
$with(cteName) {
return {
as(query) {
const fields = getSelection(query).makeVirtual(cteName);
return Object.assign(fields, {
[internalQuery]: getQuery(query).nameSelf(cteName)
});
}
};
}
with(...definitions) {
return new BuilderBase({
...getData(this),
cte: { recursive: false, definitions }
});
}
withRecursive(...definitions) {
return new BuilderBase({
...getData(this),
cte: { recursive: true, definitions }
});
}
};
// node_modules/rado/dist/core/Resolver.js
var Resolver = class {
#driver;
#dialect;
constructor(driver, dialect) {
this.#driver = driver;
this.#dialect = dialect;
}
toSQL(query) {
const emitter = this.#dialect.emit(query);
return { sql: emitter.sql, params: emitter.bind() };
}
prepare(query, name) {
const isSelection = hasSelection(query);
const mapRow = isSelection ? getSelection(query).mapRow : void 0;
const emitter = this.#dialect.emit(query);
const stmt = this.#driver.prepare(emitter.sql, {
isSelection,
name
});
return new PreparedStatement(emitter, stmt, mapRow, this.#driver);
}
batch(queries) {
return new Batch(
this.#driver,
queries.map((query) => {
const isSelection = hasSelection(query);
const mapRow = isSelection ? getSelection(query).mapRow : void 0;
const emitter = this.#dialect.emit(query);
return { sql: emitter.sql, params: emitter.bind(), isSelection, mapRow };
})
);
}
};
var Batch = class {
#driver;
#queries;
constructor(driver, queries) {
this.#driver = driver;
this.#queries = queries;
}
#transform = (results) => {
const ctx = {
values: void 0,
index: 0,
specs: this.#driver
};
for (let i = 0; i < this.#queries.length; i++) {
const { mapRow } = this.#queries[i];
if (!mapRow) continue;
const rows = results[i];
for (let j = 0; j < results[i].length; j++) {
ctx.values = rows[i];
ctx.index = 0;
rows[i] = mapRow(ctx);
}
}
return results;
};
execute() {
const results = this.#driver.batch(this.#queries);
if (results instanceof Promise) return results.then(this.#transform);
return this.#transform(results);
}
};
var PreparedStatement = class {
#emitter;
#stmt;
#mapRow;
#specs;
constructor(emitter, stmt, mapRow, specs) {
this.#emitter = emitter;
this.#stmt = stmt;
this.#mapRow = mapRow;
this.#specs = specs;
}
#transform = (rows) => {
if (!this.#mapRow) return rows;
const ctx = {
values: void 0,
index: 0,
specs: this.#specs
};
for (let i = 0; i < rows.length; i++) {
ctx.values = rows[i];
ctx.index = 0;
rows[i] = this.#mapRow(ctx);
}
return rows;
};
all(inputs) {
const rows = this.#stmt.values(this.#emitter.bind(inputs));
if (rows instanceof Promise) return rows.then(this.#transform);
return this.#transform(rows);
}
get(inputs) {
const rows = this.all(inputs);
if (rows instanceof Promise) return rows.then((rows2) => rows2[0]);
return rows[0];
}
run(inputs) {
return this.#stmt.run(this.#emitter.bind(inputs));
}
async execute(inputs) {
return this.all(inputs);
}
free() {
this.#stmt.free();
}
};
// node_modules/rado/dist/core/Database.js
var Database = class extends Builder {
driver;
dialect;
diff;
[internalResolver];
constructor(driver, dialect, diff) {
const resolver = new Resolver(driver, dialect);
super({ resolver });
this[internalResolver] = resolver;
this.driver = driver;
this.dialect = dialect;
this.diff = diff;
}
close() {
return this.driver.close();
}
[Symbol.dispose]() {
this.close();
}
async [Symbol.asyncDispose]() {
return this.close();
}
create(...tables) {
return new QueryBatch(
getResolver(this),
tables.flatMap((table2) => getTable(table2).create())
);
}
drop(...tables) {
return new QueryBatch(
getResolver(this),
tables.map((table2) => getTable(table2).drop())
);
}
migrate(...tables) {
const computeDiff = this.diff;
return this.transaction(
txGenerator(function* (tx) {
for (const table2 of tables) {
const diff = yield* computeDiff(table2);
if (diff.length > 0) yield* tx.batch(diff.map(sql.unsafe));
}
})
);
}
batch(queries) {
return new QueryBatch(getResolver(this), queries);
}
execute(input2) {
const emitter = this.dialect.emit(input2);
if (emitter.hasParams) throw new Error("Query has parameters");
return this.driver.exec(emitter.sql);
}
transaction(run, options = {}) {
return this.driver.transaction(
(inner) => {
const tx = new Transaction(inner, this.dialect, this.diff);
return run(tx);
},
{ async: run.constructor.name === "AsyncFunction", ...options }
);
}
};
var Rollback = class extends Error {
constructor(data) {
super("Rollback");
this.data = data;
}
};
var Transaction = class extends Database {
rollback(data) {
throw new Rollback(data);
}
};
var SyncDatabase = class extends Database {
};
var AsyncDatabase = class extends Database {
};
// node_modules/rado/dist/sqlite/columns.js
function boolean(name) {
return column({
name,
type: column.integer(),
mapFromDriverValue(value) {
return value === 1;
},
mapToDriverValue(value) {
return value ? 1 : 0;
}
});
}
function integer(name) {
return column({ name, type: column.integer() });
}
function text(name) {
return column({ name, type: column.text() });
}
// node_modules/rado/dist/core/Dialect.js
var Dialect = class {
runtime;
#createEmitter;
constructor(runtime, createEmitter) {
this.runtime = runtime;
this.#createEmitter = createEmitter;
}
emit = (input2) => {
const sql2 = hasQuery(input2) ? getQuery(input2) : getSql(input2);
const emitter = new this.#createEmitter(this.runtime);
sql2.emitTo(emitter);
return emitter;
};
inline = (input2) => {
const sql2 = hasQuery(input2) ? getQuery(input2) : getSql(input2);
const emitter = new this.#createEmitter(this.runtime);
sql2.inlineValues().emitTo(emitter);
return emitter.sql;
};
};
// node_modules/rado/dist/core/Param.js
var NamedParam = class {
constructor(name) {
this.name = name;
}
};
var ValueParam = class {
constructor(value) {
this.value = value;
}
};
// node_modules/rado/dist/core/Emitter.js
var Emitter = class {
#runtime;
sql = "";
params = [];
constructor(runtime) {
this.#runtime = runtime;
}
get hasParams() {
return this.params.length > 0;
}
bind(inputs) {
return this.params.map((param) => {
if (param instanceof ValueParam) return this.processValue(param.value);
if (inputs && param.name in inputs)
return this.processValue(inputs[param.name]);
throw new Error(`Missing input for named parameter: ${param.name}`);
});
}
processValue(value) {
return value;
}
emitIdentifierOrSelf(value) {
if (value === Sql.SELF_TARGET) {
if (!this.selfName) throw new Error("Self target not defined");
this.emitIdentifier(this.selfName);
} else {
this.emitIdentifier(value);
}
}
selfName;
emitSelf({ name, inner }) {
this.selfName = name;
inner.emitTo(this);
this.selfName = void 0;
}
emitUnsafe(value) {
this.sql += value;
}
emitField({ targetName, fieldName }) {
this.emitIdentifierOrSelf(targetName);
this.emitUnsafe(".");
this.emitIdentifier(fieldName);
}
emitCreateTable(tableApi) {
sql.join([
sql`create table`,
//ifNotExists ? sql`if not exists` : undefined,
tableApi.target(),
sql`(${tableApi.createDefinition()})`
]).emitTo(this);
}
emitColumn(column2) {
sql.join([
column2.type,
column2.primary && sql`primary key`,
column2.notNull && sql`not null`,
column2.isUnique && sql`unique`,
column2.autoIncrement && sql`autoincrement`,
column2.defaultValue && sql`default ${column2.defaultValue}`,
column2.references && sql`references ${sql.chunk("emitReferences", [column2.references()])}`,
column2.onUpdate && sql`on update ${column2.onUpdate}`
]).emitTo(this);
}
emitReferences(fields) {
callFunction(
sql.identifier(fields[0].targetName),
fields.map((field) => sql.identifier(field.fieldName))
).emitTo(this);
}
emitDelete(deleteOp) {
const { cte, from, where, returning } = getData(deleteOp);
if (cte) this.emitWith(cte);
const table2 = getTable(from);
sql.query({
deleteFrom: sql.identifier(table2.name),
where,
returning
}).emitTo(this);
}
emitInsert(insert) {
const {
cte,
into,
values,
select,
onConflict,
onDuplicateKeyUpdate,
returning
} = getData(insert);
if (cte) this.emitWith(cte);
const table2 = getTable(into);
const tableName = sql.identifier(table2.name);
sql.query({
insertInto: sql`${tableName}(${table2.listColumns()})`,
...values ? { values } : { "": select },
onConflict,
onDuplicateKeyUpdate,
returning
}).inlineFields(false).emitTo(this);
}
emitSelect({
select,
cte,
from,
distinct,
distinctOn,
where,
groupBy,
orderBy,
having,
limit,
offset
}) {
if (cte) this.emitWith(cte);
const prefix = distinctOn ? sql`distinct on (${sql.join(distinctOn, sql`, `)})` : distinct && sql`distinct`;
sql.query({
select: sql.join([prefix, select]),
from,
where,
groupBy,
orderBy,
having,
limit,
offset
}).emitTo(this);
}
emitUnion({ left, operator, right }) {
sql.join([getQuery(left), operator, getQuery(right)]).emitTo(this);
}
emitUpdate(update) {
const { cte, table: table2, set, where, returning } = getData(update);
const tableApi = getTable(table2);
if (cte) this.emitWith(cte);
sql.query({
update: sql.identifier(tableApi.name),
set,
where,
returning
}).inlineFields(false).emitTo(this);
}
emitWith(cte) {
sql.query({
[cte.recursive ? "withRecursive" : "with"]: sql.join(
cte.definitions.map((cte2) => {
const query = getQuery(cte2);
const target = getTarget(cte2);
return sql`${target} as (${query})`;
}),
sql`, `
)
}).add(sql` `).emitTo(this);
}
emitInclude(data) {
const wrapQuery = Boolean(data.limit || data.offset || data.orderBy);
const innerQuery = sql.chunk("emitSelect", data);
const inner = wrapQuery ? sql`select * from (${innerQuery})` : innerQuery;
if (!data.select) throw new Error("No selection defined");
const fields = data.select.fieldNames();
const subject = jsonArray(
...fields.map((name) => sql`_.${sql.identifier(name)}`)
);
sql`(select ${data.first ? subject : jsonAggregateArray(subject)} from (${inner}) as _)`.emitTo(this);
}
emitUniversal(runtimes) {
const sql2 = runtimes[this.#runtime] ?? runtimes.default;
if (!sql2) throw new Error("Unsupported runtime");
sql2.emitTo(this);
}
};
// node_modules/rado/dist/sqlite/dialect.js
var DOUBLE_QUOTE = '"';
var ESCAPE_DOUBLE_QUOTE = '""';
var MATCH_DOUBLE_QUOTE = /"/g;
var SINGLE_QUOTE = "'";
var ESCAPE_SINGLE_QUOTE = "''";
var MATCH_SINGLE_QUOTE = /'/g;
var sqliteDialect = new Dialect(
"sqlite",
class extends Emitter {
processValue(value) {
return typeof value === "boolean" ? value ? 1 : 0 : value;
}
emitValue(value) {
this.sql += "?";
this.params.push(new ValueParam(value));
}
emitJsonPath({ target, asSql, segments }) {
target.emitTo(this);
this.sql += asSql ? "->>" : "->";
this.sql += this.quoteString(
`$${segments.map((p) => typeof p === "number" ? `[${p}]` : `.${p}`).join("")}`
);
}
emitInline(value) {
if (value === null || value === void 0) return this.sql += "null";
if (typeof value === "number") return this.sql += value;
if (typeof value === "string")
return this.sql += this.quoteString(value);
if (typeof value === "boolean") return this.sql += value ? "1" : "0";
this.sql += `json(${this.quoteString(JSON.stringify(value))})`;
}
emitPlaceholder(name) {
this.sql += "?";
this.params.push(new NamedParam(name));
}
emitIdentifier(identifier) {
this.sql += DOUBLE_QUOTE + identifier.replace(MATCH_DOUBLE_QUOTE, ESCAPE_DOUBLE_QUOTE) + DOUBLE_QUOTE;
}
quoteString(input2) {
return SINGLE_QUOTE + input2.replace(MATCH_SINGLE_QUOTE, ESCAPE_SINGLE_QUOTE) + SINGLE_QUOTE;
}
}
);
// node_modules/rado/dist/sqlite/diff.js
var TableInfo = table("TableInfo", {
cid: integer().notNull(),
name: text().notNull(),
type: text().notNull(),
notnull: boolean().notNull(),
dflt_value: text(),
pk: integer().notNull()
});
var SqliteMaster = table("SqliteMaster", {
type: text().notNull(),
name: text().notNull(),
tbl_name: text().notNull(),
rootpage: integer().notNull(),
sql: text().notNull()
});
var inline = (sql2) => sqliteDialect.inline(sql2);
var sqliteDiff = (targetTable) => {
return txGenerator(function* (tx) {
const tableApi = getTable(targetTable);
const columnInfo = yield* tx.select(TableInfo).from(sql`pragma_table_info(${sql.inline(tableApi.name)}) as "TableInfo"`);
const indexInfo = yield* tx.select(SqliteMaster).from(sql`sqlite_master as "SqliteMaster"`).where(
eq(SqliteMaster.tbl_name, tableApi.name),
eq(SqliteMaster.type, "index")
);
const hasSinglePrimaryKey = columnInfo.reduce((acc, column2) => acc + column2.pk, 0) === 1;
const localColumns = new Map(
columnInfo.map((column2) => {
return [
column2.name,
inline(
sql.chunk("emitColumn", {
type: sql.unsafe(column2.type.toLowerCase()),
notNull: column2.notnull,
primary: hasSinglePrimaryKey && column2.pk === 1,
defaultValue: column2.dflt_value !== null ? sql.unsafe(column2.dflt_value) : void 0
})
)
];
})
);
const schemaColumns = new Map(
Object.entries(tableApi.columns).map(([name, column2]) => {
const columnApi = getData(column2);
return [
columnApi.name ?? name,
inline(sql.chunk("emitColumn", columnApi))
];
})
);
const localIndexes = new Map(
indexInfo.filter((index) => !index.name.startsWith("sqlite_autoindex_")).map((index) => [index.name, index.sql])
);
const schemaIndexes = new Map(
Object.entries(tableApi.indexes()).map(([name, index]) => {
const indexApi = getData(index);
return [name, inline(indexApi.toSql(tableApi.name, name, false))];
})
);
const stmts = [];
const columnNames = /* @__PURE__ */ new Set([
...localColumns.keys(),
...schemaColumns.keys()
]);
for (const columnName of columnNames) {
const localInstruction = localColumns.get(columnName);
const schemaInstruction = schemaColumns.get(columnName);
if (!schemaInstruction) {
stmts.push(
sql.query({
alterTable: sql.identifier(tableApi.name),
dropColumn: sql.identifier(columnName)
})
);
} else if (!localInstruction) {
stmts.push(
sql.query({
alterTable: sql.identifier(tableApi.name),
addColumn: [
sql.identifier(columnName),
sql.unsafe(schemaInstruction)
]
})
);
} else if (localInstruction !== schemaInstruction) {
return recreate();
}
}
const indexNames = /* @__PURE__ */ new Set([
...localIndexes.keys(),
...schemaIndexes.keys()
]);
for (const indexName of indexNames) {
const localInstruction = localIndexes.get(indexName);
const schemaInstruction = schemaIndexes.get(indexName);
const dropLocal = sql.query({
dropIndex: sql.identifier(indexName)
});
if (!schemaInstruction) {
stmts.unshift(dropLocal);
} else if (schemaInstruction && !localInstruction) {
stmts.push(sql.unsafe(schemaInstruction));
} else if (schemaInstruction && localInstruction !== schemaInstruction) {
stmts.unshift(dropLocal);
stmts.push(sql.unsafe(schemaInstruction));
}
}
try {
yield* txGenerator(function* (sp) {
yield* sp.batch(stmts);
const [tableInfo] = yield* sp.select(SqliteMaster.sql).from(sql`sqlite_master as "SqliteMaster"`).where(
eq(SqliteMaster.tbl_name, tableApi.name),
eq(SqliteMaster.type, "table")
);
sp.rollback(tableInfo);
});
} catch (err) {
if (!(err instanceof Rollback)) throw err;
const localInstruction = err.data;
const schemaInstruction = inline(tableApi.createTable());
const stripStmt = (q) => q.slice("create table ".length);
if (stripStmt(localInstruction) !== stripStmt(schemaInstruction)) {
return recreate();
}
}
return stmts.map(inline);
function recreate() {
const tempName = `new_${tableApi.name}`;
const tempTable = table(tempName, tableApi.columns);
const missingColumns = new Set(
Array.from(columnNames).filter((name) => !localColumns.has(name))
);
const selection2 = Object.fromEntries(
Object.entries(tableApi.columns).map(([name, column2]) => {
const columnApi = getData(column2);
const key = columnApi.name ?? name;
if (missingColumns.has(key))
return [name, columnApi.defaultValue ?? sql`null`];
return [name, targetTable[name]];
})
);
return [
// Create a new temporary table with the new definition
tableApi.createTable(tempName),
// Copy the data from the old table to the new table
getQuery(
tx.insert(tempTable).select(tx.select(selection2).from(targetTable))
),
// Drop the old table
sql.query({ dropTable: sql.identifier(tableApi.name) }),
// Rename the temporary table to the old table name
sql.query({
alterTable: sql.identifier(tempName),
renameTo: sql.identifier(tableApi.name)
}),
// Create missing indexes
...tableApi.createIndexes()
].map(inline);
}
});
};
// node_modules/rado/dist/sqlite/transactions.js
var locks = /* @__PURE__ */ new WeakMap();
function execTransaction(driver, depth, wrap, run, options) {
const needsLock = options.async;
const behavior = options.behavior ?? "deferred";
if (!needsLock) return transact();
let trigger;
const lock = new Promise((resolve) => trigger = resolve);
const current = Promise.resolve(locks.get(driver));
locks.set(driver, lock);
return current.then(transact).finally(trigger);
function transact() {
try {
driver.exec(depth > 0 ? `savepoint d${depth}` : `begin ${behavior}`);
const result = run(wrap(depth + 1));
if (result instanceof Promise) return result.then(release, rollback);
return release(result);
} catch (error) {
return rollback(error);
}
}
function release(result) {
driver.exec(depth > 0 ? `release d${depth}` : "commit");
return result;
}
function rollback(error) {
driver.exec(depth > 0 ? `rollback to d${depth}` : "rollback");
throw error;
}
}
// node_modules/rado/dist/driver/better-sqlite3.js
var PreparedStatement2 = class {
constructor(stmt, isSelection) {
this.stmt = stmt;
this.isSelection = isSelection;
}
all(params) {
return this.stmt.all(...params);
}
run(params) {
return this.stmt.run(...params);
}
get(params) {
return this.stmt.get(...params);
}
values(params) {
if (this.isSelection)
return this.stmt.raw(true).all(...params);
this.stmt.run(...params);
return [];
}
free() {
}
};
var BetterSqlite3Driver = class _BetterSqlite3Driver {
constructor(client, depth = 0) {
this.client = client;
this.depth = depth;
}
parsesJson = false;
supportsTransactions = true;
exec(query) {
this.client.exec(query);
}
close() {
this.client.close();
}
prepare(sql2, options) {
return new PreparedStatement2(this.client.prepare(sql2), options.isSelection);
}
batch(queries) {
return this.transaction(
(tx) => queries.map(
({ sql: sql2, params, isSelection }) => tx.prepare(sql2, { isSelection }).values(params)
),
{}
);
}
transaction(run, options) {
return execTransaction(
this,
this.depth,
(depth) => new _BetterSqlite3Driver(this.client, depth),
run,
options
);
}
};
function connect(db) {
return new SyncDatabase(
new BetterSqlite3Driver(db),
sqliteDialect,
sqliteDiff
);
}
// node_modules/rado/dist/driver/bun-sqlite.js
var PreparedStatement3 = class {
constructor(stmt) {
this.stmt = stmt;
}
all(params) {
return this.stmt.all(...params);
}
run(params) {
return this.stmt.run(...params);
}
get(params) {
return this.stmt.get(...params);
}
values(params) {
return this.stmt.values(...params);
}
free() {
this.stmt.finalize();
}
};
var BunSqliteDriver = class _BunSqliteDriver {
constructor(client, depth = 0) {
this.client = client;
this.depth = depth;
}
parsesJson = false;
supportsTransactions = true;
exec(query) {
this.client.exec(query);
}
close() {
this.client.close();
}
prepare(sql2) {
return new PreparedStatement3(this.client.prepare(sql2));
}
batch(queries) {
return this.transaction((tx) => {
return queries.map(({ sql: sql2, params }) => tx.prepare(sql2).values(params));
}, {});
}
transaction(run, options) {
return execTransaction(
this,
this.depth,
(depth) => new _BunSqliteDriver(this.client, depth),
run,
options
);
}
};
function connect2(db) {
return new SyncDatabase(new BunSqliteDriver(db), sqliteDialect, sqliteDiff);
}
// node_modules/rado/dist/driver/d1.js
var PreparedStatement4 = class {
constructor(stmt, isSelection) {
this.stmt = stmt;
this.isSelection = isSelection;
}
async all(params) {
return this.stmt.bind(...params).all().then(({ results }) => results);
}
async run(params) {
const results = await this.stmt.bind(...params).run();
}
async get(params) {
return this.stmt.bind(...params).first();
}
async values(params) {
if (this.isSelection) return this.stmt.bind(...params).raw();
await this.stmt.bind(...params).run();
return [];
}
free() {
}
};
var D1Driver = class {
constructor(client) {
this.client = client;
}
parsesJson = false;
supportsTransactions = false;
async exec(query) {
await this.client.exec(query);
}
prepare(sql2, options) {
return new PreparedStatement4(this.client.prepare(sql2), options.isSelection);
}
async close() {
}
async batch(queries) {
const stmts = queries.map(
({ sql: sql2, params }) => this.client.prepare(sql2).bind(...params)
);
const rows = await this.client.batch(stmts);
return rows.map((row) => row.results);
}
async transaction() {
throw new Error("Transactions are not supported in D1");
}
};
function connect3(client) {
return new AsyncDatabase(new D1Driver(client), sqliteDialect, sqliteDiff);
}
// node_modules/rado/dist/driver/libsql.js
var PreparedStatement5 = class {
constructor(client, sql2) {
this.client = client;
this.sql = sql2;
}
async all(params) {
const result = await this.client.execute({ sql: this.sql, args: params });
return result.rows;
}
async run(params) {
const result = await this.client.execute({ sql: this.sql, args: params });
}
async get(params) {
return (await this.all(params))[0] ?? null;
}
async values(params) {
const result = await this.client.execute({ sql: this.sql, args: params });
return result.rows;
}
free() {
}
};
var LibSQLClient = class _LibSQLClient {
constructor(client, depth = 0) {
this.client = client;
this.depth = depth;
}
parsesJson = false;
supportsTransactions = true;
async exec(query) {
await this.client.execute(query);
}
prepare(sql2, options) {
return new PreparedStatement5(this.client, sql2);
}
async close() {
if ("close" in this.client) return this.client.close();
}
async batch(queries) {
const stmts = queries.map(({ sql: sql2, params }) => {
return { sql: sql2, args: params };
});
const rows = await this.client.batch(stmts);
return rows.map((row) => row.rows);
}
async transaction(run, options) {
const client = "transaction" in this.client ? await this.client.transaction() : this.client;
const driver = new _LibSQLClient(client, this.depth + 1);
if (this.depth > 0) await client.execute(`savepoint d${this.depth}`);
try {
const result = await run(driver);
if (this.depth > 0)
await client.execute(`release savepoint d${this.depth}`);
else await client.commit();
return result;
} catch (error) {
if (this.depth > 0)
await client.execute(`rollback to savepoint d${this.depth}`);
else await client.rollback();
throw error;
} finally {
if (this.depth === 0) client.close();
}
}
};
function connect4(client) {
return new AsyncDatabase(new LibSQLClient(client), sqliteDialect, sqliteDiff);
}
// node_modules/rado/dist/mysql/dialect.js
var BACKTICK = "`";
var ESCAPE_BACKTICK = "``";
var MATCH_BACKTICK = /`/g;
var SINGLE_QUOTE2 = "'";
var ESCAPE_SINGLE_QUOTE2 = "''";
var MATCH_SINGLE_QUOTE2 = /'/g;
var mysqlDialect = new Dialect(
"mysql",
class extends Emitter {
runtime = "mysql";
paramIndex = 0;
emitValue(value) {
this.sql += "?";
this.params.push(new ValueParam(value));
}
emitJsonPath({ target, asSql, segments }) {
target.emitTo(this);
this.sql += asSql ? "->>" : "->";
this.sql += this.quoteString(
`$${segments.map((p) => typeof p === "number" ? `[${p}]` : `.${p}`).join("")}`
);
}
emitInline(value) {
if (value === null || value === void 0) return this.sql += "null";
if (typeof value === "number" || typeof value === "boolean")
return this.sql += value;
if (typeof value === "string")
return this.sql += this.quoteString(value);
this.sql += this.quoteString(JSON.stringify(value));
}
emitPlaceholder(name) {
this.sql += "?";
this.params.push(new NamedParam(name));
}
quoteString(input2) {
return SINGLE_QUOTE2 + input2.replace(MATCH_SINGLE_QUOTE2, ESCAPE_SINGLE_QUOTE2) + SINGLE_QUOTE2;
}
emitIdentifier(identifier) {
this.sql += BACKTICK + identifier.replace(MATCH_BACKTICK, ESCAPE_BACKTICK) + BACKTICK;
}
}
);
// node_modules/rado/dist/core/Schema.js
function schema(schemaName) {
return {
table(tableName, columns, config) {
return table(tableName, columns, config, schemaName);
}
};
}
// node_modules/rado/dist/mysql/columns.js
function integer2(name) {
return column({ name, type: column.integer() });
}
function text2(name) {
return column({ name, type: column.text() });
}
// node_modules/rado/dist/mysql/diff.js
var ns = schema("information_schema");
var Information = ns.table("columns", {
table_name: text2().notNull(),
column_name: text2().notNull(),
column_type: text2().notNull(),
is_nullable: text2().notNull(),
column_default: text2(),
extra: text2().notNull(),
table_schema: text2().notNull()
});
var Statistics = ns.table("statistics", {
table_name: text2().notNull(),
column_name: text2().notNull(),
index_name: text2().notNull(),
non_unique: integer2().notNull(),
seq_in_index: integer2().notNull(),
table_schema: text2().notNull()
});
var TableConstraints = ns.table("table_constraints", {
constraint_name: text2().notNull(),
table_name: text2().notNull(),
constraint_type: text2().notNull(),
table_schema: text2().notNull()
});
var inline2 = (sql2) => mysqlDialect.inline(sql2);
var mysqlDiff = (hasTable2) => {
return txGenerator(function* (tx) {
const tableApi = getTable(hasTable2);
const stmts = [];
const columnInfo = yield* tx.select({
name: Information.column_name,
type: Information.column_type,
notNull: eq(Information.is_nullable, "NO"),
defaultValue: Information.column_default,
extra: Information.extra
}).from(Information).where(
eq(Information.table_name, tableApi.name),
eq(Information.table_schema, sql`database()`)
);
const indexInfo = yield* tx.select({
index_name: Statistics.index_name,
column_name: Statistics.column_name,
non_unique: Statistics.non_unique,
seq_in_index: Statistics.seq_in_index
}).from(Statistics).where(
eq(Statistics.table_name, tableApi.name),
eq(Statistics.table_schema, sql`database()`)
).orderBy(Statistics.index_name, Statistics.seq_in_index);
const indexMap = /* @__PURE__ */ new Map();
for (const index of indexInfo) {
if (!indexMap.has(index.index_name)) {
indexMap.set(index.index_name, []);
}
indexMap.get(index.index_name).push(index.column_name);
}
const localColumns = new Map(
columnInfo.map((column2) => {
let type = column2.type.toLowerCase();
const isAutoIncrement = column2.extra.toLowerCase().includes("auto_increment");
if (isAutoIncrement) {
if (type.includes("bigint")) type = "bigserial";
else if (type.includes("smallint")) type = "smallserial";
else type = "serial";
}
return [
column2.name,
{
type: sql.unsafe(type),
notNull: column2.notNull && !isAutoIncrement,
defaultValue: column2.defaultValue && !isAutoIncrement ? sql.unsafe(column2.defaultValue) : void 0
}
];
})
);
const schemaColumns = new Map(
Object.entries(tableApi.columns).map(([name, column2]) => {
const columnApi = getData(column2);
return [columnApi.name ?? name, columnApi];
})
);
const columnNames = /* @__PURE__ */ new Set([
...localColumns.keys(),
...schemaColumns.keys()
]);
for (const columnName of columnNames) {
const alterTable = sql.identifier(tableApi.name);
const column2 = sql.identifier(columnName);
const localInstruction =