Skip to content

Commit 447d8c7

Browse files
committed
sitemap for contributors pages
1 parent 13b0842 commit 447d8c7

File tree

6 files changed

+83
-1
lines changed

6 files changed

+83
-1
lines changed

api/src/app/endpoints.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { GetContributionsResponse } from "src/contribution/types";
22
import {
33
GetContributorNameResponse,
44
GetContributorResponse,
5+
GetContributorsForSitemapResponse,
56
GetContributorsResponse,
67
} from "src/contributor/types";
78
import { GetMilestonesResponse } from "src/milestone/types";
@@ -35,6 +36,9 @@ export interface Endpoints {
3536
"api:Contributors": {
3637
response: GetContributorsResponse;
3738
};
39+
"api:contributors/for-sitemap": {
40+
response: GetContributorsForSitemapResponse;
41+
};
3842
"api:Contributors/:id": {
3943
response: GetContributorResponse;
4044
params: { id: string };

api/src/contributor/controller.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { ContributorRepository } from "./repository";
55
import {
66
GetContributorNameResponse,
77
GetContributorResponse,
8+
GetContributorsForSitemapResponse,
89
GetContributorsResponse,
910
} from "./types";
1011
import { ProjectRepository } from "src/project/repository";
@@ -28,6 +29,15 @@ export class ContributorController {
2829
};
2930
}
3031

32+
@Get("/for-sitemap")
33+
public async getContributorsForSitemap(): Promise<GetContributorsForSitemapResponse> {
34+
const contributors = await this.contributorRepository.findForSitemap();
35+
36+
return {
37+
contributors,
38+
};
39+
}
40+
3141
@Get("/:id")
3242
public async getContributor(@Param("id") id: string): Promise<GetContributorResponse> {
3343
const [contributor, projects, contributions] = await Promise.all([

api/src/contributor/repository.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,21 @@ export class ContributorRepository {
9494
return camelCased;
9595
}
9696

97+
public async findForSitemap() {
98+
const statement = sql`
99+
SELECT
100+
${contributorsTable.id}
101+
FROM
102+
${contributorsTable}
103+
`;
104+
105+
const raw = await this.postgresService.db.execute(statement);
106+
const entries = Array.from(raw);
107+
const unStringifiedRaw = unStringifyDeep(entries);
108+
const camelCased = camelCaseObject(unStringifiedRaw);
109+
return camelCased;
110+
}
111+
97112
public async upsert(contributor: ContributorRow) {
98113
return await this.postgresService.db
99114
.insert(contributorsTable)

api/src/contributor/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import { ContributorEntity } from "@dzcode.io/models/dist/contributor";
33
import { ProjectEntity } from "@dzcode.io/models/dist/project";
44
import { GeneralResponse } from "src/app/types";
55

6+
export interface GetContributorsForSitemapResponse extends GeneralResponse {
7+
contributors: Array<Pick<ContributorEntity, "id">>;
8+
}
9+
610
export interface GetContributorsResponse extends GeneralResponse {
711
contributors: Array<
812
Pick<ContributorEntity, "id" | "name" | "avatarUrl"> & {

api/src/project/repository.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ export class ProjectRepository {
160160
public async findForSitemap() {
161161
const statement = sql`
162162
SELECT
163-
id,
163+
${projectsTable.id},
164164
ROUND( 100 * sum(repo_with_stats.contributor_count) + 100 * sum(repo_with_stats.stars) + max(repo_with_stats.score) - sum(repo_with_stats.score) / sum(repo_with_stats.contributor_count) )::int as ranking
165165
FROM
166166
(
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { Env } from "handler/contributor";
2+
import { environments } from "@dzcode.io/utils/dist/config/environment";
3+
import { allLanguages, LanguageEntity } from "@dzcode.io/models/dist/language";
4+
import { getContributorURL } from "@dzcode.io/web/dist/utils/contributor";
5+
import { fsConfig } from "@dzcode.io/utils/dist/config";
6+
import { fetchV2Factory } from "@dzcode.io/utils/dist/fetch/factory";
7+
import { Endpoints } from "@dzcode.io/api/dist/app/endpoints";
8+
9+
export const onRequest: PagesFunction<Env> = async (context) => {
10+
let stage = context.env.STAGE;
11+
if (!environments.includes(stage)) {
12+
console.log(`⚠️ No STAGE provided, falling back to "development"`);
13+
stage = "development";
14+
}
15+
const fullstackConfig = fsConfig(stage);
16+
const fetchV2 = fetchV2Factory<Endpoints>(fullstackConfig);
17+
18+
const { contributors } = await fetchV2("api:contributors/for-sitemap", {});
19+
20+
const hostname = "https://www.dzCode.io";
21+
const links = contributors.reduce<{ url: string; lang: LanguageEntity["code"] }[]>((pV, cV) => {
22+
return [
23+
...pV,
24+
...allLanguages.map(({ baseUrl, code }) => ({
25+
url: `${baseUrl}${getContributorURL(cV)}`,
26+
lang: code,
27+
})),
28+
];
29+
}, []);
30+
31+
const xml = `<?xml version="1.0" encoding="UTF-8"?>
32+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
33+
xmlns:news="http://www.google.com/schemas/sitemap-news/0.9"
34+
xmlns:xhtml="http://www.w3.org/1999/xhtml"
35+
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"
36+
xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
37+
${links
38+
.map(
39+
(link) => `
40+
<url>
41+
<loc>${hostname}${link.url}</loc>
42+
<xhtml:link rel="alternate" hreflang="${link.lang}" href="${hostname}${link.url}" />
43+
</url>`,
44+
)
45+
.join("")}
46+
</urlset>`;
47+
48+
return new Response(xml, { headers: { "content-type": "application/xml; charset=utf-8" } });
49+
};

0 commit comments

Comments
 (0)