@@ -12,19 +12,35 @@ export type PackageLikes = {
1212 userHasLiked : boolean
1313}
1414
15+ //Cache keys and helpers
1516const CACHE_PREFIX = 'atproto-likes:'
1617const CACHE_PACKAGE_TOTAL_KEY = ( packageName : string ) => `${ CACHE_PREFIX } :${ packageName } :total`
1718const CACHE_USER_LIKES_KEY = ( packageName : string , did : string ) =>
18- `${ CACHE_PREFIX } ${ packageName } :users:${ did } `
19+ `${ CACHE_PREFIX } ${ packageName } :users:${ did } :liked`
20+ const CACHE_USERS_BACK_LINK = ( packageName : string , did : string ) =>
21+ `${ CACHE_PREFIX } ${ packageName } :users:${ did } :backlink`
1922
2023const CACHE_MAX_AGE = CACHE_MAX_AGE_ONE_MINUTE * 5
2124
25+ /**
26+ * Logic to handle liking, unliking, and seeing if a user has liked a package on npmx
27+ */
2228export class PackageLikesUtils {
2329 private readonly constellation : Constellation
2430 private readonly cache : CacheAdapter
2531
26- constructor ( cachedFunction : CachedFetchFunction ) {
27- this . constellation = new Constellation ( cachedFunction )
32+ constructor ( ) {
33+ this . constellation = new Constellation (
34+ // Passes in a fetch wrapped as cachedfetch since are already doing some heavy caching here
35+ async < T = unknown > (
36+ url : string ,
37+ options : Parameters < typeof $fetch > [ 1 ] = { } ,
38+ _ttl ?: number ,
39+ ) : Promise < CachedFetchResult < T > > => {
40+ const data = ( await $fetch < T > ( url , options ) ) as T
41+ return { data, isStale : false , cachedAt : null }
42+ } ,
43+ )
2844 this . cache = getCacheAdatper ( CACHE_PREFIX )
2945 }
3046
@@ -34,7 +50,6 @@ export class PackageLikesUtils {
3450 * @returns
3551 */
3652 private async constellationLikes ( subjectRef : string ) {
37- // TODO: I need to see what failed fetch calls do here
3853 const { data : totalLinks } = await this . constellation . getLinksDistinctDids (
3954 subjectRef ,
4055 likeNsid ,
@@ -65,7 +80,6 @@ export class PackageLikesUtils {
6580 [ [ usersDid ] ] ,
6681 0 ,
6782 )
68- //TODO: need to double check this logic
6983 return userLikes . total > 0
7084 }
7185
@@ -135,18 +149,34 @@ export class PackageLikesUtils {
135149 * to the user's atproto repostiory
136150 * @param packageName
137151 * @param usersDid
152+ * @param atUri - The URI of the like record
138153 */
139- async likeAPackageAndRetunLikes ( packageName : string , usersDid : string ) : Promise < PackageLikes > {
154+ async likeAPackageAndRetunLikes (
155+ packageName : string ,
156+ usersDid : string ,
157+ atUri : string ,
158+ ) : Promise < PackageLikes > {
140159 const totalLikesKey = CACHE_PACKAGE_TOTAL_KEY ( packageName )
141160 const subjectRef = PACKAGE_SUBJECT_REF ( packageName )
142161
162+ const splitAtUri = atUri . replace ( 'at://' , '' ) . split ( '/' )
163+ const backLink = {
164+ did : usersDid ,
165+ collection : splitAtUri [ 1 ] ,
166+ rkey : splitAtUri [ 2 ] ,
167+ } as Backlink
168+
169+ // We store the backlink incase a user is liking and unlikign rapidly. constellation takes a few seconds to capture the backlink
170+ const usersBackLinkKey = CACHE_USERS_BACK_LINK ( packageName , usersDid )
171+ await this . cache . set ( usersBackLinkKey , backLink , CACHE_MAX_AGE )
172+
143173 let totalLikes = await this . cache . get < number > ( totalLikesKey )
144174 if ( ! totalLikes ) {
145175 totalLikes = await this . constellationLikes ( subjectRef )
146176 totalLikes = totalLikes + 1
147177 await this . cache . set ( totalLikesKey , totalLikes , CACHE_MAX_AGE )
148178 }
149- // We already know the user has not liked the package so set in the cache
179+ // We already know the user has not liked the package before so set in the cache
150180 await this . cache . set ( CACHE_USER_LIKES_KEY ( packageName , usersDid ) , true , CACHE_MAX_AGE )
151181 return {
152182 totalLikes : totalLikes ,
@@ -164,6 +194,12 @@ export class PackageLikesUtils {
164194 packageName : string ,
165195 usersDid : string ,
166196 ) : Promise < Backlink | undefined > {
197+ const usersBackLinkKey = CACHE_USERS_BACK_LINK ( packageName , usersDid )
198+ const backLink = await this . cache . get < Backlink > ( usersBackLinkKey )
199+ if ( backLink ) {
200+ return backLink
201+ }
202+
167203 const subjectRef = PACKAGE_SUBJECT_REF ( packageName )
168204 const { data : userLikes } = await this . constellation . getBackLinks (
169205 subjectRef ,
@@ -198,7 +234,10 @@ export class PackageLikesUtils {
198234 totalLikes = totalLikes - 1
199235 await this . cache . set ( totalLikesKey , totalLikes , CACHE_MAX_AGE )
200236
237+ //Clean up
201238 await this . cache . delete ( CACHE_USER_LIKES_KEY ( packageName , usersDid ) )
239+ await this . cache . delete ( CACHE_USERS_BACK_LINK ( packageName , usersDid ) )
240+
202241 return {
203242 totalLikes : totalLikes ,
204243 userHasLiked : false ,
0 commit comments