From d0faa162dc9616d8d6d319ea31bc26ab1df88048 Mon Sep 17 00:00:00 2001 From: Anthony GAEREMYNCK <1@anthony.sh> Date: Wed, 29 Jul 2026 14:12:13 +0200 Subject: [PATCH] feat: add storage path helpers Co-Authored-By: Claude Sonnet 5 --- src/storage.js | 23 ++++++++++++++++++++ test/storage.test.js | 52 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 src/storage.js create mode 100644 test/storage.test.js diff --git a/src/storage.js b/src/storage.js new file mode 100644 index 0000000..13fb843 --- /dev/null +++ b/src/storage.js @@ -0,0 +1,23 @@ +import fs from 'node:fs/promises'; +import path from 'node:path'; + +export async function ensureStorageDirs(config) { + await fs.mkdir(path.join(config.storageDir, 'uploads'), { recursive: true }); + await fs.mkdir(path.join(config.storageDir, 'outputs'), { recursive: true }); +} + +export function uploadPath(config, id, ext) { + return path.join(config.storageDir, 'uploads', `${id}.${ext}`); +} + +export function outputPath(config, id, ext) { + return path.join(config.storageDir, 'outputs', `${id}.${ext}`); +} + +export async function deleteIfExists(filePath) { + try { + await fs.unlink(filePath); + } catch (error) { + if (error.code !== 'ENOENT') throw error; + } +} diff --git a/test/storage.test.js b/test/storage.test.js new file mode 100644 index 0000000..fadcfce --- /dev/null +++ b/test/storage.test.js @@ -0,0 +1,52 @@ +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; +import fs from 'node:fs/promises'; +import path from 'node:path'; +import os from 'node:os'; +import { ensureStorageDirs, uploadPath, outputPath, deleteIfExists } from '../src/storage.js'; + +let tmpDir; +let config; + +beforeEach(async () => { + tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'converter-storage-')); + config = { storageDir: tmpDir }; +}); + +afterEach(async () => { + await fs.rm(tmpDir, { recursive: true, force: true }); +}); + +describe('storage', () => { + it('creates uploads and outputs directories', async () => { + await ensureStorageDirs(config); + + const uploadsStat = await fs.stat(path.join(tmpDir, 'uploads')); + const outputsStat = await fs.stat(path.join(tmpDir, 'outputs')); + + expect(uploadsStat.isDirectory()).toBe(true); + expect(outputsStat.isDirectory()).toBe(true); + }); + + it('builds upload and output paths as .', () => { + const id = '11111111-1111-4111-8111-111111111111'; + + expect(uploadPath(config, id, 'png')).toBe(path.join(tmpDir, 'uploads', `${id}.png`)); + expect(outputPath(config, id, 'pdf')).toBe(path.join(tmpDir, 'outputs', `${id}.pdf`)); + }); + + it('deletes an existing file', async () => { + await ensureStorageDirs(config); + const filePath = uploadPath(config, 'file-to-delete', 'txt'); + await fs.writeFile(filePath, 'content'); + + await deleteIfExists(filePath); + + await expect(fs.stat(filePath)).rejects.toThrow(); + }); + + it('does not throw when deleting a missing file', async () => { + const filePath = uploadPath(config, 'does-not-exist', 'txt'); + + await expect(deleteIfExists(filePath)).resolves.toBeUndefined(); + }); +});