2025-08-04 17:45:44 +02:00
|
|
|
import {
|
2025-08-28 18:27:07 +02:00
|
|
|
DeduplicateJoinsPlugin,
|
|
|
|
|
HandleEmptyInListsPlugin,
|
|
|
|
|
Kysely,
|
|
|
|
|
type LogEvent,
|
|
|
|
|
PostgresDialect,
|
|
|
|
|
replaceWithNoncontingentExpression,
|
|
|
|
|
type Transaction,
|
2025-08-04 17:45:44 +02:00
|
|
|
} from "kysely";
|
2025-08-28 18:27:07 +02:00
|
|
|
import { Pool } from "pg";
|
2025-10-20 16:22:20 +02:00
|
|
|
import { env } from "~/env";
|
2025-08-04 17:45:44 +02:00
|
|
|
import type Database from "~/schemas/Database";
|
|
|
|
|
import type PublicSchema from "~/schemas/public/PublicSchema";
|
2025-08-28 18:27:07 +02:00
|
|
|
|
2025-08-04 17:45:44 +02:00
|
|
|
/**
|
|
|
|
|
* The database connection pool.
|
|
|
|
|
*/
|
|
|
|
|
const pool = new Pool({
|
2025-09-02 20:17:14 +02:00
|
|
|
//connectionTimeoutMillis: 2000,
|
2025-08-28 18:27:07 +02:00
|
|
|
database: env.POSTGRES_DB,
|
2025-08-29 16:18:32 +02:00
|
|
|
host: env.PGHOST,
|
2025-09-02 20:17:14 +02:00
|
|
|
//idleTimeoutMillis: 30000,
|
2025-08-29 16:18:32 +02:00
|
|
|
max: 10,
|
2025-08-28 18:27:07 +02:00
|
|
|
password: env.POSTGRES_PASSWORD,
|
|
|
|
|
port: Number.parseInt(env.PGPORT),
|
2025-08-29 16:18:32 +02:00
|
|
|
user: env.POSTGRES_USER,
|
2025-08-04 17:45:44 +02:00
|
|
|
});
|
|
|
|
|
|
2026-03-23 12:01:18 +01:00
|
|
|
pool.on("error", (err) => {
|
|
|
|
|
const pgErr = err as { code?: string };
|
|
|
|
|
// "admin_shutdown" error sent during backups
|
|
|
|
|
const isAdminShutdown = pgErr.code === "57P01";
|
|
|
|
|
|
2026-04-09 11:15:52 +02:00
|
|
|
if (isAdminShutdown) return;
|
2026-03-23 12:01:18 +01:00
|
|
|
|
|
|
|
|
console.error("PG error:", err);
|
|
|
|
|
});
|
|
|
|
|
|
2025-08-04 17:45:44 +02:00
|
|
|
type Db = typeof db;
|
|
|
|
|
|
|
|
|
|
type Trx = Transaction<PublicSchema>;
|
|
|
|
|
|
|
|
|
|
export type Querier = Db | Trx;
|
|
|
|
|
/**
|
|
|
|
|
* The database instance.
|
|
|
|
|
*/
|
|
|
|
|
export const db = new Kysely<Database>({
|
2025-08-28 18:27:07 +02:00
|
|
|
dialect: new PostgresDialect({
|
|
|
|
|
pool: pool,
|
|
|
|
|
}),
|
|
|
|
|
|
2025-09-05 15:22:48 +02:00
|
|
|
log: (_event) => {
|
|
|
|
|
//DbLogger(event);
|
2025-08-28 18:27:07 +02:00
|
|
|
},
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
//plugins: [new SerializePlugin()]
|
|
|
|
|
//plugins: [new CamelCasePlugin()],
|
|
|
|
|
plugins: [
|
|
|
|
|
new DeduplicateJoinsPlugin(),
|
|
|
|
|
new HandleEmptyInListsPlugin({
|
|
|
|
|
strategy: replaceWithNoncontingentExpression,
|
|
|
|
|
}),
|
2026-02-25 15:30:53 +01:00
|
|
|
//new ParseJSONResultsPlugin(),
|
2025-08-28 18:27:07 +02:00
|
|
|
],
|
2025-08-04 17:45:44 +02:00
|
|
|
});
|
|
|
|
|
|
2025-09-05 15:22:48 +02:00
|
|
|
const _DbLogger = (event: LogEvent) => {
|
2025-09-04 11:32:17 +02:00
|
|
|
if (
|
|
|
|
|
event.level === "query" &&
|
|
|
|
|
event.query.sql !== "begin" &&
|
|
|
|
|
event.query.sql !== "commit"
|
|
|
|
|
) {
|
|
|
|
|
console.log();
|
2025-08-28 18:27:07 +02:00
|
|
|
console.log("\x1b[33mquery:\x1b[0m", event.query.sql);
|
|
|
|
|
console.log("\x1b[36mparams:\x1b[0m", event.query.parameters);
|
2025-09-04 11:32:17 +02:00
|
|
|
//console.log("\x1b[32mtaken:\x1b[0m", event.queryDurationMillis, "ms");
|
2025-08-28 18:27:07 +02:00
|
|
|
}
|
|
|
|
|
if (event.level === "error") {
|
2025-09-04 11:32:17 +02:00
|
|
|
console.error();
|
2025-08-28 18:27:07 +02:00
|
|
|
console.error("\x1b[33mquery:\x1b[0m", event.query.sql);
|
|
|
|
|
console.error("\x1b[36mparams:\x1b[0m", event.query.parameters);
|
2025-09-04 11:32:17 +02:00
|
|
|
//console.error("\x1b[31merror:\x1b[0m", event.error);
|
2025-08-28 18:27:07 +02:00
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|