81 lines
2.5 KiB
TypeScript
81 lines
2.5 KiB
TypeScript
import db from "./db.js";
|
|
import { z } from "zod";
|
|
import { get as getUserByNickname } from "./user.js";
|
|
import { fillRoute } from "./router.js";
|
|
import { getByUserId as getArticlesByUserId, getById as getArticleById, Article } from "./article.js";
|
|
import { createArticleActivity, deleteArticleActivity } from "./activity.js";
|
|
import { orderedCollection } from "./collection.js";
|
|
|
|
|
|
export const zRawOutboxRecord = z.object({
|
|
id: z.number().min(0),
|
|
users_id: z.number().min(0),
|
|
verb: z.string().regex(/^[a-zA-Z]+$/).min(1),
|
|
articles_id: z.number().min(0),
|
|
created_at: z.date(),
|
|
updated_at: z.union([z.date(), z.null()]),
|
|
slug: z.optional(z.string()),
|
|
file: z.optional(z.string()),
|
|
title: z.optional(z.string())
|
|
});
|
|
|
|
export type RawOutboxRecord = z.infer<typeof zRawOutboxRecord>;
|
|
|
|
export const toCollection = async (nickname: string): Promise<Record<string, any> | null> => {
|
|
const user = await getUserByNickname(nickname);
|
|
|
|
if (user) {
|
|
const articles = await get(user.id)
|
|
|
|
const activities = articles.map((a) => {
|
|
if (a.verb === "Create") {
|
|
return createArticleActivity(a, user);
|
|
}
|
|
else if (a.verb === "Delete") {
|
|
return deleteArticleActivity(a, user);
|
|
}
|
|
else {
|
|
throw "unexpected verb";
|
|
}
|
|
});
|
|
|
|
const collection = orderedCollection(fillRoute("outbox", user.nickname), activities);
|
|
|
|
return collection;
|
|
}
|
|
else {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
export const add = async (articleId: number): Promise<number> => {
|
|
const article = await getArticleById(articleId);
|
|
|
|
if (article) {
|
|
return await db("outboxes").insert({
|
|
users_id: article.id,
|
|
verb: "Create",
|
|
articles_id: articleId,
|
|
created_at: article.created_at
|
|
})
|
|
.returning("id")
|
|
.then(([{ id: id }]: { id: number }[]) => id)
|
|
|
|
}
|
|
else throw "failed to add to outbox";
|
|
};
|
|
|
|
interface ArticleActivity extends Article {
|
|
verb: string;
|
|
activity_created_at: Date | number;
|
|
}
|
|
|
|
export const get = async (userId: number): Promise<ArticleActivity[]> =>
|
|
db<ArticleActivity>("articles")
|
|
.select("articles.*", "outboxes.verb", "outboxes.created_at as activity_created_at")
|
|
.join("outboxes", "articles.id", "outboxes.articles_id")
|
|
.where("articles.users_id", userId)
|
|
.whereIn("outboxes.verb", ["Create", "Delete"])
|
|
.orderBy("outboxes.created_at", "desc")
|
|
;
|