From 050b82e67a236d991c7151bf8a37ceb364fb11a5 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Wed, 26 Aug 2026 00:16:55 +0200 Subject: [PATCH] Refactor Dockerfile to use slim images and remove openapi.json --- Dockerfile | 8 ++++---- spa/openapi.json | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) delete mode 100644 spa/openapi.json diff --git a/Dockerfile b/Dockerfile index 40f0596..93ab819 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,17 +5,17 @@ RUN bun install --frozen-lockfile COPY spa/ . RUN bun run build -FROM rust:1-alpine AS builder +FROM rust:1-slim-bookworm AS builder WORKDIR /app -RUN apk add --no-cache musl-dev openssl-dev openssl-libs-static pkgconfig +RUN apt-get update && apt-get install -y pkg-config libssl-dev && rm -rf /var/lib/apt/lists/* COPY Cargo.toml Cargo.lock ./ COPY crates/ ./crates/ RUN cargo build --release --bin k-mood -FROM alpine:3 -RUN apk add --no-cache ca-certificates wget +FROM debian:bookworm-slim +RUN apt-get update && apt-get install -y ca-certificates wget libssl3 && rm -rf /var/lib/apt/lists/* COPY --from=builder /app/target/release/k-mood /usr/local/bin/k-mood COPY --from=frontend /app/spa/dist /spa/dist diff --git a/spa/openapi.json b/spa/openapi.json deleted file mode 100644 index 1b4c4f4..0000000 --- a/spa/openapi.json +++ /dev/null @@ -1 +0,0 @@ -{"openapi":"3.1.0","info":{"title":"k-mood API","description":"Mood tracking journal API","license":{"name":""},"version":"1.0.0"},"paths":{"/api/v1/activities":{"get":{"tags":["activities"],"operationId":"handle_list","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ActivityResponse"}}}}}},"security":[{"bearer":[]}]},"post":{"tags":["activities"],"operationId":"handle_create","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateActivityRequest"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityResponse"}}}}},"security":[{"bearer":[]}]}},"/api/v1/activities/{id}":{"get":{"tags":["activities"],"operationId":"handle_get","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityResponse"}}}}},"security":[{"bearer":[]}]},"delete":{"tags":["activities"],"operationId":"handle_delete","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"bearer":[]}]}},"/api/v1/activities/{id}/archive":{"post":{"tags":["activities"],"operationId":"handle_archive","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"bearer":[]}]}},"/api/v1/activities/{id}/category":{"patch":{"tags":["activities"],"operationId":"handle_set_category","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetCategoryRequest"}}},"required":true},"responses":{"204":{"description":""}},"security":[{"bearer":[]}]}},"/api/v1/activities/{id}/name":{"patch":{"tags":["activities"],"operationId":"handle_rename","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenameActivityRequest"}}},"required":true},"responses":{"204":{"description":""}},"security":[{"bearer":[]}]}},"/api/v1/activities/{id}/unarchive":{"post":{"tags":["activities"],"operationId":"handle_unarchive","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"bearer":[]}]}},"/api/v1/auth/login":{"post":{"tags":["auth"],"operationId":"handle_login","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Login successful"}}}},"/api/v1/auth/logout":{"post":{"tags":["auth"],"operationId":"handle_logout","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogoutRequest"}}},"required":true},"responses":{"204":{"description":"Logged out"}}}},"/api/v1/auth/refresh":{"post":{"tags":["auth"],"operationId":"handle_refresh","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshRequest"}}},"required":true},"responses":{"200":{"description":"Token refreshed"}}}},"/api/v1/data/export":{"get":{"tags":["data"],"operationId":"handle_export","responses":{"200":{"description":"ZIP archive with user data"}},"security":[{"bearer":[]}]}},"/api/v1/data/import":{"post":{"tags":["data"],"operationId":"handle_import","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportResultResponse"}}}}},"security":[{"bearer":[]}]}},"/api/v1/entries":{"get":{"tags":["entries"],"operationId":"handle_list","parameters":[{"name":"from","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"to","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EntryResponse"}}}}}},"security":[{"bearer":[]}]},"post":{"tags":["entries"],"operationId":"handle_create","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEntryRequest"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryResponse"}}}}},"security":[{"bearer":[]}]}},"/api/v1/entries/bulk/delete":{"delete":{"tags":["entries"],"operationId":"handle_delete_by_date_range","parameters":[{"name":"from","in":"query","required":true,"schema":{"type":"string"}},{"name":"to","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkActionResponse"}}}}},"security":[{"bearer":[]}]}},"/api/v1/entries/bulk/replace-activity":{"post":{"tags":["entries"],"operationId":"handle_replace_activity","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplaceActivityRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkActionResponse"}}}}},"security":[{"bearer":[]}]}},"/api/v1/entries/calendar":{"get":{"tags":["entries"],"operationId":"handle_calendar","parameters":[{"name":"from","in":"query","required":true,"schema":{"type":"string"}},{"name":"to","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CalendarDayResponse"}}}}}},"security":[{"bearer":[]}]}},"/api/v1/entries/correlation/{id}":{"get":{"tags":["entries"],"operationId":"handle_activity_correlation","parameters":[{"name":"id","in":"path","description":"Activity ID","required":true,"schema":{"type":"string"}},{"name":"from","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"to","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CorrelationResponse"}}}}},"security":[{"bearer":[]}]}},"/api/v1/entries/filter/activity/{id}":{"get":{"tags":["entries"],"operationId":"handle_filter_by_activity","parameters":[{"name":"id","in":"path","description":"Activity ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EntryResponse"}}}}}},"security":[{"bearer":[]}]}},"/api/v1/entries/filter/mood/{mood}":{"get":{"tags":["entries"],"operationId":"handle_filter_by_mood","parameters":[{"name":"mood","in":"path","description":"Mood value 1-5","required":true,"schema":{"type":"integer","format":"int32","minimum":0}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EntryResponse"}}}}}},"security":[{"bearer":[]}]}},"/api/v1/entries/stats":{"get":{"tags":["entries"],"operationId":"handle_stats","parameters":[{"name":"from","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"to","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MoodStatsResponse"}}}}},"security":[{"bearer":[]}]}},"/api/v1/entries/{id}":{"get":{"tags":["entries"],"operationId":"handle_get","parameters":[{"name":"id","in":"path","description":"Entry ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryResponse"}}}}},"security":[{"bearer":[]}]},"delete":{"tags":["entries"],"operationId":"handle_delete","parameters":[{"name":"id","in":"path","description":"Entry ID","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"bearer":[]}]},"patch":{"tags":["entries"],"operationId":"handle_update","parameters":[{"name":"id","in":"path","description":"Entry ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEntryRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryResponse"}}}}},"security":[{"bearer":[]}]}},"/api/v1/media/photos":{"post":{"tags":["media"],"operationId":"handle_upload_photo","responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaIdResponse"}}}}},"security":[{"bearer":[]}]}},"/api/v1/media/photos/{id}":{"get":{"tags":["media"],"operationId":"handle_serve_photo","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Photo binary"}}},"delete":{"tags":["media"],"operationId":"handle_delete_photo","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"bearer":[]}]}},"/api/v1/media/voice-memos":{"post":{"tags":["media"],"operationId":"handle_upload_voice_memo","responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaIdResponse"}}}}},"security":[{"bearer":[]}]}},"/api/v1/media/voice-memos/{id}":{"get":{"tags":["media"],"operationId":"handle_serve_voice_memo","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Voice memo binary"}}},"delete":{"tags":["media"],"operationId":"handle_delete_voice_memo","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"bearer":[]}]}},"/api/v1/reminders":{"get":{"tags":["reminders"],"operationId":"handle_list","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ReminderResponse"}}}}}},"security":[{"bearer":[]}]},"post":{"tags":["reminders"],"operationId":"handle_create","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateReminderRequest"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReminderResponse"}}}}},"security":[{"bearer":[]}]}},"/api/v1/reminders/{id}":{"get":{"tags":["reminders"],"operationId":"handle_get","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReminderResponse"}}}}},"security":[{"bearer":[]}]},"delete":{"tags":["reminders"],"operationId":"handle_delete","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"bearer":[]}]},"patch":{"tags":["reminders"],"operationId":"handle_update","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateReminderRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReminderResponse"}}}}},"security":[{"bearer":[]}]}},"/api/v1/users/me":{"get":{"tags":["users"],"operationId":"handle_get_profile","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}}},"security":[{"bearer":[]}]},"delete":{"tags":["users"],"operationId":"handle_delete","responses":{"204":{"description":""}},"security":[{"bearer":[]}]},"patch":{"tags":["users"],"operationId":"handle_update_profile","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProfileRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}}},"security":[{"bearer":[]}]}},"/api/v1/users/me/password":{"patch":{"tags":["users"],"operationId":"handle_change_password","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordRequest"}}},"required":true},"responses":{"204":{"description":""}},"security":[{"bearer":[]}]}},"/api/v1/users/register":{"post":{"tags":["users"],"operationId":"handle_register","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}}}}}},"components":{"schemas":{"ActivityResponse":{"type":"object","required":["id","name","archived","createdAt"],"properties":{"archived":{"type":"boolean"},"category":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}},"BulkActionResponse":{"type":"object","required":["affectedCount"],"properties":{"affectedCount":{"type":"integer","format":"int64","minimum":0}}},"CalendarDayResponse":{"type":"object","required":["date","entries"],"properties":{"date":{"type":"string","format":"date"},"dominantMood":{"type":["integer","null"],"format":"int32","minimum":0},"dominantMoodLabel":{"type":["string","null"]},"entries":{"type":"array","items":{"$ref":"#/components/schemas/EntryResponse"}}}},"ChangePasswordRequest":{"type":"object","required":["currentPassword","newPassword"],"properties":{"currentPassword":{"type":"string"},"newPassword":{"type":"string"}}},"CorrelationResponse":{"type":"object","required":["activityId"],"properties":{"activityId":{"type":"string","format":"uuid"},"correlation":{"type":["number","null"],"format":"double"}}},"CreateActivityRequest":{"type":"object","required":["name"],"properties":{"category":{"type":["string","null"]},"name":{"type":"string"}}},"CreateEntryRequest":{"type":"object","required":["mood"],"properties":{"activityIds":{"type":["array","null"],"items":{"type":"string"}},"content":{"type":["string","null"]},"loggedAt":{"type":["string","null"]},"mood":{"type":"integer","format":"int32","minimum":0},"photoIds":{"type":["array","null"],"items":{"type":"string"}},"voiceMemoIds":{"type":["array","null"],"items":{"type":"string"}}}},"CreateReminderRequest":{"type":"object","properties":{"friday":{"type":["string","null"]},"monday":{"type":["string","null"]},"saturday":{"type":["string","null"]},"sunday":{"type":["string","null"]},"thursday":{"type":["string","null"]},"tuesday":{"type":["string","null"]},"wednesday":{"type":["string","null"]}}},"DateRangeParams":{"type":"object","required":["from","to"],"properties":{"from":{"type":"string"},"to":{"type":"string"}}},"DayScheduleResponse":{"type":"object","properties":{"friday":{"type":["string","null"]},"monday":{"type":["string","null"]},"saturday":{"type":["string","null"]},"sunday":{"type":["string","null"]},"thursday":{"type":["string","null"]},"tuesday":{"type":["string","null"]},"wednesday":{"type":["string","null"]}}},"EntryResponse":{"type":"object","required":["id","userId","mood","moodLabel","loggedAt","activities","photos","photoUrls","voiceMemos","voiceMemoUrls","createdAt","updatedAt"],"properties":{"activities":{"type":"array","items":{"type":"string","format":"uuid"}},"content":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"id":{"type":"string","format":"uuid"},"loggedAt":{"type":"string","format":"date-time"},"mood":{"type":"integer","format":"int32","minimum":0},"moodLabel":{"type":"string"},"photoUrls":{"type":"array","items":{"type":"string"}},"photos":{"type":"array","items":{"type":"string","format":"uuid"}},"updatedAt":{"type":"string","format":"date-time"},"userId":{"type":"string","format":"uuid"},"voiceMemoUrls":{"type":"array","items":{"type":"string"}},"voiceMemos":{"type":"array","items":{"type":"string","format":"uuid"}}}},"ImportResultResponse":{"type":"object","required":["imported","skipped","errors"],"properties":{"errors":{"type":"array","items":{"type":"string"}},"imported":{"type":"integer","format":"int64","minimum":0},"skipped":{"type":"integer","format":"int64","minimum":0}}},"ListEntriesParams":{"type":"object","properties":{"from":{"type":["string","null"]},"to":{"type":["string","null"]}}},"LoginRequest":{"type":"object","required":["identifier","password"],"properties":{"identifier":{"type":"string"},"password":{"type":"string"}}},"LogoutRequest":{"type":"object","required":["refreshToken"],"properties":{"refreshToken":{"type":"string"}}},"MediaIdResponse":{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"uuid"}}},"MoodFrequency":{"type":"object","required":["mood","moodLabel","count"],"properties":{"count":{"type":"integer","minimum":0},"mood":{"type":"integer","format":"int32","minimum":0},"moodLabel":{"type":"string"}}},"MoodStatsResponse":{"type":"object","required":["frequency","currentStreak","totalEntries"],"properties":{"average":{"type":["number","null"],"format":"double"},"currentStreak":{"type":"integer","minimum":0},"frequency":{"type":"array","items":{"$ref":"#/components/schemas/MoodFrequency"}},"totalEntries":{"type":"integer","minimum":0}}},"RefreshRequest":{"type":"object","required":["refreshToken"],"properties":{"refreshToken":{"type":"string"}}},"RegisterRequest":{"type":"object","required":["username","email","password"],"properties":{"email":{"type":"string"},"password":{"type":"string"},"username":{"type":"string"}}},"ReminderResponse":{"type":"object","required":["id","schedule","enabled","createdAt"],"properties":{"createdAt":{"type":"string","format":"date-time"},"enabled":{"type":"boolean"},"id":{"type":"string","format":"uuid"},"schedule":{"$ref":"#/components/schemas/DayScheduleResponse"}}},"RenameActivityRequest":{"type":"object","required":["newName"],"properties":{"newName":{"type":"string"}}},"ReplaceActivityRequest":{"type":"object","required":["oldActivityId","newActivityId"],"properties":{"newActivityId":{"type":"string"},"oldActivityId":{"type":"string"}}},"SetCategoryRequest":{"type":"object","properties":{"category":{"type":["string","null"]}}},"UpdateEntryRequest":{"type":"object","required":["mood"],"properties":{"activityIds":{"type":["array","null"],"items":{"type":"string"}},"content":{"type":["string","null"]},"loggedAt":{"type":["string","null"]},"mood":{"type":"integer","format":"int32","minimum":0},"photoIds":{"type":["array","null"],"items":{"type":"string"}},"voiceMemoIds":{"type":["array","null"],"items":{"type":"string"}}}},"UpdateProfileRequest":{"type":"object","properties":{"displayName":{"type":["string","null"]},"timezone":{"type":["string","null"]}}},"UpdateReminderRequest":{"type":"object","properties":{"enabled":{"type":["boolean","null"]},"schedule":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/CreateReminderRequest"}]}}},"UserResponse":{"type":"object","required":["id","username","email","role","createdAt"],"properties":{"createdAt":{"type":"string","format":"date-time"},"displayName":{"type":["string","null"]},"email":{"type":"string"},"id":{"type":"string","format":"uuid"},"role":{"type":"string"},"timezone":{"type":["string","null"]},"username":{"type":"string"}}}},"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}},"tags":[{"name":"auth","description":"Authentication"},{"name":"entries","description":"Mood entries"},{"name":"activities","description":"Activity catalog"},{"name":"users","description":"User management"},{"name":"reminders","description":"Reminder schedules"},{"name":"media","description":"Photo and voice memo storage"},{"name":"data","description":"Import and export"}]} \ No newline at end of file