managarten/apps/storage/CLAUDE.md
Till JS ab387b9b3d chore: remove all NestJS backend references, replace with Hono/Bun
- Delete nestjs-backend.md guideline (replaced by hono-server.md)
- Delete Dockerfile.nestjs-base and Dockerfile.nestjs templates
- Delete stale BACKEND_ARCHITECTURE.md doc (NestJS-era, obsolete)
- Update CLAUDE.md, GUIDELINES.md, authentication.md to Hono/Bun first
- Update all app CLAUDE.md files: backend/ → server/, NestJS → Hono+Bun
- Update all app package.json files: @*/backend → @*/server
- Update docs: LOCAL_DEVELOPMENT, PORT_SCHEMA, ENVIRONMENT_VARIABLES,
  DATABASE_MIGRATIONS, MAC_MINI_SERVER, PROJECT_OVERVIEW
- Update scripts: generate-env.mjs, setup-databases.sh, build-app.sh
- Update CI/CD: cd-macmini.yml backend → server paths
- Update Astro docs site: @chat/backend → @chat/server

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 16:52:25 +02:00

294 lines
11 KiB
Markdown

# Storage Project Guide
## Project Structure
```
apps/storage/
├── apps/
│ ├── backend/ # Hono/Bun compute server (@storage/server) - Port 3016
│ ├── landing/ # Astro marketing landing page (@storage/landing)
│ └── web/ # SvelteKit web application (@storage/web) - Port 5185
├── packages/
│ └── shared/ # Shared types, utils, configs (@storage/shared)
└── package.json
```
## Commands
### Root Level (from monorepo root)
```bash
pnpm storage:dev # Run all storage apps
pnpm dev:storage:web # Start web app
pnpm dev:storage:landing # Start landing page
pnpm dev:storage:backend # Start backend server
pnpm dev:storage:app # Start web + backend together
pnpm storage:db:push # Push schema to database
pnpm storage:db:studio # Open Drizzle Studio
pnpm storage:db:seed # Seed database
```
### Backend (apps/storage/apps/backend)
```bash
pnpm dev # Start with hot reload
pnpm build # Build for production
pnpm start:prod # Start production server
pnpm db:push # Push schema to database
pnpm db:studio # Open Drizzle Studio
```
### Web App (apps/storage/apps/web)
```bash
pnpm dev # Start dev server
pnpm build # Build for production
pnpm preview # Preview production build
```
### Landing Page (apps/storage/apps/landing)
```bash
pnpm dev # Start dev server
pnpm build # Build for production
```
## Technology Stack
- **Web**: SvelteKit 2.x, Svelte 5 (runes mode), Tailwind CSS
- **Landing**: Astro 5.x, Tailwind CSS
- **Backend**: NestJS 11, Drizzle ORM, PostgreSQL
- **Storage**: S3-compatible (MinIO)
- **Types**: TypeScript 5.x
## Architecture
### Backend API Endpoints
#### Files
| Endpoint | Method | Description |
| --------------------------------- | ------ | -------------------------- |
| `/api/v1/health` | GET | Health check |
| `/api/v1/files` | GET | List files (with folderId) |
| `/api/v1/files/:id` | GET | Get file details |
| `/api/v1/files/upload` | POST | Upload file (multipart) |
| `/api/v1/files/:id/download` | GET | Download file |
| `/api/v1/files/:id` | PATCH | Update file (rename) |
| `/api/v1/files/:id/move` | PATCH | Move file to folder |
| `/api/v1/files/:id` | DELETE | Soft delete file |
| `/api/v1/files/:id/favorite` | POST | Toggle favorite |
| `/api/v1/files/:id/versions` | GET | List file versions |
| `/api/v1/files/:id/versions` | POST | Upload new version |
| `/api/v1/files/:id/tags` | POST | Update file tags |
#### Folders
| Endpoint | Method | Description |
| --------------------------------- | ------ | -------------------------- |
| `/api/v1/folders` | GET | List root folders |
| `/api/v1/folders/:id` | GET | Get folder with contents |
| `/api/v1/folders/:id/tree` | GET | Get folder tree (sidebar) |
| `/api/v1/folders` | POST | Create folder |
| `/api/v1/folders/:id` | PATCH | Update folder |
| `/api/v1/folders/:id/move` | PATCH | Move folder |
| `/api/v1/folders/:id` | DELETE | Soft delete folder |
| `/api/v1/folders/:id/favorite` | POST | Toggle favorite |
#### Shares
| Endpoint | Method | Description |
| --------------------------------- | ------ | -------------------------- |
| `/api/v1/shares` | GET | List user's shares |
| `/api/v1/shares` | POST | Create share link |
| `/api/v1/shares/:id` | PATCH | Update share settings |
| `/api/v1/shares/:id` | DELETE | Revoke share |
| `/api/v1/public/shares/:token` | GET | Access shared item (public)|
| `/api/v1/public/shares/:token/download` | GET | Download shared file |
#### Tags
| Endpoint | Method | Description |
| --------------------------------- | ------ | -------------------------- |
| `/api/v1/tags` | GET | List user's tags |
| `/api/v1/tags` | POST | Create tag |
| `/api/v1/tags/:id` | PATCH | Update tag |
| `/api/v1/tags/:id` | DELETE | Delete tag |
#### Trash
| Endpoint | Method | Description |
| --------------------------------- | ------ | -------------------------- |
| `/api/v1/trash` | GET | List trash items |
| `/api/v1/trash/:id/restore` | POST | Restore item |
| `/api/v1/trash/:id` | DELETE | Permanently delete |
| `/api/v1/trash` | DELETE | Empty trash |
#### Search & Favorites
| Endpoint | Method | Description |
| --------------------------------- | ------ | -------------------------- |
| `/api/v1/search?q=...` | GET | Search files & folders |
| `/api/v1/favorites` | GET | List favorites |
### Database Schema
**files** - File metadata
- `id` (UUID) - Primary key
- `user_id` (VARCHAR) - User reference
- `name` (VARCHAR) - Display name
- `original_name` (VARCHAR) - Original filename
- `mime_type` (VARCHAR) - MIME type
- `size` (BIGINT) - File size in bytes
- `storage_path` (VARCHAR) - Full S3 path
- `storage_key` (VARCHAR) - S3 object key (unique)
- `parent_folder_id` (UUID) - Parent folder reference
- `current_version` (INTEGER) - Current version number
- `is_favorite` (BOOLEAN) - Favorite flag
- `is_deleted` (BOOLEAN) - Soft delete flag
- `deleted_at` (TIMESTAMP) - Deletion timestamp
- `created_at`, `updated_at` (TIMESTAMP)
**folders** - Folder hierarchy
- `id` (UUID) - Primary key
- `user_id` (VARCHAR) - User reference
- `name` (VARCHAR) - Folder name
- `description` (TEXT) - Optional description
- `parent_folder_id` (UUID) - Self-reference for hierarchy
- `path` (TEXT) - Materialized path (e.g., /root/subfolder)
- `depth` (INTEGER) - Depth in hierarchy
- `is_favorite` (BOOLEAN) - Favorite flag
- `is_deleted` (BOOLEAN) - Soft delete flag
- `deleted_at` (TIMESTAMP) - Deletion timestamp
- `created_at`, `updated_at` (TIMESTAMP)
**file_versions** - Version history
- `id` (UUID) - Primary key
- `file_id` (UUID) - File reference
- `version_number` (INTEGER) - Version number
- `storage_path` (VARCHAR) - S3 path for this version
- `storage_key` (VARCHAR) - S3 key for this version
- `size` (BIGINT) - Version size
- `comment` (TEXT) - Version comment
- `created_by` (VARCHAR) - User who created version
- `created_at` (TIMESTAMP)
**shares** - Sharing links
- `id` (UUID) - Primary key
- `user_id` (VARCHAR) - Owner reference
- `file_id` (UUID) - Shared file (nullable)
- `folder_id` (UUID) - Shared folder (nullable)
- `share_type` (VARCHAR) - 'file' or 'folder'
- `share_token` (VARCHAR) - Unique public token
- `access_level` (VARCHAR) - 'view', 'edit', 'download'
- `password` (VARCHAR) - Optional password hash
- `max_downloads` (INTEGER) - Download limit
- `download_count` (INTEGER) - Current downloads
- `expires_at` (TIMESTAMP) - Expiration date
- `created_at` (TIMESTAMP)
**tags** - User tags
- `id` (UUID) - Primary key
- `user_id` (VARCHAR) - User reference
- `name` (VARCHAR) - Tag name
- `color` (VARCHAR) - Tag color
- `created_at` (TIMESTAMP)
**file_tags** - Many-to-many relation
- `file_id` (UUID) - File reference
- `tag_id` (UUID) - Tag reference
### Environment Variables
#### Backend (.env)
```
NODE_ENV=development
PORT=3016
DATABASE_URL=postgresql://manacore:devpassword@localhost:5432/storage
MANA_CORE_AUTH_URL=http://localhost:3001
CORS_ORIGINS=http://localhost:5173,http://localhost:5185,http://localhost:8081
S3_ENDPOINT=http://localhost:9000
S3_REGION=us-east-1
S3_ACCESS_KEY=minioadmin
S3_SECRET_KEY=minioadmin
STORAGE_S3_PUBLIC_URL=http://localhost:9000/storage-storage
MAX_FILE_SIZE=104857600
MAX_FILES_PER_UPLOAD=10
```
#### Web (.env)
```
PUBLIC_BACKEND_URL=http://localhost:3016
PUBLIC_MANA_CORE_AUTH_URL=http://localhost:3001
```
## Shared Packages
### @storage/shared
- Types: `File`, `Folder`, `FileVersion`, `Share`, `Tag`
- Utils: File type detection, size formatting, path utilities
## File Preview System
The FilePreviewModal supports rich inline previews for various file types:
| File Type | MIME / Extension | Preview |
|-----------|-----------------|---------|
| **Images** | `image/*` | Native `<img>` via download URL |
| **Audio** | `audio/*` | Play button → global MiniPlayer/FullPlayer with frequency visualizer, queue from folder |
| **Video** | `video/*` | Native `<video>` player with controls via presigned S3 URL |
| **PDF** | `application/pdf` | Embedded browser PDF viewer via `<iframe>` |
| **Text/Code** | `text/*`, `.json`, `.js`, `.ts`, `.xml`, `.yaml` | Fetched content in monospace code view (max 50KB) |
| **Markdown** | `.md` | Rendered HTML with headings, lists, code blocks, links |
| **Other** | everything else | File type icon only |
### Audio Player Architecture
```
audioPlayerStore (Svelte 5 runes)
HTMLAudioElement → Presigned S3 URL
Web Audio API (AnalyserNode)
FrequencyBars (Canvas visualizer)
```
**Key files:**
| File | Purpose |
|------|---------|
| `src/lib/stores/audio-player.svelte.ts` | Player state, queue, play/pause/seek/volume |
| `src/lib/audio/analyzer.ts` | Web Audio API singleton for frequency data |
| `src/lib/components/audio/FrequencyBars.svelte` | Canvas frequency bar visualizer |
| `src/lib/components/audio/MiniPlayer.svelte` | Fixed bottom player bar with visualizer |
| `src/lib/components/audio/FullPlayer.svelte` | Fullscreen player with mirrored visualizer background |
**Features:** Queue from audio files in folder, Media Session API (OS controls), presigned S3 URLs, keyboard shortcuts (Space, Escape, Arrow keys in FullPlayer).
## Code Style Guidelines
- **TypeScript**: Strict typing with interfaces
- **Web**: Svelte 5 runes mode (`$state`, `$derived`, `$effect`)
- **Styling**: Tailwind CSS
- **Formatting**: Prettier with project config
## Important Notes
1. **Authentication**: Uses Mana Core Auth (JWT in Authorization header)
2. **Database**: PostgreSQL with Drizzle ORM
3. **Port**: Backend runs on port 3016, Web on port 5185 by default
4. **Storage**: Uses MinIO/S3 for file storage via @manacore/shared-storage
5. **Bucket**: `storage-storage` bucket for all files
6. **Soft Delete**: Files/folders are soft-deleted first (trash), then permanently deleted
7. **Versioning**: Files support version history, each version stored separately in S3
8. **Sharing**: Public links with optional password, download limits, and expiration