import type { PostData } from './PostEngine'; import type { GenerationPostIndexLike } from './GenerationSitemapFeedService'; export type GenerationSection = 'core' | 'single' | 'category' | 'tag' | 'date'; export type GenerationPostIndex = GenerationPostIndexLike; function resolvePostCreatedAt(post: { createdAt: Date | string }): Date { if (post.createdAt instanceof Date) { return post.createdAt; } const parsed = new Date(post.createdAt); return Number.isNaN(parsed.getTime()) ? new Date() : parsed; } export function buildGenerationPostIndex(posts: PostData[]): GenerationPostIndex { const postsByCategory = new Map(); const postsByTag = new Map(); const postsByYear = new Map(); const postsByYearMonth = new Map(); const postsByYearMonthDay = new Map(); const append = (target: Map, key: TKey, post: PostData) => { const existing = target.get(key); if (existing) { existing.push(post); return; } target.set(key, [post]); }; for (const post of posts) { for (const category of post.categories || []) { append(postsByCategory, category, post); } for (const tag of post.tags || []) { append(postsByTag, tag, post); } const createdAt = resolvePostCreatedAt(post); const year = createdAt.getFullYear(); const month = String(createdAt.getMonth() + 1).padStart(2, '0'); const day = String(createdAt.getDate()).padStart(2, '0'); const ym = `${year}/${month}`; const ymd = `${year}/${month}/${day}`; append(postsByYear, year, post); append(postsByYearMonth, ym, post); append(postsByYearMonthDay, ymd, post); } return { postsByCategory, postsByTag, postsByYear, postsByYearMonth, postsByYearMonthDay, }; } function countPaginatedPages(totalPosts: number, maxPostsPerPage: number): number { if (totalPosts <= 0) { return 0; } return Math.max(1, Math.ceil(totalPosts / maxPostsPerPage)); } export function estimateGenerationUnitsBySection(params: { posts: PostData[]; allCategories: Set; allTags: Set; yearsMap: Map; yearMonthsMap: Map; yearMonthDaysMap: Map; maxPostsPerPage: number; postIndex?: GenerationPostIndex; }): Record { const { posts, allCategories, allTags, yearsMap, yearMonthsMap, yearMonthDaysMap, maxPostsPerPage, postIndex, } = params; const index = postIndex ?? buildGenerationPostIndex(posts); const rootPages = countPaginatedPages(posts.length, maxPostsPerPage); const pageRoutes = index.postsByCategory.get('page')?.length ?? 0; const categoryPages = Array.from(allCategories).reduce((sum, category) => { const count = index.postsByCategory.get(category)?.length ?? 0; return sum + countPaginatedPages(count, maxPostsPerPage); }, 0); const tagPages = Array.from(allTags).reduce((sum, tag) => { const count = index.postsByTag.get(tag)?.length ?? 0; return sum + countPaginatedPages(count, maxPostsPerPage); }, 0); let datePages = 0; for (const [year] of yearsMap) { const count = index.postsByYear.get(year)?.length ?? 0; datePages += countPaginatedPages(count, maxPostsPerPage); } for (const [ym] of yearMonthsMap) { const count = index.postsByYearMonth.get(ym)?.length ?? 0; datePages += countPaginatedPages(count, maxPostsPerPage); } for (const [ymd] of yearMonthDaysMap) { const count = index.postsByYearMonthDay.get(ymd)?.length ?? 0; datePages += countPaginatedPages(count, maxPostsPerPage); } return { core: 5 + rootPages + pageRoutes, single: posts.length, category: categoryPages, tag: tagPages, date: datePages, }; }