fix: wrong month stats and db cache undefined handling
This commit is contained in:
parent
ee5d986972
commit
ec1ea5cfe8
4 changed files with 54 additions and 67 deletions
110
src/db.ts
110
src/db.ts
|
@ -1,6 +1,6 @@
|
||||||
import { type Accessor, createEffect, createMemo, createRoot, createSignal, DEV, type Setter } from "solid-js";
|
import { createEffect, createMemo, createRoot, createSignal } from "solid-js";
|
||||||
|
|
||||||
import { Kysely, type NotNull, sql } from "kysely";
|
import { Kysely, sql, type NotNull } from "kysely";
|
||||||
import type { DB } from "kysely-codegen";
|
import type { DB } from "kysely-codegen";
|
||||||
import { SqlJsDialect } from "kysely-wasm";
|
import { SqlJsDialect } from "kysely-wasm";
|
||||||
import initSqlJS, { type Database } from "sql.js";
|
import initSqlJS, { type Database } from "sql.js";
|
||||||
|
@ -14,25 +14,10 @@ export const SQL = await initSqlJS({
|
||||||
locateFile: () => wasmURL,
|
locateFile: () => wasmURL,
|
||||||
});
|
});
|
||||||
|
|
||||||
let rawDb: Accessor<Database | undefined> = () => undefined,
|
export const [db, setDb] = createSignal<Database | undefined>();
|
||||||
setRawDb: Setter<Database | undefined> = () => undefined;
|
|
||||||
|
|
||||||
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 | undefined>(testDb);
|
|
||||||
} else {
|
|
||||||
[rawDb, setRawDb] = createSignal<Database | undefined>();
|
|
||||||
}
|
|
||||||
|
|
||||||
export { rawDb as db, setRawDb as setDb };
|
|
||||||
|
|
||||||
const sqlJsDialect = () => {
|
const sqlJsDialect = () => {
|
||||||
const currentDb = rawDb();
|
const currentDb = db();
|
||||||
|
|
||||||
if (currentDb) {
|
if (currentDb) {
|
||||||
return new SqlJsDialect({
|
return new SqlJsDialect({
|
||||||
|
@ -43,10 +28,10 @@ const sqlJsDialect = () => {
|
||||||
|
|
||||||
const kyselyDb = createRoot(() => {
|
const kyselyDb = createRoot(() => {
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
const db = rawDb();
|
const currentDb = db();
|
||||||
|
|
||||||
if (db) {
|
if (currentDb) {
|
||||||
db.create_function("is_not_empty", (str: string | null) => {
|
currentDb.create_function("is_not_empty", (str: string | null) => {
|
||||||
return str !== null && str !== "";
|
return str !== null && str !== "";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -56,7 +41,7 @@ const kyselyDb = createRoot(() => {
|
||||||
const currentSqlJsDialect = sqlJsDialect();
|
const currentSqlJsDialect = sqlJsDialect();
|
||||||
|
|
||||||
if (!currentSqlJsDialect) {
|
if (!currentSqlJsDialect) {
|
||||||
throw new Error("no db selected!");
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Kysely<DB>({
|
return new Kysely<DB>({
|
||||||
|
@ -65,46 +50,47 @@ const kyselyDb = createRoot(() => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const allThreadsOverviewQueryRaw = kyselyDb()
|
const allThreadsOverviewQueryRaw = () =>
|
||||||
.selectFrom("thread")
|
kyselyDb()
|
||||||
.innerJoin(
|
?.selectFrom("thread")
|
||||||
(eb) =>
|
.innerJoin(
|
||||||
eb
|
(eb) =>
|
||||||
.selectFrom("message")
|
eb
|
||||||
.select((eb) => ["message.thread_id", eb.fn.countAll().as("message_count")])
|
.selectFrom("message")
|
||||||
.where((eb) => {
|
.select((eb) => ["message.thread_id", eb.fn.countAll().as("message_count")])
|
||||||
return eb.and([eb("message.body", "is not", null), eb("message.body", "is not", "")]);
|
.where((eb) => {
|
||||||
})
|
return eb.and([eb("message.body", "is not", null), eb("message.body", "is not", "")]);
|
||||||
.groupBy("message.thread_id")
|
})
|
||||||
.as("message"),
|
.groupBy("message.thread_id")
|
||||||
(join) => join.onRef("message.thread_id", "=", "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")
|
.innerJoin("recipient", "thread.recipient_id", "recipient._id")
|
||||||
.select([
|
.leftJoin("groups", "recipient._id", "groups.recipient_id")
|
||||||
"thread._id as thread_id",
|
.select([
|
||||||
"thread.recipient_id",
|
"thread._id as thread_id",
|
||||||
"thread.archived",
|
"thread.recipient_id",
|
||||||
"recipient.profile_joined_name",
|
"thread.archived",
|
||||||
"recipient.system_joined_name",
|
"recipient.profile_joined_name",
|
||||||
"groups.title",
|
"recipient.system_joined_name",
|
||||||
"message_count",
|
"groups.title",
|
||||||
"thread.date as last_message_date",
|
"message_count",
|
||||||
"recipient.nickname_joined_name",
|
"thread.date as last_message_date",
|
||||||
])
|
"recipient.nickname_joined_name",
|
||||||
.where("message_count", ">", 0)
|
])
|
||||||
.$narrowType<{
|
.where("message_count", ">", 0)
|
||||||
thread_id: NotNull;
|
.$narrowType<{
|
||||||
archived: NotNull;
|
thread_id: NotNull;
|
||||||
message_count: number;
|
archived: NotNull;
|
||||||
}>()
|
message_count: number;
|
||||||
.compile();
|
}>()
|
||||||
|
.execute();
|
||||||
|
|
||||||
export const allThreadsOverviewQuery = cached(() => kyselyDb().executeQuery(allThreadsOverviewQueryRaw));
|
export const allThreadsOverviewQuery = cached(allThreadsOverviewQueryRaw);
|
||||||
|
|
||||||
const overallSentMessagesQueryRaw = (recipientId: number) =>
|
const overallSentMessagesQueryRaw = (recipientId: number) =>
|
||||||
kyselyDb()
|
kyselyDb()
|
||||||
.selectFrom("message")
|
?.selectFrom("message")
|
||||||
.select((eb) => eb.fn.countAll().as("messageCount"))
|
.select((eb) => eb.fn.countAll().as("messageCount"))
|
||||||
.where((eb) =>
|
.where((eb) =>
|
||||||
eb.and([
|
eb.and([
|
||||||
|
@ -119,7 +105,7 @@ export const overallSentMessagesQuery = cached(overallSentMessagesQueryRaw);
|
||||||
|
|
||||||
const dmPartnerRecipientQueryRaw = (dmId: number) =>
|
const dmPartnerRecipientQueryRaw = (dmId: number) =>
|
||||||
kyselyDb()
|
kyselyDb()
|
||||||
.selectFrom("recipient")
|
?.selectFrom("recipient")
|
||||||
.select([
|
.select([
|
||||||
"recipient._id",
|
"recipient._id",
|
||||||
"recipient.system_joined_name",
|
"recipient.system_joined_name",
|
||||||
|
@ -137,7 +123,7 @@ export const dmPartnerRecipientQuery = cached(dmPartnerRecipientQueryRaw);
|
||||||
|
|
||||||
const threadSentMessagesOverviewQueryRaw = (threadId: number) =>
|
const threadSentMessagesOverviewQueryRaw = (threadId: number) =>
|
||||||
kyselyDb()
|
kyselyDb()
|
||||||
.selectFrom("message")
|
?.selectFrom("message")
|
||||||
.select(["from_recipient_id", sql<string>`datetime(date_sent / 1000, 'unixepoch')`.as("message_datetime")])
|
.select(["from_recipient_id", sql<string>`datetime(date_sent / 1000, 'unixepoch')`.as("message_datetime")])
|
||||||
.orderBy(["message_datetime"])
|
.orderBy(["message_datetime"])
|
||||||
.where((eb) => eb.and([eb("body", "is not", null), eb("body", "!=", ""), eb("thread_id", "=", threadId)]))
|
.where((eb) => eb.and([eb("body", "is not", null), eb("body", "!=", ""), eb("thread_id", "=", threadId)]))
|
||||||
|
@ -147,7 +133,7 @@ export const threadSentMessagesOverviewQuery = cached(threadSentMessagesOverview
|
||||||
|
|
||||||
const threadMostUsedWordsQueryRaw = (threadId: number, limit = 10) =>
|
const threadMostUsedWordsQueryRaw = (threadId: number, limit = 10) =>
|
||||||
kyselyDb()
|
kyselyDb()
|
||||||
.withRecursive("words", (eb) => {
|
?.withRecursive("words", (eb) => {
|
||||||
return eb
|
return eb
|
||||||
.selectFrom("message")
|
.selectFrom("message")
|
||||||
.select([
|
.select([
|
||||||
|
|
|
@ -142,7 +142,9 @@ export const cached = <T extends unknown[], R, TT>(fn: (...args: T) => R, self?:
|
||||||
isPromise = promisified == newValue;
|
isPromise = promisified == newValue;
|
||||||
|
|
||||||
void promisified.then((result) => {
|
void promisified.then((result) => {
|
||||||
cache.set(cacheName, cacheKey, result);
|
if (result !== undefined) {
|
||||||
|
cache.set(cacheName, cacheKey, result);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return newValue;
|
return newValue;
|
||||||
|
|
|
@ -57,8 +57,7 @@ export const createMessageStatsSources = (
|
||||||
person[message.fromRecipientId] += 1;
|
person[message.fromRecipientId] += 1;
|
||||||
|
|
||||||
// increment the message count of the message's month for this recipient
|
// increment the message count of the message's month for this recipient
|
||||||
// months are an array from 0 - 11
|
month[messageDate.getMonth()][message.fromRecipientId] += 1;
|
||||||
month[messageDate.getMonth() - 1][message.fromRecipientId] += 1;
|
|
||||||
|
|
||||||
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
||||||
const dateStatsEntry = date.find(({ date }) => isSameDay(date, messageDate))!;
|
const dateStatsEntry = date.find(({ date }) => isSameDay(date, messageDate))!;
|
||||||
|
|
|
@ -10,8 +10,8 @@ import { Title } from "@solidjs/meta";
|
||||||
export const Overview: Component<RouteSectionProps> = () => {
|
export const Overview: Component<RouteSectionProps> = () => {
|
||||||
const [allSelfSentMessagesCount] = createResource(() => overallSentMessagesQuery(SELF_ID));
|
const [allSelfSentMessagesCount] = createResource(() => overallSentMessagesQuery(SELF_ID));
|
||||||
|
|
||||||
const [roomOverview] = createResource<RoomOverview[]>(async () => {
|
const [roomOverview] = createResource<RoomOverview[] | undefined>(async () => {
|
||||||
return (await allThreadsOverviewQuery()).rows.map((row) => {
|
return (await allThreadsOverviewQuery())?.map((row) => {
|
||||||
const isGroup = row.title !== null;
|
const isGroup = row.title !== null;
|
||||||
|
|
||||||
let name = "";
|
let name = "";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue