sendou.ink/app/db/sql.ts
Kalle 700a309e7f
Migrate Node -> Bun (#1827)
* Initial

* Faster user page

* Remove redundant function

* Favorite badge sorting

* Upgrade deps

* Simplify entry.server

* Bun tests initial

* Update package.json npm -> bun

* Update README

* Type safe translations again

* Don't load streams info for finalized tournaments

* Translations as an object

* More unit test work

* Convert match.server.test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* Test & all done

* Working cf

* Bun GA try

* No cache

* spacing

* spacing 2

* Add SQL logging

* Remove NR

* Hmm

* Hmm 2

* Interesting

* SKALOP_SYSTEM_MESSAGE_URL

* .

* .

* ?

* .

* ?

* Server.ts adjust

* Downgrade Tldraw

* E2E test fix

* Fix lint
2024-08-11 16:09:41 +03:00

88 lines
2.4 KiB
TypeScript

import { Database } from "bun:sqlite";
import { styleText } from "node:util";
import { Kysely, type LogEvent, ParseJSONResultsPlugin } from "kysely";
import { BunSqliteDialect } from "kysely-bun-sqlite";
import { format } from "sql-formatter";
import invariant from "~/utils/invariant";
import { roundToNDecimalPlaces } from "~/utils/number";
import type { DB } from "./tables";
const LOG_LEVEL = (["trunc", "full", "none"] as const).find(
(val) => val === process.env.SQL_LOG,
);
invariant(process.env.DB_PATH, "DB_PATH env variable must be set");
export const sql = new Database(process.env.DB_PATH, {
strict: true,
});
sql.exec("PRAGMA journal_mode = WAL;");
sql.exec("PRAGMA foreign_keys = ON;");
sql.exec("PRAGMA busy_timeout = 5000;");
export const db = new Kysely<DB>({
dialect: new BunSqliteDialect({
database: sql,
}),
log: LOG_LEVEL === "trunc" || LOG_LEVEL === "full" ? logQuery : undefined,
plugins: [new ParseJSONResultsPlugin()],
});
function logQuery(event: LogEvent) {
const isSelectQuery = Boolean((event.query.query as any).from?.froms);
if (event.level === "query" && isSelectQuery) {
const from = () =>
(event.query.query as any).from.froms.map(
(f: any) => f.table.identifier.name,
);
// biome-ignore lint/suspicious/noConsoleLog: dev only
console.log(styleText("blue", `-- SQLITE QUERY to "${from()}" --`));
// biome-ignore lint/suspicious/noConsoleLog: dev only
console.log(
styleText(
millisToColor(event.queryDurationMillis),
`${roundToNDecimalPlaces(event.queryDurationMillis, 1)}ms`,
),
);
// biome-ignore lint/suspicious/noConsoleLog: dev only
console.log(formatSql(event.query.sql, event.query.parameters));
}
}
function millisToColor(millis: number) {
if (millis < 1) {
return "bgGreen";
}
if (millis < 5) {
return "green";
}
if (millis < 50) {
return "yellow";
}
return "red";
}
function formatSql(sql: string, params: readonly unknown[]) {
const formatted = format(sql);
const lines = formatted.split("\n");
if (LOG_LEVEL === "full" || lines.length <= 11) {
return addParams(formatted, params);
}
const linesNotShown = lines.length - 10;
return `${lines.slice(0, 10).join("\n")}\n... (${linesNotShown} more lines) ...\n`;
}
function addParams(sql: string, params: readonly unknown[]) {
const coloredParams = params.map((param) =>
styleText("yellow", JSON.stringify(param)),
);
return sql.replace(/\?/g, () => coloredParams.shift() || "");
}