Details page

Right now our links don’t go anywhere. Create a new route, src/routes/file/[id]/+page.svelte. Then, update the links in the Files.svelte component, using resolve imported from $app/paths:

<a href={resolve('/file/[id]', { id: f.id })} class="name">{f.name}</a>

We need to create a new remote function to get the file data:

export const getFile = query(v.string(), async (id) => {
	const [d] = await db.select().from(file).where(eq(file.id, id)).limit(1);

	if (!d) {
		error(404);
	}

	if (d.shared || (await requireUser()).id === d.user_id) {
		return d;
	}

	error(403);
});

Notice that we’re putting our auth checks right here in the query — you should check the user’s credentials whenever you need to access something. Never rely on people being unable to guess the link!

We can now use it on the file details page:

<script lang="ts">
	import { getFile } from '$lib/files.remote';
	import { timeago } from '$lib/utils';
	import bytes from 'pretty-bytes';

	let { params } = $props();

	const file = $derived(await getFile(params.id));
</script>

<main>
	<h1>{file.name}</h1>
	<p>{bytes(file.size)} / uploaded {timeago(file.created_at, new Date())}</p>
</main>

<style>
	main {
		padding: 1rem;
	}
</style>