Files
website/src/routes/sitemap.xml/+server.ts

78 lines
2.4 KiB
TypeScript

import { listSummaries } from '#lib/server/lists.js';
import { db } from '#lib/server/db/index.js';
import { blogArticles, bookWorks } from '#lib/server/db/schema/index.js';
import { SITE_ORIGIN } from '#lib/seo.js';
import { races } from '#lib/derby/races.js';
import { COURSES } from '#lib/language-learner/courses/index.js';
import { eq } from 'drizzle-orm';
import type { RequestHandler } from './$types';
const staticPaths = [
'/',
'/projects',
'/trackers',
'/blog',
'/lists',
'/trackers/books',
'/projects/game-tracker',
'/projects/game-tracker/pokemon',
'/projects/game-tracker/osu',
'/projects/game-tracker/pokemon/locations',
'/projects/animaldex',
'/projects/energy',
'/projects/derby',
'/projects/spotify-beatmap-finder',
'/projects/world-opinions',
'/projects/language-learner',
...COURSES.map((c) => `/projects/language-learner/${c.code}`)
];
function escapeXml(value: string): string {
return value.replace(/[<>&"']/g, (character) => {
const entities: Record<string, string> = {
'<': '&lt;',
'>': '&gt;',
'&': '&amp;',
'"': '&quot;',
"'": '&apos;'
};
return entities[character];
});
}
export const GET: RequestHandler = async () => {
const [articles, lists, books] = await Promise.all([
db
.select({ slug: blogArticles.slug, updatedAt: blogArticles.updatedAt })
.from(blogArticles)
.where(eq(blogArticles.status, 'published')),
listSummaries(),
db.select({ id: bookWorks.id, updatedAt: bookWorks.updatedAt }).from(bookWorks)
]);
const entries: { path: string; lastmod?: string }[] = [
...staticPaths.map((path) => ({ path })),
...races.map((race) => ({ path: `/projects/derby/${race.slug}` })),
...articles.map((article) => ({
path: `/blog/${encodeURIComponent(article.slug)}`,
lastmod: article.updatedAt.toISOString()
})),
...lists.map((list) => ({ path: `/lists/${encodeURIComponent(list.slug)}` })),
...books.map((book) => ({
path: `/trackers/books/${book.id}`,
lastmod: book.updatedAt.toISOString()
}))
];
const body = `<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n${entries
.map(
({ path, lastmod }) =>
` <url><loc>${escapeXml(new URL(path, SITE_ORIGIN).href)}</loc>${lastmod ? `<lastmod>${lastmod}</lastmod>` : ''}</url>`
)
.join('\n')}\n</urlset>\n`;
return new Response(body, {
headers: {
'content-type': 'application/xml; charset=utf-8',
'cache-control': 'public, max-age=3600'
}
});
};