Files
zero-fucks-given/docs/core/file-manager/backend.md
T

7.9 KiB

File Manager Backend

Authenticated file operations under /file-manager: validation, authorization, path normalization, orchestration, with raw storage delegated to a storage adapter. Source: apps/backend/app/base_modules/FileManager/.

Request Flow

routes.ts
  -> controller/file_manager_controller.ts
  -> validator/*
  -> policy/file_manager_policy.ts
  -> services/file_manager_service.ts
  -> services/storage_service/ (interface -> factory -> fs | s3 adapter)
  -> Adonis Drive

The controller stays thin (auth checks, validation, path extraction, status codes, response shape). FileManagerService owns orchestration; storage adapters own raw persistence.

Routes

All prefixed with /file-manager, behind middleware.auth(); controller methods check policy abilities (policy/file_manager_policy.ts) before doing work. When adding an operation, add or reuse an explicit ability first.

Method Route Controller Method Ability Purpose
GET / and /* index viewList List entries for root or a nested directory.
GET /files/details/* show view Return file metadata and optional text preview content.
GET /files/raw/* raw view Stream raw file content.
GET /search?q=value search viewList Search entries recursively.
POST /folders createFolder create Create a folder.
POST /files upload create Upload a file.
POST /files/duplicate duplicate create Duplicate one or more file entries.
PUT /entries/rename rename update Rename or move an entry within its parent path.
DELETE /* destroy delete Delete an entry.

Validation

Validators in validator/: list_validator.ts (filter, sort, order, max results, pagination token), create_directory_validator.ts, rename_entry_validator.ts, upload_file_validator.ts, duplicate_entries_validator.ts, plus shared helpers in schemas.ts.

Path extraction from wildcard routes goes through helpers/get_validated_path_from_request.ts — never parse wildcard paths in controllers or storage adapters.

Services

Service Owns
file_manager_service.ts Orchestration: listing with filter/sort/pagination, file detail + preview composition, moves, unique upload and copy names, search, storage calls.
path_service.ts Client↔storage path conversion, safe joins, dirname/basename, extension metadata, filename sanitizing, unique names. Use it instead of string manipulation.
entry_list_service.ts List behavior on raw storage entries: category filter, sort, folders-first, pagination + token encoding. Frontend list controls must stay compatible with its accepted values.
file_preview_service.ts Text preview content for previewable extensions (defined in the same file). For rich previews, keep the response small and stream via /files/raw/*.
entry_search_service.ts Path search including matching parent folders for context. Receives an abort signal from the controller — long searches should respect it.

Storage

Abstractions in services/storage_service/:

  • storage_service_interface.ts — the adapter contract: list (flat and recursive), existence, metadata, read/stream/write, create directory, move, delete, copy. Services call the interface, never a concrete adapter.
  • fs_storage_service.ts — filesystem adapter over the Adonis Drive fs disk: maps filesystem objects to entries, handles streams and metadata, preserves directory marker behavior.
  • s3_storage_service.ts — S3-compatible adapter over the s3 disk: maps objects and common prefixes to entries, uploads multipart files by streaming the temp file via putStream, creates folders with directory marker objects, moves folders by moving every object under the prefix, deletes files exactly and folders by prefix, copies file entries. S3 has no native directories, so it shares the .keep marker convention. Folder operations must use slash-terminated prefixes — deleting test/ must not delete test123.txt.
  • fs_directory_marker_service.ts — encapsulates the .keep marker convention; never duplicate marker logic outside it.
  • create_storage_service.ts — factory; the active adapter (fs or s3) is selected by DRIVE_DISK.

Drive Configuration

apps/backend/config/drive.ts configures two disks: fs (local development, filesystem storage) and s3 (S3-compatible object storage, including local MinIO).

S3 environment variables:

Variable Local Docker Value Purpose
AWS_ACCESS_KEY_ID minioadmin S3 access key.
AWS_SECRET_ACCESS_KEY minioadmin S3 secret key.
AWS_REGION us-east-1 S3 region.
S3_BUCKET crux-drive Bucket used by the file manager.
S3_ENDPOINT http://minio:9000 in Docker, http://localhost:9000 outside Docker S3 API endpoint.
S3_CDN_URL http://localhost:9000/crux-drive/ Browser-facing public URL base for file URLs.

For MinIO the disk uses forcePathStyle: true and supportsACL: false; bucket public-read is handled by the Docker bucket setup container.

Local S3 Simulation

docker-compose.yml runs minio (the S3 server) and minio_create_bucket (one-shot setup that creates the bucket and enables anonymous download — it exits after setup, which is normal). Console at http://localhost:9001, credentials minioadmin / minioadmin. After dependency or Dockerfile changes: docker compose build --no-cache && docker compose up.

Response Shape

interface EntryBase {
  name: string;
  path: string;
  updatedAt?: string;
}

interface FileEntry extends EntryBase {
  type: "file";
  size?: number;
  url: string;
}

interface FolderEntry extends EntryBase {
  type: "folder";
}

List responses: { data: Entry[]; meta: { nextPaginationToken: string | null } }.

Backend Change Checklist

  1. Confirm the policy ability for the operation.
  2. Add or update a validator for all request input.
  3. Keep client paths and storage paths separated through path_service.ts.
  4. Update the frontend DTO or mapper if the response shape changes.
  5. Update this documentation when routes, permissions, storage contracts, or response shapes change.