mirror of
https://github.com/versia-pub/server.git
synced 2026-01-26 12:16:01 +01:00
Fix not working routes
This commit is contained in:
parent
f7abe06a60
commit
df939a6a7a
|
|
@ -1,8 +1,19 @@
|
||||||
import type { APINotification } from "~types/entities/notification";
|
import type { APINotification } from "~types/entities/notification";
|
||||||
import { type StatusWithRelations, statusToAPI } from "./Status";
|
import {
|
||||||
import { type UserWithRelations, userToAPI } from "./User";
|
type StatusWithRelations,
|
||||||
|
statusToAPI,
|
||||||
|
findFirstStatuses,
|
||||||
|
} from "./Status";
|
||||||
|
import {
|
||||||
|
type UserWithRelations,
|
||||||
|
userToAPI,
|
||||||
|
userRelations,
|
||||||
|
userExtrasTemplate,
|
||||||
|
transformOutputToUserWithRelations,
|
||||||
|
} from "./User";
|
||||||
import type { InferSelectModel } from "drizzle-orm";
|
import type { InferSelectModel } from "drizzle-orm";
|
||||||
import type { notification } from "~drizzle/schema";
|
import type { notification } from "~drizzle/schema";
|
||||||
|
import { db } from "~drizzle/db";
|
||||||
|
|
||||||
export type Notification = InferSelectModel<typeof notification>;
|
export type Notification = InferSelectModel<typeof notification>;
|
||||||
|
|
||||||
|
|
@ -11,6 +22,39 @@ export type NotificationWithRelations = Notification & {
|
||||||
account: UserWithRelations;
|
account: UserWithRelations;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const findManyNotifications = async (
|
||||||
|
query: Parameters<typeof db.query.notification.findMany>[0],
|
||||||
|
): Promise<NotificationWithRelations[]> => {
|
||||||
|
const output = await db.query.notification.findMany({
|
||||||
|
...query,
|
||||||
|
with: {
|
||||||
|
...query?.with,
|
||||||
|
account: {
|
||||||
|
with: {
|
||||||
|
...userRelations,
|
||||||
|
},
|
||||||
|
extras: userExtrasTemplate("notification_account"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
extras: {
|
||||||
|
...query?.extras,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return await Promise.all(
|
||||||
|
output.map(async (notif) => ({
|
||||||
|
...notif,
|
||||||
|
account: transformOutputToUserWithRelations(notif.account),
|
||||||
|
status: notif.statusId
|
||||||
|
? await findFirstStatuses({
|
||||||
|
where: (status, { eq }) =>
|
||||||
|
eq(status.id, notif.statusId ?? ""),
|
||||||
|
})
|
||||||
|
: null,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const notificationToAPI = async (
|
export const notificationToAPI = async (
|
||||||
notification: NotificationWithRelations,
|
notification: NotificationWithRelations,
|
||||||
): Promise<APINotification> => {
|
): Promise<APINotification> => {
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,21 @@ export const statusExtras = {
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const statusExtrasTemplate = (name: string) => ({
|
||||||
|
// @ts-ignore
|
||||||
|
reblogCount: sql([
|
||||||
|
`(SELECT COUNT(*) FROM "Status" "status" WHERE "status"."reblogId" = ${name}.id)`,
|
||||||
|
]).as("reblog_count"),
|
||||||
|
// @ts-ignore
|
||||||
|
likeCount: sql([
|
||||||
|
`(SELECT COUNT(*) FROM "Like" "like" WHERE "like"."likedId" = ${name}.id)`,
|
||||||
|
]).as("like_count"),
|
||||||
|
// @ts-ignore
|
||||||
|
replyCount: sql([
|
||||||
|
`(SELECT COUNT(*) FROM "Status" "status" WHERE "status"."inReplyToPostId" = ${name}.id)`,
|
||||||
|
]).as("reply_count"),
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether this status is viewable by a user.
|
* Returns whether this status is viewable by a user.
|
||||||
* @param user The user to check.
|
* @param user The user to check.
|
||||||
|
|
@ -138,6 +153,15 @@ export const findManyStatuses = async (
|
||||||
where: (attachment, { eq }) =>
|
where: (attachment, { eq }) =>
|
||||||
eq(attachment.statusId, sql`"status"."id"`),
|
eq(attachment.statusId, sql`"status"."id"`),
|
||||||
},
|
},
|
||||||
|
emojis: {
|
||||||
|
with: {
|
||||||
|
emoji: {
|
||||||
|
with: {
|
||||||
|
instance: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
author: {
|
author: {
|
||||||
with: {
|
with: {
|
||||||
...userRelations,
|
...userRelations,
|
||||||
|
|
|
||||||
|
|
@ -536,7 +536,12 @@ export const userRelations = relations(user, ({ many, one }) => ({
|
||||||
relationshipSubjects: many(relationship, {
|
relationshipSubjects: many(relationship, {
|
||||||
relationName: "RelationshipToSubject",
|
relationName: "RelationshipToSubject",
|
||||||
}),
|
}),
|
||||||
notifications: many(notification),
|
notificationsMade: many(notification, {
|
||||||
|
relationName: "NotificationToAccount",
|
||||||
|
}),
|
||||||
|
notificationsReceived: many(notification, {
|
||||||
|
relationName: "NotificationToNotified",
|
||||||
|
}),
|
||||||
openIdAccounts: many(openIdAccount),
|
openIdAccounts: many(openIdAccount),
|
||||||
flags: many(flag),
|
flags: many(flag),
|
||||||
modNotes: many(modNote),
|
modNotes: many(modNote),
|
||||||
|
|
@ -637,6 +642,24 @@ export const statusRelations = relations(status, ({ many, one }) => ({
|
||||||
reblogs: many(status, {
|
reblogs: many(status, {
|
||||||
relationName: "StatusToReblog",
|
relationName: "StatusToReblog",
|
||||||
}),
|
}),
|
||||||
|
notifications: many(notification),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const notificationRelations = relations(notification, ({ one }) => ({
|
||||||
|
account: one(user, {
|
||||||
|
fields: [notification.accountId],
|
||||||
|
references: [user.id],
|
||||||
|
relationName: "NotificationToAccount",
|
||||||
|
}),
|
||||||
|
notified: one(user, {
|
||||||
|
fields: [notification.notifiedId],
|
||||||
|
references: [user.id],
|
||||||
|
relationName: "NotificationToNotified",
|
||||||
|
}),
|
||||||
|
status: one(status, {
|
||||||
|
fields: [notification.statusId],
|
||||||
|
references: [status.id],
|
||||||
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const likeRelations = relations(like, ({ one }) => ({
|
export const likeRelations = relations(like, ({ one }) => ({
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
import { apiRoute, applyConfig } from "@api";
|
import { apiRoute, applyConfig } from "@api";
|
||||||
import { errorResponse, jsonResponse } from "@response";
|
import { errorResponse, jsonResponse } from "@response";
|
||||||
import { fetchTimeline } from "@timelines";
|
import { fetchTimeline } from "@timelines";
|
||||||
import { client } from "~database/datasource";
|
import {
|
||||||
import { userToAPI, type UserWithRelations } from "~database/entities/User";
|
findManyUsers,
|
||||||
import { userRelations } from "~database/entities/relations";
|
userToAPI,
|
||||||
|
type UserWithRelations,
|
||||||
|
} from "~database/entities/User";
|
||||||
|
|
||||||
export const meta = applyConfig({
|
export const meta = applyConfig({
|
||||||
allowedMethods: ["GET"],
|
allowedMethods: ["GET"],
|
||||||
|
|
@ -34,26 +36,19 @@ export default apiRoute<{
|
||||||
if (!user) return errorResponse("Unauthorized", 401);
|
if (!user) return errorResponse("Unauthorized", 401);
|
||||||
|
|
||||||
const { objects, link } = await fetchTimeline<UserWithRelations>(
|
const { objects, link } = await fetchTimeline<UserWithRelations>(
|
||||||
client.user,
|
findManyUsers,
|
||||||
{
|
{
|
||||||
where: {
|
// @ts-expect-error Yes I KNOW the types are wrong
|
||||||
id: {
|
where: (subject, { lt, gte, gt, and, sql }) =>
|
||||||
lt: max_id ?? undefined,
|
and(
|
||||||
gte: since_id ?? undefined,
|
max_id ? lt(subject.id, max_id) : undefined,
|
||||||
gt: min_id ?? undefined,
|
since_id ? gte(subject.id, since_id) : undefined,
|
||||||
},
|
min_id ? gt(subject.id, min_id) : undefined,
|
||||||
relationships: {
|
sql`EXISTS (SELECT 1 FROM "Relationship" WHERE "Relationship"."subjectId" = ${user.id} AND "Relationship"."ownerId" = ${subject.id} AND "Relationship"."requested" = true)`,
|
||||||
some: {
|
),
|
||||||
subjectId: user.id,
|
limit: Number(limit),
|
||||||
requested: true,
|
// @ts-expect-error Yes I KNOW the types are wrong
|
||||||
},
|
orderBy: (subject, { desc }) => desc(subject.id),
|
||||||
},
|
|
||||||
},
|
|
||||||
include: userRelations,
|
|
||||||
take: Number(limit),
|
|
||||||
orderBy: {
|
|
||||||
id: "desc",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
req,
|
req,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,20 @@
|
||||||
import { apiRoute, applyConfig } from "@api";
|
import { apiRoute, applyConfig } from "@api";
|
||||||
import type { Prisma } from "@prisma/client";
|
|
||||||
import { errorResponse, jsonResponse } from "@response";
|
import { errorResponse, jsonResponse } from "@response";
|
||||||
import { fetchTimeline } from "@timelines";
|
import { fetchTimeline } from "@timelines";
|
||||||
import { client } from "~database/datasource";
|
import { client } from "~database/datasource";
|
||||||
import { notificationToAPI } from "~database/entities/Notification";
|
import {
|
||||||
|
findManyNotifications,
|
||||||
|
notificationToAPI,
|
||||||
|
} from "~database/entities/Notification";
|
||||||
import {
|
import {
|
||||||
statusAndUserRelations,
|
statusAndUserRelations,
|
||||||
userRelations,
|
userRelations,
|
||||||
} from "~database/entities/relations";
|
} from "~database/entities/relations";
|
||||||
|
import type {
|
||||||
|
Notification,
|
||||||
|
NotificationWithRelations,
|
||||||
|
} from "~database/entities/Notification";
|
||||||
|
import { db } from "~drizzle/db";
|
||||||
|
|
||||||
export const meta = applyConfig({
|
export const meta = applyConfig({
|
||||||
allowedMethods: ["GET"],
|
allowedMethods: ["GET"],
|
||||||
|
|
@ -52,41 +59,24 @@ export default apiRoute<{
|
||||||
return errorResponse("Can't use both types and exclude_types", 400);
|
return errorResponse("Can't use both types and exclude_types", 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { objects, link } = await fetchTimeline<
|
const { objects, link } = await fetchTimeline<NotificationWithRelations>(
|
||||||
Prisma.NotificationGetPayload<{
|
findManyNotifications,
|
||||||
include: {
|
|
||||||
account: {
|
|
||||||
include: typeof userRelations;
|
|
||||||
};
|
|
||||||
status: {
|
|
||||||
include: typeof statusAndUserRelations;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}>
|
|
||||||
>(
|
|
||||||
client.notification,
|
|
||||||
{
|
{
|
||||||
where: {
|
// @ts-expect-error Yes I KNOW the types are wrong
|
||||||
id: {
|
where: (notification, { lt, gte, gt, and, or, eq, inArray, sql }) =>
|
||||||
lt: max_id ?? undefined,
|
or(
|
||||||
gte: since_id ?? undefined,
|
and(
|
||||||
gt: min_id ?? undefined,
|
max_id ? lt(notification.id, max_id) : undefined,
|
||||||
},
|
since_id ? gte(notification.id, since_id) : undefined,
|
||||||
notifiedId: user.id,
|
min_id ? gt(notification.id, min_id) : undefined,
|
||||||
accountId: account_id,
|
),
|
||||||
},
|
eq(notification.notifiedId, user.id),
|
||||||
include: {
|
eq(notification.accountId, account_id),
|
||||||
account: {
|
),
|
||||||
include: userRelations,
|
with: {},
|
||||||
},
|
limit: Number(limit),
|
||||||
status: {
|
// @ts-expect-error Yes I KNOW the types are wrong
|
||||||
include: statusAndUserRelations,
|
orderBy: (notification, { desc }) => desc(notification.id),
|
||||||
},
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
id: "desc",
|
|
||||||
},
|
|
||||||
take: Number(limit),
|
|
||||||
},
|
},
|
||||||
req,
|
req,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -65,9 +65,9 @@ export default apiRoute<{
|
||||||
status.authorId,
|
status.authorId,
|
||||||
followers.map((f) => f.ownerId),
|
followers.map((f) => f.ownerId),
|
||||||
), */
|
), */
|
||||||
// All statuses where the user is mentioned, using table StatusToUser which has a: status.id and b: user.id
|
// All statuses where the user is mentioned, using table _StatusToUser which has a: status.id and b: user.id
|
||||||
// WHERE format (... = ...)
|
// WHERE format (... = ...)
|
||||||
sql`EXISTS (SELECT 1 FROM "StatusToUser" WHERE "StatusToUser"."a" = ${status.id} AND "StatusToUser"."b" = ${user.id})`,
|
sql`EXISTS (SELECT 1 FROM "_StatusToUser" WHERE "_StatusToUser"."a" = ${status.id} AND "_StatusToUser"."b" = ${user.id})`,
|
||||||
// All statuses from users that the user is following
|
// All statuses from users that the user is following
|
||||||
// WHERE format (... = ...)
|
// WHERE format (... = ...)
|
||||||
sql`EXISTS (SELECT 1 FROM "Relationship" WHERE "Relationship"."subjectId" = ${status.authorId} AND "Relationship"."ownerId" = ${user.id} AND "Relationship"."following" = true)`,
|
sql`EXISTS (SELECT 1 FROM "Relationship" WHERE "Relationship"."subjectId" = ${status.authorId} AND "Relationship"."ownerId" = ${user.id} AND "Relationship"."following" = true)`,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// import { server } from "~index";
|
import { server } from "~index";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This allows us to send a test request to the server even when it isnt running
|
* This allows us to send a test request to the server even when it isnt running
|
||||||
|
|
@ -7,9 +7,7 @@
|
||||||
* @returns Response from the server
|
* @returns Response from the server
|
||||||
*/
|
*/
|
||||||
export async function sendTestRequest(req: Request) {
|
export async function sendTestRequest(req: Request) {
|
||||||
console.log(req);
|
return server.fetch(req);
|
||||||
return fetch(req);
|
|
||||||
// return server.fetch(req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function wrapRelativeUrl(url: string, base_url: string) {
|
export function wrapRelativeUrl(url: string, base_url: string) {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,16 @@
|
||||||
import type { findManyStatuses, Status } from "~database/entities/Status";
|
import type { findManyStatuses, Status } from "~database/entities/Status";
|
||||||
import type { findManyUsers, User } from "~database/entities/User";
|
import type { findManyUsers, User } from "~database/entities/User";
|
||||||
import type { Notification } from "~database/entities/Notification";
|
import type {
|
||||||
|
findManyNotifications,
|
||||||
|
Notification,
|
||||||
|
} from "~database/entities/Notification";
|
||||||
import type { db } from "~drizzle/db";
|
import type { db } from "~drizzle/db";
|
||||||
|
|
||||||
export async function fetchTimeline<T extends User | Status | Notification>(
|
export async function fetchTimeline<T extends User | Status | Notification>(
|
||||||
model:
|
model:
|
||||||
| typeof findManyStatuses
|
| typeof findManyStatuses
|
||||||
| typeof findManyUsers
|
| typeof findManyUsers
|
||||||
| typeof db.query.notification.findMany,
|
| typeof findManyNotifications,
|
||||||
args:
|
args:
|
||||||
| Parameters<typeof findManyStatuses>[0]
|
| Parameters<typeof findManyStatuses>[0]
|
||||||
| Parameters<typeof findManyUsers>[0]
|
| Parameters<typeof findManyUsers>[0]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue