98 lines
2.0 KiB
TypeScript
98 lines
2.0 KiB
TypeScript
import { db } from "~/server/db";
|
|
import { publicProcedure, router } from "~/server/trpc";
|
|
|
|
type ReadmeRequest = {
|
|
url: string;
|
|
};
|
|
|
|
function getReadmeRequest(sourceLink: string): ReadmeRequest | null {
|
|
let url: URL;
|
|
|
|
try {
|
|
url = new URL(sourceLink);
|
|
} catch {
|
|
return null;
|
|
}
|
|
|
|
const pathParts = url.pathname.split("/").filter(Boolean);
|
|
const [owner, repo] = pathParts;
|
|
|
|
if (!owner || !repo) {
|
|
return null;
|
|
}
|
|
|
|
const repoName = repo.replace(/\.git$/, "");
|
|
|
|
if (url.hostname === "github.com" || url.hostname === "www.github.com") {
|
|
return {
|
|
url: `https://raw.githubusercontent.com/${owner}/${repoName}/main/README.md`,
|
|
};
|
|
}
|
|
|
|
if (url.hostname.includes("gitea.")) {
|
|
return {
|
|
url: `${url.origin}/${owner}/${repoName}/raw/branch/main/README.md`,
|
|
};
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
async function fetchReadme(sourceLink: string) {
|
|
const readmeRequest = getReadmeRequest(sourceLink);
|
|
|
|
if (!readmeRequest) {
|
|
return null;
|
|
}
|
|
|
|
const controller = new AbortController();
|
|
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
|
|
try {
|
|
const response = await fetch(readmeRequest.url, {
|
|
headers: {
|
|
Accept: "text/plain",
|
|
},
|
|
signal: controller.signal,
|
|
});
|
|
|
|
if (!response.ok) {
|
|
return null;
|
|
}
|
|
|
|
return await response.text();
|
|
} catch {
|
|
return null;
|
|
} finally {
|
|
clearTimeout(timeout);
|
|
}
|
|
}
|
|
|
|
export const projectRouter = router({
|
|
listWithStack: publicProcedure.query(async () => {
|
|
const projects = await db.query.project.findMany({
|
|
orderBy: (project, { asc }) => [
|
|
asc(project.orderPos),
|
|
asc(project.title),
|
|
asc(project.id),
|
|
],
|
|
with: {
|
|
techStack: true,
|
|
},
|
|
});
|
|
|
|
return Promise.all(
|
|
projects.map(async (project) => {
|
|
if (project.description?.length !== 0 || !project.sourceLink) {
|
|
return project;
|
|
}
|
|
|
|
return {
|
|
...project,
|
|
description: await fetchReadme(project.sourceLink),
|
|
};
|
|
}),
|
|
);
|
|
}),
|
|
});
|