All checks were successful
Release / Scraper / Test (push) Successful in 10s
Release / UI / Build (push) Successful in 26s
Release / v2 / Build ui-v2 (push) Successful in 17s
Release / Scraper / Docker (push) Successful in 47s
Release / UI / Docker (push) Successful in 56s
CI / Scraper / Lint (pull_request) Successful in 7s
CI / Scraper / Test (pull_request) Successful in 8s
CI / UI / Build (pull_request) Successful in 16s
CI / Scraper / Docker Push (pull_request) Has been skipped
CI / UI / Docker Push (pull_request) Has been skipped
Release / v2 / Docker / ui-v2 (push) Successful in 56s
Release / v2 / Test backend (push) Successful in 4m35s
iOS CI / Build (pull_request) Successful in 4m28s
Release / v2 / Docker / backend (push) Successful in 1m29s
Release / v2 / Docker / runner (push) Successful in 1m39s
iOS CI / Test (pull_request) Successful in 9m51s
- backend/: Go API server and runner binaries with PocketBase + MinIO storage - ui-v2/: SvelteKit frontend rewrite - docker-compose-new.yml: compose file for the v2 stack - .gitea/workflows/release-v2.yaml: CI/CD for backend, runner, and ui-v2 Docker Hub images - scripts/pb-init.sh: migrate from wget to curl, add superuser bootstrap for fresh installs - .env.example: document DOCKER_BUILDKIT=1 for Colima users
60 lines
1.8 KiB
TypeScript
60 lines
1.8 KiB
TypeScript
import { error } from '@sveltejs/kit';
|
|
import type { PageServerLoad } from './$types';
|
|
import {
|
|
getPublicProfile,
|
|
getSubscription,
|
|
getUserPublicLibrary,
|
|
getUserCurrentlyReading
|
|
} from '$lib/server/pocketbase';
|
|
import { presignAvatarUrl } from '$lib/server/minio';
|
|
import { log } from '$lib/server/logger';
|
|
|
|
export const load: PageServerLoad = async ({ params, locals }) => {
|
|
const { username } = params;
|
|
|
|
const profile = await getPublicProfile(username).catch(() => null);
|
|
if (!profile) error(404, `User "${username}" not found`);
|
|
|
|
// Resolve avatar
|
|
let avatarUrl: string | null = null;
|
|
if (profile.avatar_url) {
|
|
avatarUrl = await presignAvatarUrl(profile.id).catch(() => null);
|
|
}
|
|
|
|
// Subscription state for the logged-in visitor
|
|
let isSubscribed = false;
|
|
const isSelf = locals.user?.id === profile.id;
|
|
if (locals.user && !isSelf) {
|
|
const sub = await getSubscription(locals.user.id, profile.id).catch(() => null);
|
|
isSubscribed = !!sub;
|
|
}
|
|
|
|
// Load public library + currently reading in parallel
|
|
const [library, currentlyReading] = await Promise.all([
|
|
getUserPublicLibrary(profile.id).catch((e) => {
|
|
log.error('users/profile', 'getUserPublicLibrary failed', { username, err: String(e) });
|
|
return [] as Awaited<ReturnType<typeof getUserPublicLibrary>>;
|
|
}),
|
|
getUserCurrentlyReading(profile.id).catch((e) => {
|
|
log.error('users/profile', 'getUserCurrentlyReading failed', { username, err: String(e) });
|
|
return [] as Awaited<ReturnType<typeof getUserCurrentlyReading>>;
|
|
})
|
|
]);
|
|
|
|
return {
|
|
profile: {
|
|
id: profile.id,
|
|
username: profile.username,
|
|
created: profile.created,
|
|
followerCount: profile.followerCount,
|
|
followingCount: profile.followingCount
|
|
},
|
|
avatarUrl,
|
|
isSubscribed,
|
|
isSelf,
|
|
isLoggedIn: !!locals.user,
|
|
library,
|
|
currentlyReading
|
|
};
|
|
};
|