|
1 | 1 | // Server-only post helpers (astro:content cannot be bundled into client scripts — |
2 | 2 | // keep this module out of anything imported by <script> code; taxonomy lives in data.ts). |
3 | | -import { getEntries, type CollectionEntry } from 'astro:content'; |
| 3 | +import { getEntry, type CollectionEntry } from 'astro:content'; |
| 4 | + |
| 5 | +type AuthorData = CollectionEntry<'authors'>['data']; |
| 6 | + |
| 7 | +// A resolved author is shaped like an authors-collection entry, but is produced |
| 8 | +// defensively: a handle with no profile never throws, it degrades to Guest. |
| 9 | +export type ResolvedAuthor = { id: string; data: AuthorData }; |
4 | 10 |
|
5 | 11 | export type PostWithAuthors = CollectionEntry<'posts'> & { |
6 | | - authors: CollectionEntry<'authors'>[]; |
| 12 | + authors: ResolvedAuthor[]; |
| 13 | +}; |
| 14 | + |
| 15 | +const SYNTHETIC_GUEST: ResolvedAuthor = { |
| 16 | + id: 'guest', |
| 17 | + data: { name: 'Guest Contributor', role: 'contributor' } as AuthorData, |
7 | 18 | }; |
8 | 19 |
|
| 20 | +// Resolve one handle to an author. Missing profile → Guest, with a build-time |
| 21 | +// warning so a broken reference is visible in logs without breaking the build. |
| 22 | +async function resolveAuthor(handle: string): Promise<ResolvedAuthor> { |
| 23 | + const entry = await getEntry('authors', handle); |
| 24 | + if (entry) return { id: entry.id, data: entry.data }; |
| 25 | + console.warn(`[authors] no profile for "${handle}" — falling back to Guest.`); |
| 26 | + const guest = await getEntry('authors', 'guest'); |
| 27 | + return guest ? { id: guest.id, data: guest.data } : SYNTHETIC_GUEST; |
| 28 | +} |
| 29 | + |
| 30 | +export async function resolveAuthors(handles: string[] = []): Promise<ResolvedAuthor[]> { |
| 31 | + return Promise.all(handles.map(resolveAuthor)); |
| 32 | +} |
| 33 | + |
9 | 34 | export async function resolvePostAuthors( |
10 | 35 | posts: CollectionEntry<'posts'>[], |
11 | 36 | ): Promise<PostWithAuthors[]> { |
12 | | - return Promise.all(posts.map(async (p) => ({ ...p, authors: await getEntries(p.data.authors) }))); |
| 37 | + return Promise.all( |
| 38 | + posts.map(async (p) => ({ ...p, authors: await resolveAuthors(p.data.authors) })), |
| 39 | + ); |
13 | 40 | } |
14 | 41 |
|
15 | 42 | export function authorNames(post: PostWithAuthors): string { |
|
0 commit comments