@@ -70,6 +70,10 @@ const FULL_DETAILS_TTL = 60 * 60 * 2; // 2 hours
7070 * The TTL of the cached descriptions, in seconds. 
7171 */ 
7272const  DESCRIPTIONS_TTL  =  60  *  60  *  24  *  10 ;  // 10 days 
73+ /** 
74+  * The TTL for non-deprecated packages, in seconds 
75+  */ 
76+ const  DEPRECATIONS_TTL  =  60  *  60  *  24  *  2 ;  // 2 days 
7377
7478/** 
7579 * A fetch layer to reach the GitHub API 
@@ -115,6 +119,21 @@ export class GitHubCache {
115119		return  `repo:${ owner } ${ repo } ${ type } ${ strArgs }  ; 
116120	} 
117121
122+ 	/** 
123+ 	 * Generates a Redis key from the passed info. 
124+ 	 * 
125+ 	 * @param  packageName the package name 
126+ 	 * @param  args the optional additional values to append 
127+ 	 * at the end of the key; every element will be interpolated 
128+ 	 * in a string 
129+ 	 * @returns  the pure computed key 
130+ 	 * @private  
131+ 	 */ 
132+ 	#getPackageKey( packageName : string ,  ...args : unknown [ ] )  { 
133+ 		const  strArgs  =  args . map ( a  =>  `:${ a }  ) ; 
134+ 		return  `package:${ packageName } ${ strArgs }  ; 
135+ 	} 
136+ 
118137	/** 
119138	 * An abstraction over general processing that: 
120139	 * 1. tries getting stuff from Redis cache 
@@ -138,7 +157,7 @@ export class GitHubCache {
138157			cacheKey : string , 
139158			promise : ( )  =>  Promise < PromiseType > , 
140159			transformer : ( from : Awaited < PromiseType > )  =>  RType  |  Promise < RType > , 
141- 			ttl : number  |  undefined  =  undefined 
160+ 			ttl : number  |  ( ( value :  RType )   =>   number   |   undefined )   |   undefined  =  undefined 
142161		) : Promise < RType >  =>  { 
143162			const  cachedValue  =  await  this . #redis. json . get < RType > ( cacheKey ) ; 
144163			if  ( cachedValue )  { 
@@ -152,7 +171,14 @@ export class GitHubCache {
152171
153172			await  this . #redis. json . set ( cacheKey ,  "$" ,  newValue ) ; 
154173			if  ( ttl  !==  undefined )  { 
155- 				await  this . #redis. expire ( cacheKey ,  ttl ) ; 
174+ 				if  ( typeof  ttl  ===  "function" )  { 
175+ 					const  ttlResult  =  ttl ( newValue ) ; 
176+ 					if  ( ttlResult  !==  undefined )  { 
177+ 						await  this . #redis. expire ( cacheKey ,  ttlResult ) ; 
178+ 					} 
179+ 				}  else  { 
180+ 					await  this . #redis. expire ( cacheKey ,  ttl ) ; 
181+ 				} 
156182			} 
157183
158184			return  newValue ; 
@@ -537,7 +563,6 @@ export class GitHubCache {
537563	 * @param  repo the GitHub repository name to fetch the 
538564	 * descriptions in 
539565	 * @returns  a map of paths to descriptions. 
540- 	 * @private  
541566	 */ 
542567	async  getDescriptions ( owner : string ,  repo : string )  { 
543568		return  await  this . #processCached< {  [ key : string ] : string  } > ( ) ( 
@@ -586,6 +611,37 @@ export class GitHubCache {
586611			DESCRIPTIONS_TTL 
587612		) ; 
588613	} 
614+ 
615+ 	/** 
616+ 	 * Get the deprecation state of a package from its name. 
617+ 	 * 
618+ 	 * @param  packageName the name of the package to search 
619+ 	 * @returns  the deprecation status message if any, `false` otherwise 
620+ 	 */ 
621+ 	async  getPackageDeprecation ( packageName : string )  { 
622+ 		return  await  this . #processCached< {  value : string  |  false  } > ( ) ( 
623+ 			this . #getPackageKey( packageName ,  "deprecation" ) , 
624+ 			async  ( )  =>  { 
625+ 				try  { 
626+ 					// npmjs.org in a GitHub cache, I know, but hey, let's put that under the fact that 
627+ 					// GitHub owns npmjs.org okay?? 
628+ 					const  res  =  await  fetch ( `https://registry.npmjs.org/${ packageName }  ) ; 
629+ 					if  ( res . status  !==  200 )  return  { } ; 
630+ 					return  ( await  res . json ( ) )  as  {  deprecated ?: boolean  |  string  } ; 
631+ 				}  catch  ( error )  { 
632+ 					console . error ( `Error fetching npmjs.org for package ${ packageName }  ,  error ) ; 
633+ 					return  { } ; 
634+ 				} 
635+ 			} , 
636+ 			( {  deprecated } )  =>  { 
637+ 				if  ( deprecated  ===  undefined )  return  {  value : false  } ; 
638+ 				if  ( typeof  deprecated  ===  "boolean" ) 
639+ 					return  {  value : deprecated  &&  "This package is deprecated"  } ; 
640+ 				return  {  value : deprecated  ||  "This package is deprecated"  } ; 
641+ 			} , 
642+ 			item  =>  ( item . value  ===  false  ? DEPRECATIONS_TTL  : undefined ) 
643+ 		) ; 
644+ 	} 
589645} 
590646
591647export  const  gitHubCache  =  new  GitHubCache ( KV_REST_API_URL ,  KV_REST_API_TOKEN ,  GITHUB_TOKEN ) ; 
0 commit comments