mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-24 20:25:36 -04:00
297 lines
11 KiB
TypeScript
297 lines
11 KiB
TypeScript
/* oxlint-disable */
|
|
import { Effect } from "effect"
|
|
import type { SqlError } from "effect/unstable/sql/SqlError"
|
|
import type { EffectCacheShape } from "drizzle-orm/cache/core/cache-effect"
|
|
import type { MutationOption } from "drizzle-orm/cache/core/cache"
|
|
import type { QueryEffectHKTBase } from "drizzle-orm/effect-core/query-effect"
|
|
import { entityKind } from "drizzle-orm/entity"
|
|
import type { TypedQueryBuilder } from "drizzle-orm/query-builders/query-builder"
|
|
import type { AnyRelations, EmptyRelations } from "drizzle-orm/relations"
|
|
import { SelectionProxyHandler } from "drizzle-orm/selection-proxy"
|
|
import { type ColumnsSelection, type SQL, sql, type SQLWrapper } from "drizzle-orm/sql/sql"
|
|
import type { SQLiteAsyncDialect } from "drizzle-orm/sqlite-core/dialect"
|
|
import { QueryBuilder } from "drizzle-orm/sqlite-core/query-builders/query-builder"
|
|
import type { SelectedFields } from "drizzle-orm/sqlite-core/query-builders/select.types"
|
|
import type { SQLiteTransactionConfig } from "drizzle-orm/sqlite-core/session"
|
|
import type { SQLiteTable } from "drizzle-orm/sqlite-core/table"
|
|
import type { SQLiteViewBase } from "drizzle-orm/sqlite-core/view-base"
|
|
import { WithSubquery } from "drizzle-orm/subquery"
|
|
import type { WithBuilder } from "drizzle-orm/sqlite-core/subquery"
|
|
import { SQLiteEffectCountBuilder } from "./count"
|
|
import { SQLiteEffectDeleteBase } from "./delete"
|
|
import { SQLiteEffectInsertBuilder } from "./insert"
|
|
import { SQLiteEffectRelationalQueryBuilder } from "./query"
|
|
import { SQLiteEffectRaw } from "./raw"
|
|
import { SQLiteEffectSelectBuilder } from "./select"
|
|
import type { SQLiteEffectSelectBase } from "./select"
|
|
import type { SQLiteEffectSession, SQLiteEffectTransaction } from "./session"
|
|
import { SQLiteEffectUpdateBuilder } from "./update"
|
|
|
|
export class SQLiteEffectDatabase<
|
|
TEffectHKT extends QueryEffectHKTBase,
|
|
TRunResult,
|
|
TRelations extends AnyRelations = EmptyRelations,
|
|
> {
|
|
static readonly [entityKind]: string = "SQLiteEffectDatabase"
|
|
|
|
declare readonly _: {
|
|
readonly relations: TRelations
|
|
readonly session: SQLiteEffectSession<TEffectHKT, TRunResult, TRelations>
|
|
}
|
|
|
|
query: {
|
|
[K in keyof TRelations]: SQLiteEffectRelationalQueryBuilder<TRelations, TRelations[K], TEffectHKT>
|
|
}
|
|
|
|
constructor(
|
|
/** @internal */
|
|
readonly dialect: SQLiteAsyncDialect,
|
|
/** @internal */
|
|
readonly session: SQLiteEffectSession<TEffectHKT, TRunResult, TRelations>,
|
|
relations: TRelations,
|
|
readonly rowModeRQB?: boolean,
|
|
readonly forbidJsonb?: boolean,
|
|
) {
|
|
this._ = {
|
|
relations,
|
|
session,
|
|
}
|
|
|
|
this.query = {} as (typeof this)["query"]
|
|
for (const [tableName, relation] of Object.entries(relations)) {
|
|
;(this.query as SQLiteEffectDatabase<TEffectHKT, TRunResult, AnyRelations>["query"])[tableName] =
|
|
new SQLiteEffectRelationalQueryBuilder(
|
|
relations,
|
|
relations[relation.name]!.table as SQLiteTable,
|
|
relation,
|
|
dialect,
|
|
session,
|
|
rowModeRQB,
|
|
forbidJsonb,
|
|
)
|
|
}
|
|
|
|
this.$cache = {
|
|
invalidate: (_params: MutationOption) => Effect.void,
|
|
}
|
|
}
|
|
|
|
$with: WithBuilder = (alias: string, selection?: ColumnsSelection) => {
|
|
const self = this
|
|
const as = (
|
|
qb:
|
|
| TypedQueryBuilder<ColumnsSelection | undefined>
|
|
| SQL
|
|
| ((qb: QueryBuilder) => TypedQueryBuilder<ColumnsSelection | undefined> | SQL),
|
|
) => {
|
|
if (typeof qb === "function") {
|
|
qb = qb(new QueryBuilder(self.dialect))
|
|
}
|
|
|
|
return new Proxy(
|
|
new WithSubquery(
|
|
qb.getSQL(),
|
|
selection ??
|
|
(("getSelectedFields" in qb
|
|
? ((qb as { getSelectedFields(): SelectedFields | undefined }).getSelectedFields() ?? {})
|
|
: {}) as SelectedFields),
|
|
alias,
|
|
true,
|
|
),
|
|
new SelectionProxyHandler({ alias, sqlAliasedBehavior: "alias", sqlBehavior: "error" }),
|
|
)
|
|
}
|
|
return { as }
|
|
}
|
|
|
|
$cache: { invalidate: EffectCacheShape["onMutate"] }
|
|
|
|
$count(source: SQLiteTable | SQLiteViewBase | SQL | SQLWrapper, filters?: SQL<unknown>) {
|
|
return new SQLiteEffectCountBuilder({ source, filters, session: this.session })
|
|
}
|
|
|
|
with(...queries: WithSubquery[]) {
|
|
const self = this
|
|
|
|
function select(): SQLiteEffectSelectBuilder<undefined, TRunResult, TEffectHKT>
|
|
function select<TSelection extends SelectedFields>(
|
|
fields: TSelection,
|
|
): SQLiteEffectSelectBuilder<TSelection, TRunResult, TEffectHKT>
|
|
function select(
|
|
fields?: SelectedFields,
|
|
): SQLiteEffectSelectBuilder<SelectedFields | undefined, TRunResult, TEffectHKT> {
|
|
return new SQLiteEffectSelectBuilder({
|
|
fields: fields ?? undefined,
|
|
session: self.session,
|
|
dialect: self.dialect,
|
|
withList: queries,
|
|
})
|
|
}
|
|
|
|
function selectDistinct(): SQLiteEffectSelectBuilder<undefined, TRunResult, TEffectHKT>
|
|
function selectDistinct<TSelection extends SelectedFields>(
|
|
fields: TSelection,
|
|
): SQLiteEffectSelectBuilder<TSelection, TRunResult, TEffectHKT>
|
|
function selectDistinct(
|
|
fields?: SelectedFields,
|
|
): SQLiteEffectSelectBuilder<SelectedFields | undefined, TRunResult, TEffectHKT> {
|
|
return new SQLiteEffectSelectBuilder({
|
|
fields: fields ?? undefined,
|
|
session: self.session,
|
|
dialect: self.dialect,
|
|
withList: queries,
|
|
distinct: true,
|
|
})
|
|
}
|
|
|
|
function update<TTable extends SQLiteTable>(
|
|
table: TTable,
|
|
): SQLiteEffectUpdateBuilder<TTable, TRunResult, TEffectHKT> {
|
|
return new SQLiteEffectUpdateBuilder(table, self.session, self.dialect, queries)
|
|
}
|
|
|
|
function insert<TTable extends SQLiteTable>(
|
|
into: TTable,
|
|
): SQLiteEffectInsertBuilder<TTable, TRunResult, TEffectHKT> {
|
|
return new SQLiteEffectInsertBuilder(into, self.session, self.dialect, queries)
|
|
}
|
|
|
|
function delete_<TTable extends SQLiteTable>(
|
|
from: TTable,
|
|
): SQLiteEffectDeleteBase<TTable, TRunResult, undefined, false, never, TEffectHKT> {
|
|
return new SQLiteEffectDeleteBase(from, self.session, self.dialect, queries)
|
|
}
|
|
|
|
return { select, selectDistinct, update, insert, delete: delete_ }
|
|
}
|
|
|
|
select(): SQLiteEffectSelectBuilder<undefined, TRunResult, TEffectHKT>
|
|
select<TSelection extends SelectedFields>(
|
|
fields: TSelection,
|
|
): SQLiteEffectSelectBuilder<TSelection, TRunResult, TEffectHKT>
|
|
select(fields?: SelectedFields): SQLiteEffectSelectBuilder<SelectedFields | undefined, TRunResult, TEffectHKT> {
|
|
return new SQLiteEffectSelectBuilder({ fields: fields ?? undefined, session: this.session, dialect: this.dialect })
|
|
}
|
|
|
|
selectDistinct(): SQLiteEffectSelectBuilder<undefined, TRunResult, TEffectHKT>
|
|
selectDistinct<TSelection extends SelectedFields>(
|
|
fields: TSelection,
|
|
): SQLiteEffectSelectBuilder<TSelection, TRunResult, TEffectHKT>
|
|
selectDistinct(
|
|
fields?: SelectedFields,
|
|
): SQLiteEffectSelectBuilder<SelectedFields | undefined, TRunResult, TEffectHKT> {
|
|
return new SQLiteEffectSelectBuilder({
|
|
fields: fields ?? undefined,
|
|
session: this.session,
|
|
dialect: this.dialect,
|
|
distinct: true,
|
|
})
|
|
}
|
|
|
|
update<TTable extends SQLiteTable>(table: TTable): SQLiteEffectUpdateBuilder<TTable, TRunResult, TEffectHKT> {
|
|
return new SQLiteEffectUpdateBuilder(table, this.session, this.dialect)
|
|
}
|
|
|
|
insert<TTable extends SQLiteTable>(into: TTable): SQLiteEffectInsertBuilder<TTable, TRunResult, TEffectHKT> {
|
|
return new SQLiteEffectInsertBuilder(into, this.session, this.dialect)
|
|
}
|
|
|
|
delete<TTable extends SQLiteTable>(
|
|
from: TTable,
|
|
): SQLiteEffectDeleteBase<TTable, TRunResult, undefined, false, never, TEffectHKT> {
|
|
return new SQLiteEffectDeleteBase(from, this.session, this.dialect)
|
|
}
|
|
|
|
private raw<TResult>(
|
|
query: SQLWrapper | string,
|
|
action: "all" | "get" | "run" | "values",
|
|
execute: (query: SQL) => Effect.Effect<TResult, TEffectHKT["error"], TEffectHKT["context"]>,
|
|
): SQLiteEffectRaw<TResult, TEffectHKT> {
|
|
const sequel = typeof query === "string" ? sql.raw(query) : query.getSQL()
|
|
return new SQLiteEffectRaw(
|
|
() => execute(sequel),
|
|
() => sequel,
|
|
action,
|
|
this.dialect,
|
|
(result) => result,
|
|
)
|
|
}
|
|
|
|
run(query: SQLWrapper | string): SQLiteEffectRaw<TRunResult, TEffectHKT> {
|
|
return this.raw(query, "run", (sequel) => this.session.run(sequel))
|
|
}
|
|
|
|
all<T = unknown>(query: SQLWrapper | string): SQLiteEffectRaw<T[], TEffectHKT> {
|
|
return this.raw(query, "all", (sequel) => this.session.all(sequel))
|
|
}
|
|
|
|
get<T = unknown>(query: SQLWrapper | string): SQLiteEffectRaw<T | undefined, TEffectHKT> {
|
|
return this.raw(query, "get", (sequel) => this.session.get(sequel))
|
|
}
|
|
|
|
values<T extends unknown[] = unknown[]>(query: SQLWrapper | string): SQLiteEffectRaw<T[], TEffectHKT> {
|
|
return this.raw(query, "values", (sequel) => this.session.values(sequel))
|
|
}
|
|
|
|
transaction: <A, E, R>(
|
|
transaction: (tx: SQLiteEffectTransaction<TEffectHKT, TRunResult, TRelations>) => Effect.Effect<A, E, R>,
|
|
config?: SQLiteTransactionConfig,
|
|
) => Effect.Effect<A, E | SqlError, R> = (tx, config) => this.session.transaction(tx, config)
|
|
}
|
|
|
|
export type SQLiteEffectWithReplicas<Q> = Q & { $primary: Q; $replicas: Q[] }
|
|
|
|
export const withReplicas = <
|
|
TEffectHKT extends QueryEffectHKTBase,
|
|
TRunResult,
|
|
TRelations extends AnyRelations,
|
|
Q extends SQLiteEffectDatabase<TEffectHKT, TRunResult, TRelations>,
|
|
>(
|
|
primary: Q,
|
|
replicas: [Q, ...Q[]],
|
|
getReplica: (replicas: Q[]) => Q = () => replicas[Math.floor(Math.random() * replicas.length)]!,
|
|
): SQLiteEffectWithReplicas<Q> => {
|
|
const select: Q["select"] = (...args: []) => getReplica(replicas).select(...args)
|
|
const selectDistinct: Q["selectDistinct"] = (...args: []) => getReplica(replicas).selectDistinct(...args)
|
|
const $count: Q["$count"] = (...args: [any]) => getReplica(replicas).$count(...args)
|
|
const _with: Q["with"] = (...args: []) => getReplica(replicas).with(...args)
|
|
const $with = ((...args: [string] | [string, ColumnsSelection]) =>
|
|
args.length === 1
|
|
? getReplica(replicas).$with(args[0])
|
|
: getReplica(replicas).$with(args[0], args[1])) as Q["$with"]
|
|
|
|
const update: Q["update"] = (...args: [any]) => primary.update(...args)
|
|
const insert: Q["insert"] = (...args: [any]) => primary.insert(...args)
|
|
const $delete: Q["delete"] = (...args: [any]) => primary.delete(...args)
|
|
const run: Q["run"] = (...args: [any]) => primary.run(...args)
|
|
const all: Q["all"] = (...args: [any]) => primary.all(...args)
|
|
const get: Q["get"] = (...args: [any]) => primary.get(...args)
|
|
const values: Q["values"] = (...args: [any]) => primary.values(...args)
|
|
const transaction: Q["transaction"] = (...args: [any]) => primary.transaction(...args)
|
|
|
|
return {
|
|
...primary,
|
|
update,
|
|
insert,
|
|
delete: $delete,
|
|
run,
|
|
all,
|
|
get,
|
|
values,
|
|
transaction,
|
|
$primary: primary,
|
|
$replicas: replicas,
|
|
select,
|
|
selectDistinct,
|
|
$count,
|
|
$with,
|
|
with: _with,
|
|
get query() {
|
|
return getReplica(replicas).query
|
|
},
|
|
}
|
|
}
|
|
|
|
export type AnySQLiteEffectDatabase = SQLiteEffectDatabase<any, any, any>
|
|
export type AnySQLiteEffectSelectBase = SQLiteEffectSelectBase<any, any, any, any, any, any, any, any, any, any>
|