feat: fetch data for charts
This commit is contained in:
36
apps/openpage-api/app/community/route.ts
Normal file
36
apps/openpage-api/app/community/route.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import type { NextRequest } from 'next/server';
|
||||
|
||||
import cors from '@/lib/cors';
|
||||
|
||||
const paths = [
|
||||
{ path: '/total-prs', description: 'Total GitHub Forks' },
|
||||
{ path: '/total-stars', description: 'Total GitHub Stars' },
|
||||
{ path: '/total-forks', description: 'Total GitHub Forks' },
|
||||
{ path: '/total-issues', description: 'Total GitHub Issues' },
|
||||
];
|
||||
|
||||
export function GET(request: NextRequest) {
|
||||
const url = request.nextUrl.toString();
|
||||
const apis = paths.map(({ path, description }) => {
|
||||
return { path: url + path, description };
|
||||
});
|
||||
|
||||
return cors(
|
||||
request,
|
||||
new Response(JSON.stringify(apis), {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export function OPTIONS(request: Request) {
|
||||
return cors(
|
||||
request,
|
||||
new Response(null, {
|
||||
status: 204,
|
||||
}),
|
||||
);
|
||||
}
|
||||
27
apps/openpage-api/app/community/total-forks/route.ts
Normal file
27
apps/openpage-api/app/community/total-forks/route.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import cors from '@/lib/cors';
|
||||
import { transformRepoStats } from '@/lib/transform-repo-stats';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const res = await fetch('https://stargrazer-live.onrender.com/api/stats');
|
||||
const data = await res.json();
|
||||
const transformedData = transformRepoStats(data, 'forks');
|
||||
|
||||
return cors(
|
||||
request,
|
||||
new Response(JSON.stringify({ 'total-forks': transformedData }), {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export function OPTIONS(request: Request) {
|
||||
return cors(
|
||||
request,
|
||||
new Response(null, {
|
||||
status: 204,
|
||||
}),
|
||||
);
|
||||
}
|
||||
27
apps/openpage-api/app/community/total-issues/route.ts
Normal file
27
apps/openpage-api/app/community/total-issues/route.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import cors from '@/lib/cors';
|
||||
import { transformRepoStats } from '@/lib/transform-repo-stats';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const res = await fetch('https://stargrazer-live.onrender.com/api/stats');
|
||||
const data = await res.json();
|
||||
const transformedData = transformRepoStats(data, 'openIssues');
|
||||
|
||||
return cors(
|
||||
request,
|
||||
new Response(JSON.stringify({ 'total-issues': transformedData }), {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export function OPTIONS(request: Request) {
|
||||
return cors(
|
||||
request,
|
||||
new Response(null, {
|
||||
status: 204,
|
||||
}),
|
||||
);
|
||||
}
|
||||
27
apps/openpage-api/app/community/total-prs/route.ts
Normal file
27
apps/openpage-api/app/community/total-prs/route.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import cors from '@/lib/cors';
|
||||
import { transformRepoStats } from '@/lib/transform-repo-stats';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const res = await fetch('https://stargrazer-live.onrender.com/api/stats');
|
||||
const data = await res.json();
|
||||
const transformedData = transformRepoStats(data, 'stars');
|
||||
|
||||
return cors(
|
||||
request,
|
||||
new Response(JSON.stringify({ 'total-stars': transformedData }), {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export function OPTIONS(request: Request) {
|
||||
return cors(
|
||||
request,
|
||||
new Response(null, {
|
||||
status: 204,
|
||||
}),
|
||||
);
|
||||
}
|
||||
27
apps/openpage-api/app/community/total-stars/route.ts
Normal file
27
apps/openpage-api/app/community/total-stars/route.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import cors from '@/lib/cors';
|
||||
import { transformRepoStats } from '@/lib/transform-repo-stats';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const res = await fetch('https://stargrazer-live.onrender.com/api/stats');
|
||||
const data = await res.json();
|
||||
const transformedData = transformRepoStats(data, 'stars');
|
||||
|
||||
return cors(
|
||||
request,
|
||||
new Response(JSON.stringify({ 'total-stars': transformedData }), {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export function OPTIONS(request: Request) {
|
||||
return cors(
|
||||
request,
|
||||
new Response(null, {
|
||||
status: 204,
|
||||
}),
|
||||
);
|
||||
}
|
||||
@@ -2,7 +2,10 @@ import type { NextRequest } from 'next/server';
|
||||
|
||||
import cors from '@/lib/cors';
|
||||
|
||||
const paths = [{ path: 'github', description: 'GitHub Data' }];
|
||||
const paths = [
|
||||
{ path: 'github', description: 'GitHub Data' },
|
||||
{ path: 'community', description: 'Community Data' },
|
||||
];
|
||||
|
||||
export function GET(request: NextRequest) {
|
||||
const url = request.nextUrl.toString();
|
||||
|
||||
71
apps/openpage-api/lib/transform-repo-stats.ts
Normal file
71
apps/openpage-api/lib/transform-repo-stats.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
// Define interfaces for the data structure
|
||||
type RepoStats = {
|
||||
stars: number;
|
||||
forks: number;
|
||||
mergedPRs: number;
|
||||
openIssues: number;
|
||||
};
|
||||
|
||||
type DataEntry = {
|
||||
[key: string]: RepoStats;
|
||||
};
|
||||
|
||||
type TransformedData = {
|
||||
labels: string[];
|
||||
datasets: {
|
||||
label: string;
|
||||
data: number[];
|
||||
}[];
|
||||
};
|
||||
|
||||
type MonthNames = {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
||||
type MetricKey = keyof RepoStats;
|
||||
|
||||
const FRIENDLY_METRIC_NAMES: { [key in MetricKey]: string } = {
|
||||
stars: 'Stars',
|
||||
forks: 'Forks',
|
||||
mergedPRs: 'Merged PRs',
|
||||
openIssues: 'Open Issues',
|
||||
};
|
||||
|
||||
export function transformRepoStats(data: DataEntry, metric: MetricKey): TransformedData {
|
||||
const sortedEntries = Object.entries(data).sort(([dateA], [dateB]) => {
|
||||
const [yearA, monthA] = dateA.split('-').map(Number);
|
||||
const [yearB, monthB] = dateB.split('-').map(Number);
|
||||
return new Date(yearA, monthA - 1).getTime() - new Date(yearB, monthB - 1).getTime();
|
||||
});
|
||||
|
||||
const monthNames: MonthNames = {
|
||||
'1': 'Jan',
|
||||
'2': 'Feb',
|
||||
'3': 'Mar',
|
||||
'4': 'Apr',
|
||||
'5': 'May',
|
||||
'6': 'Jun',
|
||||
'7': 'Jul',
|
||||
'8': 'Aug',
|
||||
'9': 'Sep',
|
||||
'10': 'Oct',
|
||||
'11': 'Nov',
|
||||
'12': 'Dec',
|
||||
};
|
||||
|
||||
const labels = sortedEntries.map(([date]) => {
|
||||
const [year, month] = date.split('-');
|
||||
const monthIndex = parseInt(month);
|
||||
return `${monthNames[monthIndex.toString()]} ${year}`;
|
||||
});
|
||||
|
||||
return {
|
||||
labels,
|
||||
datasets: [
|
||||
{
|
||||
label: `Total ${FRIENDLY_METRIC_NAMES[metric]}`,
|
||||
data: sortedEntries.map(([_, stats]) => stats[metric]),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
"dev:marketing": "turbo run dev --filter=@documenso/marketing",
|
||||
"dev:docs": "turbo run dev --filter=@documenso/documentation",
|
||||
"dev:openpage-api": "turbo run dev --filter=@documenso/openpage-api",
|
||||
"start": "turbo run start --filter=@documenso/web --filter=@documenso/marketing --filter=@documenso/documentation",
|
||||
"start": "turbo run start --filter=@documenso/web --filter=@documenso/marketing --filter=@documenso/documentation --filter=@documenso/openpage-api",
|
||||
"lint": "turbo run lint",
|
||||
"lint:fix": "turbo run lint:fix",
|
||||
"format": "prettier --write \"**/*.{js,jsx,cjs,mjs,ts,tsx,cts,mts,mdx}\"",
|
||||
|
||||
Reference in New Issue
Block a user