import type { AnySchemas, AnyRelations } from "../orm/index.ts" import { PgliteDatabase as RawDatabase, PgliteTransaction as RawTransaction } from "./pglite.ts" export type PgliteNormalDatabase< Schemas extends AnySchemas, Relations extends AnyRelations, > = RawDatabase export type PgliteTransactionDatabase< Schemas extends AnySchemas, Relations extends AnyRelations, // oxlint-disable-next-line typescript/no-explicit-any > = RawTransaction export type PgliteUnionDatabase = | PgliteNormalDatabase | PgliteTransactionDatabase export interface WithPgliteUnionDatabase< Schemas extends AnySchemas, Relations extends AnyRelations, > { database: PgliteUnionDatabase } export interface WithOptionalPgliteUnionDatabase< Schemas extends AnySchemas, Relations extends AnyRelations, > { database?: PgliteUnionDatabase | undefined } export type WithoutPgliteUnionDatabase = Omit export const isPgliteNormalDatabase = ( database: unknown, ): database is PgliteNormalDatabase => { return database instanceof RawDatabase } export type GetIsPgliteNormalDatabase< Schemas extends AnySchemas, Relations extends AnyRelations, > = (database: unknown) => database is PgliteNormalDatabase export const getIsPgliteNormalDatabase = < Schemas extends AnySchemas, Relations extends AnyRelations, >(): GetIsPgliteNormalDatabase => { return isPgliteNormalDatabase } export const isPgliteTransactionDatabase = < Schemas extends AnySchemas, Relations extends AnyRelations, >( database: unknown, ): database is PgliteTransactionDatabase => { return database instanceof RawTransaction } export type GetIsPgliteTransactionDatabase< Schemas extends AnySchemas, Relations extends AnyRelations, > = (database: unknown) => database is PgliteTransactionDatabase export const getIsPgliteTransactionDatabase = < Schemas extends AnySchemas, Relations extends AnyRelations, >(): GetIsPgliteTransactionDatabase => { return isPgliteTransactionDatabase } export const isPgliteUnionDatabase = ( database: unknown, ): database is PgliteUnionDatabase => { if (isPgliteTransactionDatabase(database) === true) { return true } if (isPgliteNormalDatabase(database) === true) { return true } return false } export type GetIsPgliteUnionDatabase = ( database: unknown, ) => database is PgliteUnionDatabase export const getIsPgliteUnionDatabase = < Schemas extends AnySchemas, Relations extends AnyRelations, >(): GetIsPgliteUnionDatabase => { return isPgliteUnionDatabase } export type AutoPgliteDatabaseTransaction = < Result, Schemas extends AnySchemas, Relations extends AnyRelations, >( database: PgliteUnionDatabase, run: (database: PgliteTransactionDatabase) => Promise, ) => Promise export const autoPgliteDatabaseTransaction = async < Result, Schemas extends AnySchemas, Relations extends AnyRelations, >( database: PgliteUnionDatabase, run: (database: PgliteTransactionDatabase) => Promise, ): Promise => { // detect transaction database first, then normal database // because transaction database is a subclass of normal database if (isPgliteTransactionDatabase(database)) { return await run(database) } if (isPgliteNormalDatabase(database)) { return await database.transaction(async (database) => { return await run(database) }) } throw new Error("Invalid database instance") } export type GetAutoPgliteDatabaseTransaction< Schemas extends AnySchemas, Relations extends AnyRelations, > = ( database: PgliteUnionDatabase, run: (database: PgliteTransactionDatabase) => Promise, ) => Promise export const getAutoPgliteDatabaseTransaction = < Schemas extends AnySchemas, Relations extends AnyRelations, >() => { return async ( database: PgliteUnionDatabase, run: (database: PgliteTransactionDatabase) => Promise, ): Promise => { return await autoPgliteDatabaseTransaction(database, run) } }