Attic is a cozy space with lofty ambitions. attic.social

event type fixes

dbushell.com 070170ae 8fe61dda

verified
+79 -42
+1 -1
src/app.d.ts
··· 1 - import type { PrivateUserData } from "$lib/valibot.ts"; 1 + import type { PrivateUserData } from "$lib/valibot"; 2 2 import type { OAuthClient } from "@atcute/oauth-node-client"; 3 3 4 4 declare global {
+6 -2
src/hooks.server.ts
··· 1 1 import { dev } from "$app/environment"; 2 - import type { Handle } from "@sveltejs/kit"; 2 + import { restoreSession } from "$lib/server/session"; 3 + import { isAuthEvent } from "$lib/types"; 4 + import { error, type Handle } from "@sveltejs/kit"; 3 5 import { sequence } from "@sveltejs/kit/hooks"; 4 - import { restoreSession } from "./lib/server/session.ts"; 5 6 6 7 /** 7 8 * {@link https://svelte.dev/docs/cli/devtools-json} ··· 15 16 }; 16 17 17 18 export const defaultHandle: Handle = async ({ event, resolve }) => { 19 + if (isAuthEvent(event) === false) { 20 + error(500); 21 + } 18 22 // [TODO] necessary? 19 23 // if ( 20 24 // event.url.searchParams.has("session") ||
+4 -9
src/lib/server/oauth.ts
··· 1 1 import { dev } from "$app/environment"; 2 - import type {} from "$lexicons/index.ts"; 3 2 import { 4 3 OAUTH_COOKIE_PREFIX, 5 4 OAUTH_MAX_AGE, 6 5 SESSION_MAX_AGE, 7 - } from "$lib/server/constants.ts"; 8 - import { decryptText, encryptText } from "$lib/server/crypto.ts"; 6 + } from "$lib/server/constants"; 7 + import { decryptText, encryptText } from "$lib/server/crypto"; 8 + import type { AuthEvent } from "$lib/types"; 9 9 import { 10 10 CompositeDidDocumentResolver, 11 11 CompositeHandleResolver, ··· 101 101 } 102 102 } 103 103 104 - export function createOAuthClient( 105 - event: { cookies: Cookies; locals: App.Locals; platform?: App.Platform }, 106 - ): OAuthClient { 107 - if (event.platform === undefined) { 108 - throw new Error(); 109 - } 104 + export function createOAuthClient(event: AuthEvent): OAuthClient { 110 105 if (event.locals.oAuthClient) { 111 106 return event.locals.oAuthClient; 112 107 }
+11 -9
src/lib/server/session.ts
··· 4 4 OAUTH_MAX_AGE, 5 5 SESSION_COOKIE, 6 6 SESSION_MAX_AGE, 7 - } from "$lib/server/constants.ts"; 8 - import { decryptText, encryptText } from "$lib/server/crypto.ts"; 9 - import { createOAuthClient } from "$lib/server/oauth.ts"; 10 - import { parsePublicUser, type PublicUserData } from "$lib/valibot.ts"; 7 + } from "$lib/server/constants"; 8 + import { decryptText, encryptText } from "$lib/server/crypto"; 9 + import { createOAuthClient } from "$lib/server/oauth"; 10 + import type { AuthEvent } from "$lib/types"; 11 + import { parsePublicUser, type PublicUserData } from "$lib/valibot"; 11 12 import { Client } from "@atcute/client"; 12 13 import { isHandle } from "@atcute/lexicons/syntax"; 13 - import type { RequestEvent } from "@sveltejs/kit"; 14 14 15 15 /** 16 16 * Logout 17 17 */ 18 18 export const destroySession = async ( 19 - event: RequestEvent, 19 + event: AuthEvent, 20 20 ): Promise<void> => { 21 21 event.cookies.delete(SESSION_COOKIE, { path: "/" }); 22 22 if (event.locals.user) { ··· 36 36 * @returns {URL} OAuth redirect 37 37 */ 38 38 export const startSession = async ( 39 - event: RequestEvent, 39 + event: AuthEvent, 40 40 handle: string, 41 41 ): Promise<URL> => { 42 42 if (isHandle(handle) === false) { ··· 65 65 * Store the logged in user data 66 66 */ 67 67 export const updateSession = async ( 68 - event: RequestEvent, 68 + event: AuthEvent, 69 69 user: PublicUserData, 70 70 ) => { 71 71 const { cookies, platform } = event; ··· 92 92 /** 93 93 * Setup OAuth client from cookies 94 94 */ 95 - export const restoreSession = async (event: RequestEvent): Promise<void> => { 95 + export const restoreSession = async ( 96 + event: AuthEvent, 97 + ): Promise<void> => { 96 98 const { cookies, platform } = event; 97 99 if (platform?.env === undefined) { 98 100 throw new Error();
+9
src/lib/types.ts
··· 1 + import type { RequestEvent } from "@sveltejs/kit"; 2 + 3 + export type AuthEvent = RequestEvent & { 4 + platform: App.Platform; 5 + }; 6 + 7 + export const isAuthEvent = (event: RequestEvent): event is AuthEvent => { 8 + return event.platform?.env !== undefined; 9 + };
+2 -2
src/routes/+layout.server.ts
··· 1 - import type { PublicUserData } from "$lib/valibot.ts"; 2 - import type { LayoutServerLoad } from "./$types.d.ts"; 1 + import type { PublicUserData } from "$lib/valibot"; 2 + import type { LayoutServerLoad } from "./$types"; 3 3 4 4 export const load: LayoutServerLoad = (event) => { 5 5 let user: PublicUserData | undefined = undefined;
+22 -5
src/routes/+page.server.ts
··· 1 - import { HANDLE_COOKIE } from "$lib/server/constants.ts"; 1 + import { HANDLE_COOKIE } from "$lib/server/constants"; 2 2 import { 3 3 destroySession, 4 4 startSession, 5 5 updateSession, 6 - } from "$lib/server/session.ts"; 6 + } from "$lib/server/session"; 7 + import { isAuthEvent } from "$lib/types"; 8 + import { parseActorProfile } from "$lib/valibot"; 7 9 import { Client } from "@atcute/client"; 8 10 import { type Actions, fail, redirect } from "@sveltejs/kit"; 9 - import { parseActorProfile } from "../lib/valibot.ts"; 10 11 11 12 export const actions = { 12 13 logout: async (event) => { 14 + if (isAuthEvent(event) === false) { 15 + throw new Error(); 16 + } 13 17 await destroySession(event); 14 18 redirect(303, "/"); 15 19 }, 16 20 login: async (event) => { 21 + if (isAuthEvent(event) === false) { 22 + throw new Error(); 23 + } 17 24 const formData = await event.request.formData(); 18 25 const handle = formData.get("handle"); 19 26 let url: URL; ··· 27 34 redirect(303, url); 28 35 }, 29 36 displayName: async (event) => { 30 - if (event.locals.user === undefined) return; 37 + if (isAuthEvent(event) === false) { 38 + throw new Error(); 39 + } 40 + if (event.locals.user === undefined) { 41 + return; 42 + } 31 43 const { user } = event.locals; 32 44 try { 33 45 const formData = await event.request.formData(); ··· 58 70 } 59 71 }, 60 72 purge: async (event) => { 73 + if (isAuthEvent(event) === false) { 74 + throw new Error(); 75 + } 61 76 const { user } = event.locals; 62 - if (user === undefined) return; 77 + if (user === undefined) { 78 + return; 79 + } 63 80 const rpc = new Client({ handler: user.session }); 64 81 const result = await rpc.post("com.atproto.repo.deleteRecord", { 65 82 input: {
+2 -1
src/routes/+page.svelte
··· 5 5 </script> 6 6 7 7 <script lang="ts"> 8 - import type { PageProps } from "./$types.d.ts"; 8 + import type { PageProps } from "./$types"; 9 9 let { data, form }: PageProps = $props(); 10 10 11 11 let handle = $derived(String(form?.handle ?? "")); ··· 179 179 tabindex="-1" 180 180 > 181 181 {#each bskyUsers as user, i (user.did)} 182 + <!-- svelte-ignore a11y_click_events_have_key_events --> 182 183 <li 183 184 class="avatar" 184 185 role="option"
+6 -2
src/routes/.well-known/jwks.json/+server.ts
··· 1 - import { createOAuthClient } from "$lib/server/oauth.ts"; 1 + import { createOAuthClient } from "$lib/server/oauth"; 2 + import { isAuthEvent } from "$lib/types"; 2 3 import { error, json } from "@sveltejs/kit"; 3 - import type { RequestHandler } from "./$types.d.ts"; 4 + import type { RequestHandler } from "./$types"; 4 5 5 6 export const GET: RequestHandler = (event) => { 6 7 try { 8 + if (isAuthEvent(event) === false) { 9 + throw new Error(); 10 + } 7 11 const oAuthClient = createOAuthClient(event); 8 12 return json(oAuthClient.jwks ?? { keys: [] }); 9 13 } catch {
+1 -1
src/routes/avatar/[did]/+server.ts
··· 2 2 import { ok } from "@atcute/client"; 3 3 import { isDid } from "@atcute/lexicons/syntax"; 4 4 import { error } from "@sveltejs/kit"; 5 - import type { RequestHandler } from "./$types.d.ts"; 5 + import type { RequestHandler } from "./$types"; 6 6 7 7 export const GET: RequestHandler = async (event) => { 8 8 const { params: { did }, locals: { user } } = event;
+1 -1
src/routes/favicon.ico/+server.ts
··· 1 1 import { error } from "@sveltejs/kit"; 2 - import type { RequestHandler } from "./$types.d.ts"; 2 + import type { RequestHandler } from "./$types"; 3 3 4 4 export const GET: RequestHandler = async (event) => { 5 5 if (event.platform === undefined) {
+6 -2
src/routes/oauth-client-metadata.json/+server.ts
··· 1 - import { createOAuthClient } from "$lib/server/oauth.ts"; 1 + import { createOAuthClient } from "$lib/server/oauth"; 2 + import { isAuthEvent } from "$lib/types"; 2 3 import { error, json } from "@sveltejs/kit"; 3 - import type { RequestHandler } from "./$types.d.ts"; 4 + import type { RequestHandler } from "./$types"; 4 5 5 6 export const GET: RequestHandler = (event) => { 6 7 try { 8 + if (isAuthEvent(event) === false) { 9 + throw new Error(); 10 + } 7 11 const oAuthClient = createOAuthClient(event); 8 12 return json(oAuthClient.metadata); 9 13 } catch {
+8 -7
src/routes/oauth/callback/+server.ts
··· 1 - import { HANDLE_COOKIE } from "$lib/server/constants.ts"; 2 - import { createOAuthClient } from "$lib/server/oauth.ts"; 3 - import { parseActorProfile, type PublicUserData } from "$lib/valibot.ts"; 1 + import { HANDLE_COOKIE } from "$lib/server/constants"; 2 + import { createOAuthClient } from "$lib/server/oauth"; 3 + import { updateSession } from "$lib/server/session"; 4 + import { isAuthEvent } from "$lib/types"; 5 + import { parseActorProfile, type PublicUserData } from "$lib/valibot"; 4 6 import { AppBskyActorGetProfile } from "@atcute/bluesky"; 5 7 import { Client, ok } from "@atcute/client"; 6 8 import { isHandle } from "@atcute/lexicons/syntax"; 7 9 import type { OAuthSession } from "@atcute/oauth-node-client"; 8 10 import { redirect } from "@sveltejs/kit"; 9 - import { updateSession } from "../../../lib/server/session.ts"; 10 - import type { RequestHandler } from "./$types.d.ts"; 11 + import type { RequestHandler } from "./$types"; 11 12 12 13 export const GET: RequestHandler = async (event) => { 13 - const { cookies, platform, url } = event; 14 - if (platform?.env === undefined) { 14 + if (isAuthEvent(event) === false) { 15 15 throw new Error(); 16 16 } 17 + const { cookies, url } = event; 17 18 18 19 const handle = cookies.get(HANDLE_COOKIE); 19 20 if (isHandle(handle) === false) {