UNPKG

digitaltwin-core

Version:

Minimalist framework to collect and handle data in a Digital Twin project

110 lines 4.42 kB
import { StorageService } from '../storage_service.js'; import fs from 'fs/promises'; import path from 'path'; /** * Local filesystem-based implementation of the StorageService. * Saves files in a configured folder using a timestamp as filename. */ export class LocalStorageService extends StorageService { constructor(baseDir = 'data') { super(); this.baseDir = baseDir; } /** * Saves the given buffer to disk under a unique filename. * @param buffer - Content to save * @param collectorName - Name of the collector (used for folder) * @param extension - Optional file extension (e.g. 'json', 'txt') * @returns Relative path to the saved file */ async save(buffer, collectorName, extension) { const now = new Date(); const timestamp = now.toISOString().replace(/[:.]/g, '-'); const folder = collectorName || 'default'; const filename = extension ? `${timestamp}.${extension}` : timestamp; const dirPath = path.join(this.baseDir, folder); const filePath = path.join(dirPath, filename); await fs.mkdir(dirPath, { recursive: true }); await fs.writeFile(filePath, buffer); // return relative path (e.g., 'mycollector/2025-07-07T15-45-22-456Z.json') return path.join(folder, filename); } /** * Retrieves a file as buffer using its relative path. * @param relativePath - Filename previously returned by `save` * @returns File content as Buffer */ async retrieve(relativePath) { const filePath = path.join(this.baseDir, relativePath); return fs.readFile(filePath); } /** * Deletes a stored file. * @param relativePath - Filename previously returned by `save` */ async delete(relativePath) { const filePath = path.join(this.baseDir, relativePath); await fs.rm(filePath, { force: true }); } /** * Saves the given buffer to disk at a specific path (preserves filename). * Unlike save(), this method does not auto-generate a timestamp filename. * @param buffer - Content to save * @param relativePath - Full relative path including filename (e.g., 'tilesets/123/tileset.json') * @returns The same relative path that was provided */ async saveWithPath(buffer, relativePath) { const filePath = path.join(this.baseDir, relativePath); const dirPath = path.dirname(filePath); await fs.mkdir(dirPath, { recursive: true }); await fs.writeFile(filePath, buffer); return relativePath; } /** * Returns a local file path for the stored file. * Note: For local storage, this returns a relative file path, not an HTTP URL. * In production, use a cloud storage service (OVH, S3) for public URLs. * @param relativePath - The storage path of the file * @returns The file path (relative to baseDir) */ getPublicUrl(relativePath) { // For local storage, return the file path // In a real deployment, you'd need Express static serving or similar return path.join(this.baseDir, relativePath); } /** * Deletes all files under a given prefix (folder). * @param prefix - The folder/prefix to delete (e.g., 'tilesets/123') * @returns Number of files deleted */ async deleteByPrefix(prefix) { const folderPath = path.join(this.baseDir, prefix); try { // Check if folder exists await fs.access(folderPath); // Count files before deletion const countFiles = async (dir) => { let count = 0; const entries = await fs.readdir(dir, { withFileTypes: true }); for (const entry of entries) { if (entry.isDirectory()) { count += await countFiles(path.join(dir, entry.name)); } else { count++; } } return count; }; const fileCount = await countFiles(folderPath); // Delete folder recursively await fs.rm(folderPath, { recursive: true, force: true }); return fileCount; } catch { // Folder doesn't exist return 0; } } } //# sourceMappingURL=local_storage_service.js.map