refactor: read page data from generated content
This commit is contained in:
@@ -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'
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user