···11-import type { OAuthClient } from "@atcute/oauth-node-client";
21import type { PrivateUserData } from "$lib/valibot.ts";
22+import type { OAuthClient } from "@atcute/oauth-node-client";
3344// See https://svelte.dev/docs/kit/types#app.d.ts
55// for information about these interfaces
+2-2
src/hooks.server.ts
···11-import type { Handle } from "@sveltejs/kit";
21import { dev } from "$app/environment";
33-import { sequence } from "@sveltejs/kit/hooks";
42import { restoreSession } from "$lib/server/session.ts";
33+import type { Handle } from "@sveltejs/kit";
44+import { sequence } from "@sveltejs/kit/hooks";
5566/**
77 * {@link https://svelte.dev/docs/cli/devtools-json}
+9-9
src/lib/server/oauth.ts
···11-import type { Cookies } from "@sveltejs/kit";
11+import { dev } from "$app/environment";
22+import { env } from "$env/dynamic/private";
33+import {
44+ OAUTH_COOKIE_PREFIX,
55+ OAUTH_MAX_AGE,
66+ SESSION_MAX_AGE,
77+} from "$lib/server/constants.ts";
88+import { decryptText, encryptText } from "$lib/server/crypto.ts";
29import {
310 CompositeDidDocumentResolver,
411 CompositeHandleResolver,
···916} from "@atcute/identity-resolver";
1017import { NodeDnsHandleResolver } from "@atcute/identity-resolver-node";
1118import { OAuthClient, scope, type Store } from "@atcute/oauth-node-client";
1212-import { decryptText, encryptText } from "$lib/server/crypto.ts";
1313-import {
1414- OAUTH_COOKIE_PREFIX,
1515- OAUTH_MAX_AGE,
1616- SESSION_MAX_AGE,
1717-} from "$lib/server/constants.ts";
1818-import { env } from "$env/dynamic/private";
1919-import { dev } from "$app/environment";
1919+import type { Cookies } from "@sveltejs/kit";
2020import { Buffer } from "node:buffer";
21212222class CookieStore<K extends string, V> implements Store<K, V> {
+7-7
src/lib/server/session.ts
···11-import type { RequestEvent } from "@sveltejs/kit";
22-import { Client } from "@atcute/client";
33-import { isHandle } from "@atcute/lexicons/syntax";
44-import { createOAuthClient } from "$lib/server/oauth.ts";
55-import { decryptText } from "$lib/server/crypto.ts";
11+import { dev } from "$app/environment";
22+import { env } from "$env/dynamic/private";
63import {
74 HANDLE_COOKIE,
85 OAUTH_MAX_AGE,
96 SESSION_COOKIE,
107} from "$lib/server/constants.ts";
88+import { decryptText } from "$lib/server/crypto.ts";
99+import { createOAuthClient } from "$lib/server/oauth.ts";
1110import { parsePublicUser, type PublicUserData } from "$lib/valibot.ts";
1212-import { dev } from "$app/environment";
1313-import { env } from "$env/dynamic/private";
1111+import { Client } from "@atcute/client";
1212+import { isHandle } from "@atcute/lexicons/syntax";
1313+import type { RequestEvent } from "@sveltejs/kit";
14141515/**
1616 * Logout
+3-3
src/lib/valibot.ts
···11-import * as v from "valibot";
21import { Client } from "@atcute/client";
33-import { OAuthSession } from "@atcute/oauth-node-client";
44-import { isDid, isHandle } from "@atcute/lexicons/syntax";
52import type { Did, Handle } from "@atcute/lexicons";
33+import { isDid, isHandle } from "@atcute/lexicons/syntax";
44+import { OAuthSession } from "@atcute/oauth-node-client";
55+import * as v from "valibot";
6677const UserSchema = {
88 did: v.custom<Did>(isDid, "invalid did"),
+1-1
src/routes/+layout.server.ts
···11-import type { LayoutServerLoad } from "./$types";
21import type { PublicUserData } from "$lib/valibot.ts";
22+import type { LayoutServerLoad } from "./$types.d.ts";
3344export const load: LayoutServerLoad = (event) => {
55 let user: PublicUserData | undefined = undefined;
+1-1
src/routes/+page.server.ts
···11-import { type Actions, fail, redirect } from "@sveltejs/kit";
21import { destroySession, startSession } from "$lib/server/session.ts";
22+import { type Actions, fail, redirect } from "@sveltejs/kit";
3344export const actions = {
55 logout: async (event) => {
+2-1
src/routes/+page.svelte
···11<script lang="ts">
22- import type { PageProps } from "./$types";
22+ import type { PageProps } from "./$types.d.ts";
33 let { data, form }: PageProps = $props();
4455 let handle = $derived(form?.handle ?? "");
66</script>
7788{#if data.user}
99+ <img alt="avatar" src="/avatar/{data.user.did}" width="50" height="50" />
910 <h2>Hello, {data.user.displayName}!</h2>
1011 <form method="POST" action="?/logout">
1112 <button type="submit">Logout</button>
+22
src/routes/avatar/[did]/+server.ts
···11+import { AppBskyActorGetProfile } from "@atcute/bluesky";
22+import { ok } from "@atcute/client";
33+import { isDid } from "@atcute/lexicons/syntax";
44+import { error } from "@sveltejs/kit";
55+import type { RequestHandler } from "./$types.d.ts";
66+77+export const GET: RequestHandler = async (event) => {
88+ const { params: { did }, locals: { user } } = event;
99+ if (user === undefined || isDid(did) === false) {
1010+ error(404);
1111+ }
1212+ try {
1313+ const profile = await ok(user.client.call(AppBskyActorGetProfile, {
1414+ params: { actor: did },
1515+ }));
1616+ const avatar = new URL(profile.avatar!);
1717+ return event.fetch(avatar);
1818+ } catch (err) {
1919+ console.log(err);
2020+ error(404);
2121+ }
2222+};
+9-9
src/routes/oauth/callback/+server.ts
···11-import type { RequestHandler } from "./$types";
22-import type { OAuthSession } from "@atcute/oauth-node-client";
11+import { dev } from "$app/environment";
22+import { env } from "$env/dynamic/private";
33+import { HANDLE_COOKIE, SESSION_COOKIE } from "$lib/server/constants.ts";
44+import { encryptText } from "$lib/server/crypto.ts";
55+import { createOAuthClient } from "$lib/server/oauth.ts";
66+import type { PublicUserData } from "$lib/valibot.ts";
37import { AppBskyActorGetProfile } from "@atcute/bluesky";
48import { Client, ok } from "@atcute/client";
55-import { redirect } from "@sveltejs/kit";
66-import { createOAuthClient } from "$lib/server/oauth.ts";
77-import { encryptText } from "$lib/server/crypto.ts";
88-import { HANDLE_COOKIE, SESSION_COOKIE } from "$lib/server/constants.ts";
99-import { env } from "$env/dynamic/private";
1010-import { dev } from "$app/environment";
119import { isHandle } from "@atcute/lexicons/syntax";
1212-import type { PublicUserData } from "$lib/valibot.ts";
1010+import type { OAuthSession } from "@atcute/oauth-node-client";
1111+import { redirect } from "@sveltejs/kit";
1212+import type { RequestHandler } from "./$types.d.ts";
13131414export const GET: RequestHandler = async (event) => {
1515 const { url, cookies } = event;