@@ -2,7 +2,6 @@ import type { FastifyContextConfig, FastifyInstance, FastifyRequest, FastifyRepl
22import { generateQRBuffer , generateQRSvg } from '../utils/qr.js' ;
33import type { PlatformLink } from '@devcard/shared' ;
44import { getErrorMessage } from '../utils/error.util.js' ;
5-
65type PublicProfileLink = {
76 id : string ;
87 platform : string ;
@@ -12,7 +11,7 @@ type PublicProfileLink = {
1211 followed ?: boolean ;
1312}
1413
15- type UsernamePublicProfileResponse = {
14+ type UsernamePublicProfileResponse = {
1615 username : string ;
1716 displayName : string ;
1817 bio : string | null ;
@@ -60,6 +59,7 @@ type UsernameCardPublicProfileResponse = {
6059 links : PublicProfileCardLink [ ]
6160}
6261
62+ // Represents a CardLink record with the joined PlatformLink relation
6363interface CardLinkWithPlatform {
6464 id : string ;
6565 displayOrder : number ;
@@ -103,17 +103,20 @@ export async function publicRoutes(app: FastifyInstance) {
103103 } else {
104104 viewerId = decoded ?. id ?? null ;
105105 }
106+ } else {
107+ viewerId = null ; // Unauthenticated viewer
106108 }
107109 } catch {
108110 // Ignored if invalid token
109111 }
110112
111113 // Don't track if the owner is viewing their own profile
112114 if ( ! isSelfView && viewerId !== user . id ) {
115+ // Background view tracking
113116 app . prisma . cardView . create ( {
114117 data : {
115118 ownerId : user . id ,
116- cardId : null ,
119+ cardId : null , // this is a profile view, not a card view
117120 viewerId,
118121 viewerIp : request . ip || null ,
119122 viewerAgent : request . headers [ 'user-agent' ] || null ,
@@ -170,6 +173,7 @@ export async function publicRoutes(app: FastifyInstance) {
170173 }
171174
172175 return response ;
176+
173177 } ) ;
174178
175179 /**
@@ -223,6 +227,7 @@ export async function publicRoutes(app: FastifyInstance) {
223227 }
224228
225229 return response ;
230+
226231 } ) ;
227232
228233 // ─── Public Card View ───
@@ -267,11 +272,11 @@ export async function publicRoutes(app: FastifyInstance) {
267272 let isSelfView = false ;
268273 try {
269274 if ( request . headers . authorization ) {
270- const decoded = await request . jwtVerify ( ) as any ;
275+ const decoded = ( await request . jwtVerify ( ) ) as { id ?: string } ;
271276 if ( decoded ?. id === user . id ) {
272277 isSelfView = true ;
273278 } else {
274- viewerId = decoded . id ;
279+ viewerId = decoded ? .id ?? null ;
275280 }
276281 }
277282 } catch ( e ) {
@@ -291,6 +296,7 @@ export async function publicRoutes(app: FastifyInstance) {
291296 } ) . catch ( ( err : unknown ) => app . log . error ( `Failed to log view: ${ getErrorMessage ( err ) } ` ) ) ;
292297 }
293298
299+
294300 const response : UsernameCardPublicProfileResponse = {
295301 title : card . title ,
296302 owner : {
@@ -319,7 +325,7 @@ export async function publicRoutes(app: FastifyInstance) {
319325 app . get ( '/:username/qr' , {
320326 config : {
321327 rateLimit : {
322- max : 50 ,
328+ max : 50 , // Lower limit for QR generation as it's more resource intensive
323329 timeWindow : '1 minute'
324330 }
325331 } as FastifyContextConfig
@@ -331,6 +337,7 @@ export async function publicRoutes(app: FastifyInstance) {
331337 const format = request . query . format || 'png' ;
332338 const size = parseInt ( request . query . size || '400' , 10 ) ;
333339
340+ // Verify user exists
334341 const user = await app . prisma . user . findUnique ( {
335342 where : { username } ,
336343 } ) ;
@@ -355,4 +362,4 @@ export async function publicRoutes(app: FastifyInstance) {
355362 . header ( 'Content-Disposition' , `inline; filename="devcard-${ username } .png"` )
356363 . send ( png ) ;
357364 } ) ;
358- }
365+ }
0 commit comments