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; export const toCollection = async (nickname: string): Promise | 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 => { 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 => db("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") ;