|
|
@@ -0,0 +1,112 @@
|
|
|
+<!-- --------------------------------------------------------------------------- -->
|
|
|
+
|
|
|
+<!-- Ordner: Docs -->
|
|
|
+
|
|
|
+<!-- Datei: storage.md -->
|
|
|
+
|
|
|
+<!-- Relativer Pfad: Docs/storage.md -->
|
|
|
+
|
|
|
+<!-- --------------------------------------------------------------------------- -->
|
|
|
+
|
|
|
+# Storage Module (`lib/storage`)
|
|
|
+
|
|
|
+The `lib/storage` module is the **single source of truth** for reading delivery note PDFs from the NAS share.
|
|
|
+
|
|
|
+All code that needs to read from the NAS should go through this module instead of using Node.js `fs` directly. This keeps filesystem logic centralized and makes it easier to change conventions later.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 1. High-Level Responsibilities
|
|
|
+
|
|
|
+- Resolve paths under the NAS root (`NAS_ROOT_PATH`).
|
|
|
+- Provide intention-revealing helpers:
|
|
|
+
|
|
|
+ - `listBranches()` → `['NL01', 'NL02', ...]`
|
|
|
+ - `listYears(branch)` → `['2023', '2024', ...]`
|
|
|
+ - `listMonths(branch, year)` → `['01', '02', ...]`
|
|
|
+ - `listDays(branch, year, month)` → `['01', '02', ...]`
|
|
|
+ - `listFiles(branch, year, month, day)` → `[{ name, relativePath }, ...]`
|
|
|
+
|
|
|
+- Enforce **read-only** behavior.
|
|
|
+- Use async filesystem APIs (`fs/promises`).
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 2. Environment Configuration
|
|
|
+
|
|
|
+### 2.1 `NAS_ROOT_PATH` (required)
|
|
|
+
|
|
|
+The module depends on:
|
|
|
+
|
|
|
+- `NAS_ROOT_PATH` — absolute Unix path where the NAS share is mounted **inside the app container**.
|
|
|
+
|
|
|
+Default/typical value:
|
|
|
+
|
|
|
+```env
|
|
|
+NAS_ROOT_PATH=/mnt/niederlassungen
|
|
|
+```
|
|
|
+
|
|
|
+Important:
|
|
|
+
|
|
|
+- `lib/storage` reads `process.env.NAS_ROOT_PATH` on demand and does not cache it at module load.
|
|
|
+- If `NAS_ROOT_PATH` is missing, `lib/storage` throws (fail fast).
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 3. Docker Mount Strategy (Local vs Server)
|
|
|
+
|
|
|
+The application code always expects the NAS path **inside the container** to be:
|
|
|
+
|
|
|
+- `/mnt/niederlassungen`
|
|
|
+
|
|
|
+Which host folder is mounted there is an environment concern:
|
|
|
+
|
|
|
+- **Server (`docker-compose.yml`)** mounts the real NAS:
|
|
|
+
|
|
|
+ ```yaml
|
|
|
+ volumes:
|
|
|
+ - /mnt/niederlassungen:/mnt/niederlassungen:ro
|
|
|
+ ```
|
|
|
+
|
|
|
+- **Local development (`docker-compose.local.yml`)** mounts a local fixture folder:
|
|
|
+
|
|
|
+ ```yaml
|
|
|
+ volumes:
|
|
|
+ - ./.local_nas:/mnt/niederlassungen:ro
|
|
|
+ ```
|
|
|
+
|
|
|
+This separation keeps code identical across environments while allowing safe local testing.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 4. Directory Layout Assumptions
|
|
|
+
|
|
|
+`lib/storage` assumes the following structure under `NAS_ROOT_PATH`:
|
|
|
+
|
|
|
+```text
|
|
|
+NAS_ROOT_PATH/
|
|
|
+ @Recently-Snapshot/ # ignored
|
|
|
+ NL01/
|
|
|
+ 2024/
|
|
|
+ 10/
|
|
|
+ 23/
|
|
|
+ file1.pdf
|
|
|
+ file2.pdf
|
|
|
+ ...
|
|
|
+```
|
|
|
+
|
|
|
+Rules:
|
|
|
+
|
|
|
+- Branch directories follow `NL<Number>` (e.g. `NL01`).
|
|
|
+- Year directories are 4-digit numeric (`2024`).
|
|
|
+- Month/day directories are numeric and normalized to **two digits**.
|
|
|
+- Only `.pdf` files are returned by `listFiles()`.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 5. Error Handling
|
|
|
+
|
|
|
+`lib/storage` does not swallow errors:
|
|
|
+
|
|
|
+- If a folder does not exist or is not accessible, `fs.promises.readdir` throws.
|
|
|
+- API route handlers catch and convert errors into HTTP responses.
|