refactor: read page data from generated content

This commit is contained in:
SepComet
2026-05-05 09:14:51 +08:00
parent d85c8ac85d
commit 7915f8c244
6 changed files with 201 additions and 61 deletions
+116
View File
@@ -0,0 +1,116 @@
import { readFile } from 'node:fs/promises';
import path from 'node:path';
import process from 'node:process';
type ProjectSeed = {
name: string;
description: string;
gitea_repo: string;
cover_image: string;
demo_video?: string;
download_link?: string;
tags: string[];
featured: boolean;
};
export type ProjectData = ProjectSeed & {
repo_url?: string;
updated_at?: string;
source?: 'seed' | 'gitea' | 'gitea+seafile';
};
type ShareSeed = {
name: string;
description: string;
url: string;
time: string;
};
export type ShareData = ShareSeed & {
size?: number;
source?: 'seed' | 'seafile';
updated_at?: string;
};
export type ActivityDay = {
date: string;
count: number;
};
export type RecentActivity = {
type: string;
repo: string;
message: string;
url: string;
time: string;
};
export type GiteaActivityData = {
updatedAt: string;
source: 'placeholder' | 'gitea';
itemCount: number;
days: ActivityDay[];
recent: RecentActivity[];
};
const rootDir = process.cwd();
const generatedProjectsPath = path.join(rootDir, 'src/data/generated/projects.json');
const generatedSharesPath = path.join(rootDir, 'src/data/generated/shares.json');
const generatedActivityPath = path.join(rootDir, 'src/data/generated/gitea-activity.json');
const seedProjectsPath = path.join(rootDir, 'src/content/projects/index.json');
const seedSharesPath = path.join(rootDir, 'src/content/shares/index.json');
const emptyActivity: GiteaActivityData = {
updatedAt: '',
source: 'placeholder',
itemCount: 0,
days: [],
recent: [],
};
export async function loadProjects(): Promise<ProjectData[]> {
return readJsonWithFallback<ProjectData[]>(generatedProjectsPath, seedProjectsPath);
}
export async function loadShares(): Promise<ShareData[]> {
return readJsonWithFallback<ShareData[]>(generatedSharesPath, seedSharesPath);
}
export async function loadGiteaActivity(): Promise<GiteaActivityData> {
try {
return await readJson<GiteaActivityData>(generatedActivityPath);
} catch (error) {
if (!isMissingFileError(error)) {
throw error;
}
return emptyActivity;
}
}
async function readJsonWithFallback<T>(preferredPath: string, fallbackPath: string): Promise<T> {
try {
return await readJson<T>(preferredPath);
} catch (error) {
if (!isMissingFileError(error)) {
throw error;
}
return readJson<T>(fallbackPath);
}
}
async function readJson<T>(filePath: string): Promise<T> {
const raw = await readFile(filePath, 'utf-8');
return JSON.parse(raw) as T;
}
function isMissingFileError(error: unknown) {
return (
typeof error === 'object' &&
error !== null &&
'code' in error &&
error.code === 'ENOENT'
);
}