Skip to content

Commit

Permalink
Merge pull request #614 from dzcode-io/feat/sitemap-for-contributors
Browse files Browse the repository at this point in the history
feat: sitemap for contributors pages
  • Loading branch information
ZibanPirate authored Dec 19, 2024
2 parents 13b0842 + 447d8c7 commit fc2a31f
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 1 deletion.
4 changes: 4 additions & 0 deletions api/src/app/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { GetContributionsResponse } from "src/contribution/types";
import {
GetContributorNameResponse,
GetContributorResponse,
GetContributorsForSitemapResponse,
GetContributorsResponse,
} from "src/contributor/types";
import { GetMilestonesResponse } from "src/milestone/types";
Expand Down Expand Up @@ -35,6 +36,9 @@ export interface Endpoints {
"api:Contributors": {
response: GetContributorsResponse;
};
"api:contributors/for-sitemap": {
response: GetContributorsForSitemapResponse;
};
"api:Contributors/:id": {
response: GetContributorResponse;
params: { id: string };
Expand Down
10 changes: 10 additions & 0 deletions api/src/contributor/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ContributorRepository } from "./repository";
import {
GetContributorNameResponse,
GetContributorResponse,
GetContributorsForSitemapResponse,
GetContributorsResponse,
} from "./types";
import { ProjectRepository } from "src/project/repository";
Expand All @@ -28,6 +29,15 @@ export class ContributorController {
};
}

@Get("/for-sitemap")
public async getContributorsForSitemap(): Promise<GetContributorsForSitemapResponse> {
const contributors = await this.contributorRepository.findForSitemap();

return {
contributors,
};
}

@Get("/:id")
public async getContributor(@Param("id") id: string): Promise<GetContributorResponse> {
const [contributor, projects, contributions] = await Promise.all([
Expand Down
15 changes: 15 additions & 0 deletions api/src/contributor/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,21 @@ export class ContributorRepository {
return camelCased;
}

public async findForSitemap() {
const statement = sql`
SELECT
${contributorsTable.id}
FROM
${contributorsTable}
`;

const raw = await this.postgresService.db.execute(statement);
const entries = Array.from(raw);
const unStringifiedRaw = unStringifyDeep(entries);
const camelCased = camelCaseObject(unStringifiedRaw);
return camelCased;
}

public async upsert(contributor: ContributorRow) {
return await this.postgresService.db
.insert(contributorsTable)
Expand Down
4 changes: 4 additions & 0 deletions api/src/contributor/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { ContributorEntity } from "@dzcode.io/models/dist/contributor";
import { ProjectEntity } from "@dzcode.io/models/dist/project";
import { GeneralResponse } from "src/app/types";

export interface GetContributorsForSitemapResponse extends GeneralResponse {
contributors: Array<Pick<ContributorEntity, "id">>;
}

export interface GetContributorsResponse extends GeneralResponse {
contributors: Array<
Pick<ContributorEntity, "id" | "name" | "avatarUrl"> & {
Expand Down
2 changes: 1 addition & 1 deletion api/src/project/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ export class ProjectRepository {
public async findForSitemap() {
const statement = sql`
SELECT
id,
${projectsTable.id},
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
FROM
(
Expand Down
49 changes: 49 additions & 0 deletions web/cloudflare/functions/w/contributors-sitemap.xml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Env } from "handler/contributor";
import { environments } from "@dzcode.io/utils/dist/config/environment";
import { allLanguages, LanguageEntity } from "@dzcode.io/models/dist/language";
import { getContributorURL } from "@dzcode.io/web/dist/utils/contributor";
import { fsConfig } from "@dzcode.io/utils/dist/config";
import { fetchV2Factory } from "@dzcode.io/utils/dist/fetch/factory";
import { Endpoints } from "@dzcode.io/api/dist/app/endpoints";

export const onRequest: PagesFunction<Env> = async (context) => {
let stage = context.env.STAGE;
if (!environments.includes(stage)) {
console.log(`⚠️ No STAGE provided, falling back to "development"`);
stage = "development";
}
const fullstackConfig = fsConfig(stage);
const fetchV2 = fetchV2Factory<Endpoints>(fullstackConfig);

const { contributors } = await fetchV2("api:contributors/for-sitemap", {});

const hostname = "https://www.dzCode.io";
const links = contributors.reduce<{ url: string; lang: LanguageEntity["code"] }[]>((pV, cV) => {
return [
...pV,
...allLanguages.map(({ baseUrl, code }) => ({
url: `${baseUrl}${getContributorURL(cV)}`,
lang: code,
})),
];
}, []);

const xml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:news="http://www.google.com/schemas/sitemap-news/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"
xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
${links
.map(
(link) => `
<url>
<loc>${hostname}${link.url}</loc>
<xhtml:link rel="alternate" hreflang="${link.lang}" href="${hostname}${link.url}" />
</url>`,
)
.join("")}
</urlset>`;

return new Response(xml, { headers: { "content-type": "application/xml; charset=utf-8" } });
};

0 comments on commit fc2a31f

Please sign in to comment.