Skip to content

Commit

Permalink
🥅 Better handle errors
Browse files Browse the repository at this point in the history
  • Loading branch information
fTrestour committed Nov 2, 2024
1 parent 7664c18 commit d2a8a9c
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 38 deletions.
12 changes: 3 additions & 9 deletions src/build.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import { buildPages, copyStaticFiles, createSiteMap, getEnv } from "./utils";
import { buildPages, copyStaticFiles, createSiteMap } from "./utils";

async function render() {
const { siteUrl } = getEnv();
const builtFilenames = await buildPages();
await copyStaticFiles();
await createSiteMap(builtFilenames, siteUrl);
}

render().catch(console.error);
buildPages().then(createSiteMap);
copyStaticFiles();
6 changes: 3 additions & 3 deletions src/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Html, type PropsWithChildren } from "@kitajs/html";
import { getEnv } from "./utils";
import { getSiteConfig } from "./utils";

export default function Layout(
props: PropsWithChildren<{ title: string; lang?: string }>,
) {
const { siteLang } = getEnv();
const { lang } = getSiteConfig();
return (
<>
{"<!DOCTYPE html>"}
<html lang={props.lang ?? siteLang}>
<html lang={props.lang ?? lang}>
<head>
<meta charset="UTF-8" />
<meta
Expand Down
128 changes: 102 additions & 26 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,58 +2,134 @@ import { promises as fs } from "node:fs";
import { join } from "node:path";
import { Glob } from "bun";

export function getEnv() {
const siteUrl = process.env["SITE_URL"];
export function getSiteConfig() {
const url = process.env["SITE_URL"];

if (!siteUrl) {
throw new Error("SITE_URL environment variable is missing");
if (!url) {
throw new Error(
"SITE_URL environment variable is missing. Add it to the .env file",
);
}
if (!siteUrl.endsWith("/")) {
if (!url.endsWith("/")) {
throw new Error("SITE_URL should finish with /");
}

const siteLang = process.env["SITE_LANGUAGE"];
const lang = process.env["SITE_LANGUAGE"];

if (!lang) {
throw new Error(
"SITE_LANGUAGE environment variable is missing. Add it to the .env file",
);
}

return {
siteUrl,
siteLang,
url,
lang,
buildDir: "dist",
pagesDir: "src/pages",
staticDir: "src/static",
};
}

export async function createSiteMap(builtFilenames: string[], siteUrl: string) {
export async function createSiteMap(builtFilenames: string[]) {
const siteConfig = getSiteConfig();

console.log("Building sitemap");

const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${builtFilenames.map((filename) => `<url><loc>${siteUrl}${filename}</loc></url>`).join("\n ")}
${builtFilenames.map((filename) => `<url><loc>${siteConfig.url}${filename}</loc></url>`).join("\n ")}
</urlset>`;

await fs.writeFile(join("dist", "sitemap.xml"), sitemap, "utf8");
try {
await fs.writeFile(
join(siteConfig.buildDir, "sitemap.xml"),
sitemap,
"utf8",
);

console.log("Successfully built sitemap");
} catch (e) {
console.error("Failed to build sitemap:");
console.error(e);
}
}

export async function buildPages() {
const glob = new Glob("**/*.tsx");
const pages = "src/pages";
const siteConfig = getSiteConfig();

const paths = new Array<string>();
for await (const path of new Glob("**/*.tsx").scan(siteConfig.pagesDir)) {
paths.push(path);
}
const results = await Promise.allSettled(paths.map(buildPage));

const successfulBuilds: string[] = [];
const failedBuilds: string[] = [];

const builtFilenames = new Array<string>();
for await (const path of glob.scan("src/pages")) {
const file = join(pages, path);
results.forEach((result, index) => {
if (result.status === "fulfilled") {
successfulBuilds.push(result.value);
} else {
failedBuilds.push(paths[index]);
console.error(`Failed to build ${paths[index]}:`);
console.error(result.reason);
}
});

return successfulBuilds;
}

async function buildPage(path: string) {
const siteConfig = getSiteConfig();
const file = join(siteConfig.pagesDir, path);

console.log(`Building page for ${file}`);

let html: string;
try {
const { default: Page } = await import(file);
const html = Page();
html = Page();
} catch (e) {
throw new Error(`Could not import ${file}`, { cause: e });
}

const builtFilename = path.replace(".tsx", ".html");
const toBuildUrl = path.replace(".tsx", ".html");
const toBuildFile = join(siteConfig.buildDir, toBuildUrl);
const targetDir = join(siteConfig.buildDir, toBuildUrl, "..");

builtFilenames.push(builtFilename);
try {
await fs.mkdir(targetDir, {
recursive: true,
});
await fs.writeFile(toBuildFile, html, "utf8");

await fs.mkdir(join("dist", builtFilename, ".."), { recursive: true });
await fs.writeFile(join("dist", builtFilename), html, "utf8");
console.log(`Successfully built ${file} to ${toBuildFile}`);
} catch (e) {
throw new Error(`Could not save ${toBuildUrl}`, { cause: e });
}
return builtFilenames;

return toBuildUrl;
}

export async function copyStaticFiles() {
const glob = new Glob("**/*");
for await (const path of glob.scan("src/static")) {
await fs.mkdir(join("dist", path, ".."), { recursive: true });
await fs.copyFile(join("src/static", path), join("dist", path));
const siteConfig = getSiteConfig();

for await (const path of new Glob("**/*").scan(siteConfig.staticDir)) {
const sourceFile = join(siteConfig.staticDir, path);
const targetFile = join(siteConfig.buildDir, path);

console.log(`Copying ${sourceFile} to ${targetFile}`);
try {
await fs.mkdir(join(siteConfig.buildDir, path, ".."), {
recursive: true,
});
await fs.copyFile(sourceFile, targetFile);

console.log(`Successfully copied ${sourceFile} to ${targetFile}`);
} catch (e) {
console.error("Failed to build sitemap:");
console.error(e);
}
}
}

0 comments on commit d2a8a9c

Please sign in to comment.