Refactor code structure and remove redundant sections for improved readability and maintainability

This commit is contained in:
Puechberty Arthur
2026-02-23 03:57:05 +01:00
parent 5be8966d66
commit 6760a523e4
27 changed files with 2025 additions and 1087 deletions
+35
View File
@@ -0,0 +1,35 @@
import { createHash } from 'node:crypto';
function getRequiredEnv(name) {
const value = process.env[name];
if (!value) {
throw new Error(`Missing required environment variable: ${name}`);
}
return value;
}
export const ADMIN_USERNAME = getRequiredEnv('ADMIN_USERNAME');
export const ADMIN_PASSWORD = getRequiredEnv('ADMIN_PASSWORD');
export const ADMIN_SESSION_SECRET = getRequiredEnv('ADMIN_SESSION_SECRET');
export const ADMIN_COOKIE = 'admin_session';
function hash(value) {
return createHash('sha256').update(value).digest('hex');
}
function expectedToken() {
return hash(`${ADMIN_USERNAME}:${ADMIN_PASSWORD}:${ADMIN_SESSION_SECRET}`);
}
export function isValidAdminCredentials(username, password) {
return username === ADMIN_USERNAME && password === ADMIN_PASSWORD;
}
export function createAdminSessionToken() {
return expectedToken();
}
export function isAdminRequest(request) {
const token = request.cookies.get(ADMIN_COOKIE)?.value;
return token === expectedToken();
}
+121
View File
@@ -0,0 +1,121 @@
import { mkdir, readFile, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { randomUUID } from 'node:crypto';
import { socialLinks } from '../config';
const DATA_DIR = path.join(process.cwd(), 'data');
const LINKS_FILE = path.join(DATA_DIR, 'links.json');
const ANALYTICS_FILE = path.join(DATA_DIR, 'analytics.json');
function slugify(text) {
return (text || '')
.toLowerCase()
.trim()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '')
.slice(0, 50);
}
function withId(link, index) {
return {
id: link.id || `${slugify(link.name)}-${index + 1}`,
name: link.name,
url: link.url,
icon: link.icon,
description: link.description || '',
category: link.category || 'Autres'
};
}
async function fileExists(filePath) {
try {
await readFile(filePath, 'utf-8');
return true;
} catch {
return false;
}
}
async function readJson(filePath, fallback) {
try {
const content = await readFile(filePath, 'utf-8');
return JSON.parse(content);
} catch {
return fallback;
}
}
async function writeJson(filePath, value) {
await writeFile(filePath, JSON.stringify(value, null, 2), 'utf-8');
}
export async function ensureDataFiles() {
await mkdir(DATA_DIR, { recursive: true });
if (!(await fileExists(LINKS_FILE))) {
const initialLinks = socialLinks.map(withId);
await writeJson(LINKS_FILE, initialLinks);
}
if (!(await fileExists(ANALYTICS_FILE))) {
await writeJson(ANALYTICS_FILE, {});
}
}
export async function getLinks() {
await ensureDataFiles();
return readJson(LINKS_FILE, []);
}
export async function addLink(payload) {
await ensureDataFiles();
const links = await getLinks();
const newLink = {
id: randomUUID(),
name: payload.name,
url: payload.url,
icon: payload.icon || '/github.png',
description: payload.description || '',
category: payload.category || 'Autres'
};
const updatedLinks = [...links, newLink];
await writeJson(LINKS_FILE, updatedLinks);
return newLink;
}
export async function removeLink(linkId) {
await ensureDataFiles();
const links = await getLinks();
const nextLinks = links.filter((link) => link.id !== linkId);
if (nextLinks.length === links.length) {
return false;
}
await writeJson(LINKS_FILE, nextLinks);
return true;
}
export async function incrementClick(linkId) {
await ensureDataFiles();
const analytics = await readJson(ANALYTICS_FILE, {});
analytics[linkId] = (analytics[linkId] || 0) + 1;
await writeJson(ANALYTICS_FILE, analytics);
}
export async function getAnalyticsForLinks() {
await ensureDataFiles();
const [links, analytics] = await Promise.all([
readJson(LINKS_FILE, []),
readJson(ANALYTICS_FILE, {})
]);
return links.map((link) => ({
id: link.id,
name: link.name,
url: link.url,
clicks: analytics[link.id] || 0
}));
}