mirror of
https://github.com/versia-pub/server.git
synced 2026-03-13 05:49:16 +01:00
refactor(database): ♻️ Move Notifications to their own ORM abstractions
This commit is contained in:
parent
14ace17ad4
commit
e732a3df03
16 changed files with 440 additions and 401 deletions
|
|
@ -1,8 +1,7 @@
|
|||
import { apiRoute, applyConfig, auth } from "@/api";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { db } from "@versia/kit/db";
|
||||
import { Notifications, RolePermissions } from "@versia/kit/tables";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { Notification } from "@versia/kit/db";
|
||||
import { RolePermissions } from "@versia/kit/tables";
|
||||
import { z } from "zod";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
||||
|
|
@ -59,12 +58,15 @@ export default apiRoute((app) =>
|
|||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
await db
|
||||
.update(Notifications)
|
||||
.set({
|
||||
dismissed: true,
|
||||
})
|
||||
.where(eq(Notifications.id, id));
|
||||
const notification = await Notification.fromId(id);
|
||||
|
||||
if (!notification) {
|
||||
return context.json({ error: "Notification not found" }, 404);
|
||||
}
|
||||
|
||||
await notification.update({
|
||||
dismissed: true,
|
||||
});
|
||||
|
||||
return context.newResponse(null, 200);
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -1,13 +1,8 @@
|
|||
import { apiRoute, applyConfig, auth } from "@/api";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { Note, User } from "@versia/kit/db";
|
||||
import { Note, Notification, User } from "@versia/kit/db";
|
||||
import { RolePermissions } from "@versia/kit/tables";
|
||||
import type { SQL } from "drizzle-orm";
|
||||
import { z } from "zod";
|
||||
import {
|
||||
findManyNotifications,
|
||||
notificationToApi,
|
||||
} from "~/classes/functions/notification";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
||||
export const meta = applyConfig({
|
||||
|
|
@ -101,21 +96,12 @@ export default apiRoute((app) =>
|
|||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const notification = (
|
||||
await findManyNotifications(
|
||||
{
|
||||
where: (notification, { eq }): SQL | undefined =>
|
||||
eq(notification.id, id),
|
||||
limit: 1,
|
||||
},
|
||||
user.id,
|
||||
)
|
||||
)[0];
|
||||
const notification = await Notification.fromId(id, user.id);
|
||||
|
||||
if (!notification) {
|
||||
return context.json({ error: "Notification not found" }, 404);
|
||||
}
|
||||
|
||||
return context.json(await notificationToApi(notification), 200);
|
||||
return context.json(await notification.toApi(), 200);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { apiRoute, applyConfig, auth } from "@/api";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { db } from "@versia/kit/db";
|
||||
import { Notifications, RolePermissions } from "@versia/kit/tables";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { RolePermissions } from "@versia/kit/tables";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
||||
export const meta = applyConfig({
|
||||
|
|
@ -47,12 +45,7 @@ export default apiRoute((app) =>
|
|||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
await db
|
||||
.update(Notifications)
|
||||
.set({
|
||||
dismissed: true,
|
||||
})
|
||||
.where(eq(Notifications.notifiedId, user.id));
|
||||
await user.clearAllNotifications();
|
||||
|
||||
return context.newResponse(null, 200);
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { apiRoute, applyConfig, auth } from "@/api";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { db } from "@versia/kit/db";
|
||||
import { Notifications, RolePermissions } from "@versia/kit/tables";
|
||||
import { and, eq, inArray } from "drizzle-orm";
|
||||
import { RolePermissions } from "@versia/kit/tables";
|
||||
import { z } from "zod";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
||||
|
|
@ -60,17 +58,7 @@ export default apiRoute((app) =>
|
|||
|
||||
const { "ids[]": ids } = context.req.valid("query");
|
||||
|
||||
await db
|
||||
.update(Notifications)
|
||||
.set({
|
||||
dismissed: true,
|
||||
})
|
||||
.where(
|
||||
and(
|
||||
inArray(Notifications.id, ids),
|
||||
eq(Notifications.notifiedId, user.id),
|
||||
),
|
||||
);
|
||||
await user.clearSomeNotifications(ids);
|
||||
|
||||
return context.newResponse(null, 200);
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -1,15 +1,9 @@
|
|||
import { apiRoute, applyConfig, auth, idValidator } from "@/api";
|
||||
import { fetchTimeline } from "@/timelines";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { Note, User } from "@versia/kit/db";
|
||||
import { RolePermissions } from "@versia/kit/tables";
|
||||
import { type SQL, sql } from "drizzle-orm";
|
||||
import { Note, Timeline, User } from "@versia/kit/db";
|
||||
import { Notifications, RolePermissions } from "@versia/kit/tables";
|
||||
import { and, eq, gt, gte, inArray, lt, not, sql } from "drizzle-orm";
|
||||
import { z } from "zod";
|
||||
import {
|
||||
findManyNotifications,
|
||||
notificationToApi,
|
||||
} from "~/classes/functions/notification";
|
||||
import type { NotificationWithRelations } from "~/classes/functions/notification";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
||||
export const meta = applyConfig({
|
||||
|
|
@ -150,65 +144,48 @@ export default apiRoute((app) =>
|
|||
types,
|
||||
} = context.req.valid("query");
|
||||
|
||||
const { objects, link } =
|
||||
await fetchTimeline<NotificationWithRelations>(
|
||||
findManyNotifications,
|
||||
{
|
||||
where: (
|
||||
// @ts-expect-error Yes I KNOW the types are wrong
|
||||
notification,
|
||||
// @ts-expect-error Yes I KNOW the types are wrong
|
||||
{ lt, gte, gt, and, eq, not, inArray },
|
||||
): SQL | undefined =>
|
||||
and(
|
||||
max_id ? lt(notification.id, max_id) : undefined,
|
||||
since_id
|
||||
? gte(notification.id, since_id)
|
||||
: undefined,
|
||||
min_id ? gt(notification.id, min_id) : undefined,
|
||||
eq(notification.notifiedId, user.id),
|
||||
eq(notification.dismissed, false),
|
||||
account_id
|
||||
? eq(notification.accountId, account_id)
|
||||
: undefined,
|
||||
not(eq(notification.accountId, user.id)),
|
||||
types
|
||||
? inArray(notification.type, types)
|
||||
: undefined,
|
||||
exclude_types
|
||||
? not(inArray(notification.type, exclude_types))
|
||||
: undefined,
|
||||
// Don't show notes that have filtered words in them (via Notification.note.content via Notification.noteId)
|
||||
// Filters in `Filters` table have keyword in `FilterKeywords` table (use LIKE)
|
||||
// Filters table has a userId and a context which is an array
|
||||
sql`NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM "Filters"
|
||||
WHERE "Filters"."userId" = ${user.id}
|
||||
AND "Filters"."filter_action" = 'hide'
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM "FilterKeywords", "Notifications" as "n_inner", "Notes"
|
||||
WHERE "FilterKeywords"."filterId" = "Filters"."id"
|
||||
AND "n_inner"."noteId" = "Notes"."id"
|
||||
AND "Notes"."content" LIKE
|
||||
'%' || "FilterKeywords"."keyword" || '%'
|
||||
AND "n_inner"."id" = "Notifications"."id"
|
||||
)
|
||||
AND "Filters"."context" @> ARRAY['notifications']
|
||||
)`,
|
||||
),
|
||||
limit,
|
||||
// @ts-expect-error Yes I KNOW the types are wrong
|
||||
orderBy: (notification, { desc }): SQL | undefined =>
|
||||
desc(notification.id),
|
||||
},
|
||||
context.req.raw,
|
||||
user.id,
|
||||
);
|
||||
const { objects, link } = await Timeline.getNotificationTimeline(
|
||||
and(
|
||||
max_id ? lt(Notifications.id, max_id) : undefined,
|
||||
since_id ? gte(Notifications.id, since_id) : undefined,
|
||||
min_id ? gt(Notifications.id, min_id) : undefined,
|
||||
eq(Notifications.notifiedId, user.id),
|
||||
eq(Notifications.dismissed, false),
|
||||
account_id
|
||||
? eq(Notifications.accountId, account_id)
|
||||
: undefined,
|
||||
not(eq(Notifications.accountId, user.id)),
|
||||
types ? inArray(Notifications.type, types) : undefined,
|
||||
exclude_types
|
||||
? not(inArray(Notifications.type, exclude_types))
|
||||
: undefined,
|
||||
// Don't show notes that have filtered words in them (via Notification.note.content via Notification.noteId)
|
||||
// Filters in `Filters` table have keyword in `FilterKeywords` table (use LIKE)
|
||||
// Filters table has a userId and a context which is an array
|
||||
sql`NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM "Filters"
|
||||
WHERE "Filters"."userId" = ${user.id}
|
||||
AND "Filters"."filter_action" = 'hide'
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM "FilterKeywords", "Notifications" as "n_inner", "Notes"
|
||||
WHERE "FilterKeywords"."filterId" = "Filters"."id"
|
||||
AND "n_inner"."noteId" = "Notes"."id"
|
||||
AND "Notes"."content" LIKE
|
||||
'%' || "FilterKeywords"."keyword" || '%'
|
||||
AND "n_inner"."id" = "Notifications"."id"
|
||||
)
|
||||
AND "Filters"."context" @> ARRAY['notifications']
|
||||
)`,
|
||||
),
|
||||
limit,
|
||||
context.req.url,
|
||||
user?.id,
|
||||
);
|
||||
|
||||
return context.json(
|
||||
await Promise.all(objects.map((n) => notificationToApi(n))),
|
||||
await Promise.all(objects.map((n) => n.toApi())),
|
||||
200,
|
||||
{
|
||||
Link: link,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { apiRoute, applyConfig, auth, jsonOrForm } from "@/api";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { Note, db } from "@versia/kit/db";
|
||||
import { Notes, Notifications, RolePermissions } from "@versia/kit/tables";
|
||||
import { Note, Notification } from "@versia/kit/db";
|
||||
import { Notes, RolePermissions } from "@versia/kit/tables";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { z } from "zod";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
|
@ -141,7 +141,7 @@ export default apiRoute((app) =>
|
|||
}
|
||||
|
||||
if (foundStatus.author.isLocal() && user.isLocal()) {
|
||||
await db.insert(Notifications).values({
|
||||
await Notification.insert({
|
||||
accountId: user.id,
|
||||
notifiedId: foundStatus.author.id,
|
||||
type: "reblog",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue