feat: typed database with kysely, updated config
This commit is contained in:
parent
d06e6d913e
commit
0e6f5a24bd
24 changed files with 1656 additions and 434 deletions
156
src/db.ts
156
src/db.ts
|
@ -1,8 +1,11 @@
|
|||
import { type Accessor, createMemo, createSignal, DEV, type Setter } from "solid-js";
|
||||
|
||||
import { Kysely, type NotNull } from "kysely";
|
||||
import type { DB } from "kysely-codegen";
|
||||
import { SqlJsDialect } from "kysely-wasm";
|
||||
import initSqlJS, { type Database } from "sql.js";
|
||||
|
||||
import wasmURL from "./assets/sql-wasm.wasm?url";
|
||||
import dbURL from "./assets/database.sqlite?url";
|
||||
import { createMemo, createSignal } from "solid-js";
|
||||
|
||||
export const SELF_ID = 2;
|
||||
|
||||
|
@ -10,80 +13,87 @@ export const SQL = await initSqlJS({
|
|||
locateFile: () => wasmURL,
|
||||
});
|
||||
|
||||
const file = await fetch(dbURL).then((res) => res.arrayBuffer());
|
||||
let rawDb: Accessor<Database | undefined>, setRawDb: Setter<Database | undefined>;
|
||||
|
||||
const testDb = new SQL.Database(new Uint8Array(file));
|
||||
|
||||
export const [db, setDb] = createSignal<Database>(testDb);
|
||||
|
||||
const createStatement = (sql: string) => {
|
||||
return createMemo(() => {
|
||||
return db().prepare(sql);
|
||||
if (DEV) {
|
||||
const file = await import("./assets/database.sqlite?url").then((result) => {
|
||||
return fetch(result.default).then((res) => res.arrayBuffer());
|
||||
});
|
||||
|
||||
const testDb = new SQL.Database(new Uint8Array(file));
|
||||
|
||||
[rawDb, setRawDb] = createSignal<Database>(testDb);
|
||||
} else {
|
||||
[rawDb, setRawDb] = createSignal<Database>();
|
||||
}
|
||||
|
||||
export { rawDb as db, setRawDb as setDb };
|
||||
|
||||
const sqlJsDialect = () => {
|
||||
const currentDb = rawDb();
|
||||
|
||||
if (currentDb) {
|
||||
return new SqlJsDialect({
|
||||
database: currentDb,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const roomOverviewStmt = createStatement(`
|
||||
SELECT
|
||||
thread.recipient_id,
|
||||
thread.active,
|
||||
thread.archived,
|
||||
recipient.profile_joined_name,
|
||||
recipient.system_joined_name,
|
||||
groups.title,
|
||||
message_count,
|
||||
last_message_date
|
||||
FROM
|
||||
thread
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
thread_id,
|
||||
COUNT(*) AS message_count
|
||||
FROM
|
||||
message
|
||||
WHERE
|
||||
message.body IS NOT NULL
|
||||
AND message.body != ''
|
||||
GROUP BY
|
||||
thread_id
|
||||
) message_counts ON message_counts.thread_id = thread._id
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
thread_id,
|
||||
max(date_sent) AS last_message_date
|
||||
FROM
|
||||
message
|
||||
GROUP BY
|
||||
thread_id
|
||||
) last_messages ON last_messages.thread_id = thread._id
|
||||
JOIN recipient ON thread.recipient_id = recipient._id
|
||||
LEFT JOIN groups ON recipient._id = groups.recipient_id
|
||||
WHERE
|
||||
message_count > 0
|
||||
`);
|
||||
const kyselyDb = createMemo(() => {
|
||||
const currentSqlJsDialect = sqlJsDialect();
|
||||
|
||||
export type RoomOverviewColumn = {
|
||||
recipient_id: number;
|
||||
active: 0 | 1;
|
||||
archived: 0 | 1;
|
||||
message_count: number;
|
||||
last_message_date: number;
|
||||
} & (
|
||||
| {
|
||||
profile_joined_name: string;
|
||||
system_joined_name: string | null;
|
||||
title: null;
|
||||
}
|
||||
| {
|
||||
profile_joined_name: null;
|
||||
system_joined_name: null;
|
||||
title: string;
|
||||
}
|
||||
);
|
||||
if (!currentSqlJsDialect) {
|
||||
throw new Error("no db selected!");
|
||||
}
|
||||
|
||||
export const overallSentMessagesStmt = createStatement(`
|
||||
SELECT
|
||||
COUNT(*) as message_count
|
||||
FROM
|
||||
message
|
||||
WHERE (message.from_recipient_id = :recipient_id AND message.body IS NOT NULL AND message.body != '')
|
||||
`);
|
||||
return new Kysely<DB>({
|
||||
dialect: currentSqlJsDialect,
|
||||
});
|
||||
});
|
||||
|
||||
export const threadOverviewQuery = kyselyDb()
|
||||
.selectFrom("thread")
|
||||
.innerJoin(
|
||||
(eb) =>
|
||||
eb
|
||||
.selectFrom("message")
|
||||
.select(["thread_id", kyselyDb().fn.countAll().as("message_count")])
|
||||
.where((eb) => {
|
||||
return eb.and([eb("message.body", "is not", null), eb("message.body", "is not", "")]);
|
||||
})
|
||||
.groupBy("message.thread_id")
|
||||
.as("message"),
|
||||
(join) => join.onRef("message.thread_id", "=", "thread._id"),
|
||||
)
|
||||
.innerJoin("recipient", "thread.recipient_id", "recipient._id")
|
||||
.leftJoin("groups", "recipient._id", "groups.recipient_id")
|
||||
.select([
|
||||
"thread._id as thread_id",
|
||||
"thread.recipient_id",
|
||||
"thread.archived",
|
||||
"recipient.profile_joined_name",
|
||||
"recipient.system_joined_name",
|
||||
"groups.title",
|
||||
"message_count",
|
||||
"thread.date as last_message_date",
|
||||
])
|
||||
.where("message_count", ">", 0)
|
||||
.$narrowType<{
|
||||
thread_id: NotNull;
|
||||
archived: NotNull;
|
||||
message_count: number;
|
||||
}>();
|
||||
|
||||
console.log(threadOverviewQuery.compile());
|
||||
|
||||
export const overallSentMessagesQuery = (recipientId: number) =>
|
||||
kyselyDb()
|
||||
.selectFrom("message")
|
||||
.select(kyselyDb().fn.countAll().as("message_count"))
|
||||
.where((eb) =>
|
||||
eb.and([
|
||||
eb("message.from_recipient_id", "=", recipientId),
|
||||
eb("message.body", "is not", null),
|
||||
eb("message.body", "!=", ""),
|
||||
]),
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue