chore: synchronize local fixes to gitea

This commit is contained in:
2026-03-14 00:25:56 +00:00
commit b4ffe72b3e
393 changed files with 71657 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
import fs from 'fs/promises';
import path from 'path';
import { v4 as uuidv4 } from 'uuid';
const DATA_DIR = path.join(process.cwd(), 'data');
// Ensure data directory exists
const initDataDir = async () => {
try {
await fs.access(DATA_DIR);
} catch {
await fs.mkdir(DATA_DIR, { recursive: true });
}
};
initDataDir();
export class FileStorageService<T extends { id: string }> {
private filePath: string;
constructor(filename: string) {
this.filePath = path.join(DATA_DIR, filename);
}
private async readFile(): Promise<T[]> {
try {
await initDataDir();
const data = await fs.readFile(this.filePath, 'utf-8');
return JSON.parse(data);
} catch (error: unknown) {
const err = error as { code?: string };
if (err.code === 'ENOENT') {
return []; // File doesn't exist yet, return empty array
}
throw error;
}
}
private async writeFile(data: T[]): Promise<void> {
await initDataDir();
await fs.writeFile(this.filePath, JSON.stringify(data, null, 2), 'utf-8');
}
async getAll(): Promise<T[]> {
return this.readFile();
}
async getById(id: string): Promise<T | null> {
const items = await this.readFile();
return items.find(item => item.id === id) || null;
}
async create(data: Omit<T, 'id'>): Promise<T> {
const items = await this.readFile();
const newItem = { ...data, id: uuidv4() } as T;
items.push(newItem);
await this.writeFile(items);
return newItem;
}
async update(id: string, data: Partial<T>): Promise<T | null> {
const items = await this.readFile();
const index = items.findIndex(item => item.id === id);
if (index === -1) return null;
items[index] = { ...items[index], ...data };
await this.writeFile(items);
return items[index];
}
async delete(id: string): Promise<boolean> {
const items = await this.readFile();
const filtered = items.filter(item => item.id !== id);
if (filtered.length === items.length) return false;
await this.writeFile(filtered);
return true;
}
// Helper for filtering by foreign keys (e.g., get parts by projectId)
async getByField(field: keyof T, value: T[keyof T]): Promise<T[]> {
const items = await this.readFile();
return items.filter(item => item[field] === value);
}
}