From 79fd506d30eef3d113f4a8e3ab9ebd9004f1e8cc Mon Sep 17 00:00:00 2001 From: João Augusto Costa Branco Marado Torres Date: Sat, 28 Jun 2025 18:14:22 -0300 Subject: feat: index page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: João Augusto Costa Branco Marado Torres --- src/lib/collection/helpers.ts | 107 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/lib/collection/helpers.ts (limited to 'src/lib/collection/helpers.ts') diff --git a/src/lib/collection/helpers.ts b/src/lib/collection/helpers.ts new file mode 100644 index 0000000..83eb21d --- /dev/null +++ b/src/lib/collection/helpers.ts @@ -0,0 +1,107 @@ +import type { CollectionEntry } from "astro:content"; +import { + Blog, + Entity, + type Entry, + type MicroEntry, + type OriginalEntry, + type TranslationEntry, +} from "./schemas.ts"; +import { getEntries, type z } from "astro:content"; +import { defined, get, identity } from "../../utils/anonymous.ts"; +import { createKeyFromArmor } from "../pgp/create.ts"; +import { getUserIDsFromKey } from "../pgp/user.ts"; +import type { UserIDPacket } from "openpgp"; +import { getCollection } from "astro:content"; + +export function getLastUpdate({ data }: CollectionEntry<"blog">): Date { + return data.dateUpdated ?? data.dateCreated; +} +export const sortLastCreated = ( + { data: a }: CollectionEntry<"blog">, + { data: b }: CollectionEntry<"blog">, +): number => b.dateCreated - a.dateCreated; +export const sortFirstCreated = ( + a: CollectionEntry<"blog">, + b: CollectionEntry<"blog">, +): number => sortLastCreated(b, a); +export const sortLastUpdated = ( + { data: a }: CollectionEntry<"blog">, + { data: b }: CollectionEntry<"blog">, +): number => + (b.dateUpdated ?? b.dateCreated) - (a.dateUpdated ?? a.dateCreated); +export const sortFirstUpdated = ( + a: CollectionEntry<"blog">, + b: CollectionEntry<"blog">, +): number => sortLastUpdated(b, a); + +export async function getSigners( + { data }: CollectionEntry<"blog">, +): Promise<{ + id: string; + entity: CollectionEntry<"entity">; + role: z.infer["signers"][number]["role"] | undefined; +}[]> { + const post = Blog.parse(data); + return await getEntries(post.signers.map(get("entity"))).then((x) => + x.map((x) => ({ + id: x.id, + entity: x, + role: post.signers?.find((y) => y.entity.id === x.id)?.role, + })).filter(({ role }) => defined(role)) + ); +} + +export async function getFirstAuthorEmail( + blog: CollectionEntry<"blog">, +): Promise { + const signers = await getSigners(blog); + const emails = await Promise.all( + signers.filter(({ role }) => role === "author").map(async ({ entity }) => { + const { publickey } = Entity.parse(entity.data); + const key = await createKeyFromArmor(publickey.armor); + const users = getUserIDsFromKey(undefined, key); + return users.map(get("email")).filter(Boolean)?.[0]; + }), + ); + return emails.filter(defined)?.[0]; +} + +export async function getFirstUserID( + blog: CollectionEntry<"blog">, +): Promise< + (Partial & { entity: string; website: string | undefined }) +> { + const signers = await getSigners(blog); + const userIDs = await Promise.all( + signers.filter(({ role }) => role === "author").map( + async ({ id, entity }) => { + const { publickey, websites } = Entity.parse(entity.data); + const website = websites?.[0]; + const key = await createKeyFromArmor(publickey.armor); + const users = getUserIDsFromKey(undefined, key); + return users.map((user) => { + return { ...user, entity: id, website }; + })?.[0]; + }, + ), + ); + return userIDs.filter(defined)?.[0]; +} + +export async function fromPosts( + filter: (entry: CollectionEntry<"blog">) => entry is T, + predicate: (entries: T[]) => U = identity as (entries: T[]) => U, +): Promise { + const entries = await getCollection<"blog", T>("blog", filter); + return predicate(entries); +} +export const isOriginal = ( + entry: CollectionEntry<"blog">, +): entry is OriginalEntry => entry.data.kind === "original"; +export const isTranslation = ( + entry: CollectionEntry<"blog">, +): entry is TranslationEntry => entry.data.kind === "translation"; +export const isMicro = ( + entry: CollectionEntry<"blog">, +): entry is MicroEntry => entry.data.kind === "micro"; -- cgit v1.2.3