@@ -2120,4 +2120,184 @@ describe("api-key", async () => {
21202120expect ( apiKey ) . not . toBeNull ( ) ;
21212121expect ( apiKey . permissions ) . toEqual ( permissions ) ;
21222122} ) ;
2123+
2124+ it ( "should refill API key credits after refill interval (milliseconds)" , async ( ) => {
2125+ vi . useRealTimers ( ) ;
2126+
2127+ const refillInterval = 3600000 ; // 1 hour in milliseconds
2128+ const refillAmount = 5 ;
2129+ const initialRemaining = 2 ;
2130+
2131+ const apiKey = await auth . api . createApiKey ( {
2132+ body : {
2133+ userId : user . id ,
2134+ remaining : initialRemaining ,
2135+ refillInterval : refillInterval ,
2136+ refillAmount : refillAmount ,
2137+ } ,
2138+ } ) ;
2139+
2140+ // First verification - should reduce remaining to 1
2141+ let result = await auth . api . verifyApiKey ( {
2142+ body : {
2143+ key : apiKey . key ,
2144+ } ,
2145+ } ) ;
2146+ expect ( result . valid ) . toBe ( true ) ;
2147+ expect ( result . key ?. remaining ) . toBe ( initialRemaining - 1 ) ;
2148+
2149+ // Second verification - should reduce remaining to 0
2150+ result = await auth . api . verifyApiKey ( {
2151+ body : {
2152+ key : apiKey . key ,
2153+ } ,
2154+ } ) ;
2155+ expect ( result . valid ) . toBe ( true ) ;
2156+ expect ( result . key ?. remaining ) . toBe ( 0 ) ;
2157+
2158+ // Third verification - should fail due to no remaining credits
2159+ result = await auth . api . verifyApiKey ( {
2160+ body : {
2161+ key : apiKey . key ,
2162+ } ,
2163+ } ) ;
2164+ expect ( result . valid ) . toBe ( false ) ;
2165+ expect ( result . error ?. code ) . toBe ( "USAGE_EXCEEDED" ) ;
2166+
2167+ // Advance time by more than refill interval
2168+ vi . useFakeTimers ( ) ;
2169+ await vi . advanceTimersByTimeAsync ( refillInterval + 1000 ) ;
2170+
2171+ // Fourth verification - should succeed with refilled credits
2172+ result = await auth . api . verifyApiKey ( {
2173+ body : {
2174+ key : apiKey . key ,
2175+ } ,
2176+ } ) ;
2177+ expect ( result . valid ) . toBe ( true ) ;
2178+ expect ( result . key ?. remaining ) . toBe ( refillAmount - 1 ) ;
2179+
2180+ vi . useRealTimers ( ) ;
2181+ } ) ;
2182+
2183+ it ( "should not refill API key credits before refill interval expires" , async ( ) => {
2184+ vi . useRealTimers ( ) ;
2185+
2186+ const refillInterval = 86400000 ; // 24 hours in milliseconds
2187+ const refillAmount = 10 ;
2188+ const initialRemaining = 1 ;
2189+
2190+ const apiKey = await auth . api . createApiKey ( {
2191+ body : {
2192+ userId : user . id ,
2193+ remaining : initialRemaining ,
2194+ refillInterval : refillInterval ,
2195+ refillAmount : refillAmount ,
2196+ } ,
2197+ } ) ;
2198+
2199+ // First verification - should reduce remaining to 0
2200+ let result = await auth . api . verifyApiKey ( {
2201+ body : {
2202+ key : apiKey . key ,
2203+ } ,
2204+ } ) ;
2205+ expect ( result . valid ) . toBe ( true ) ;
2206+ expect ( result . key ?. remaining ) . toBe ( 0 ) ;
2207+
2208+ // Advance time by less than refill interval
2209+ vi . useFakeTimers ( ) ;
2210+ await vi . advanceTimersByTimeAsync ( refillInterval / 2 ) ; // Only advance half the interval
2211+
2212+ // Second verification - should still fail (no refill yet)
2213+ result = await auth . api . verifyApiKey ( {
2214+ body : {
2215+ key : apiKey . key ,
2216+ } ,
2217+ } ) ;
2218+ expect ( result . valid ) . toBe ( false ) ;
2219+ expect ( result . error ?. code ) . toBe ( "USAGE_EXCEEDED" ) ;
2220+
2221+ // Advance time to complete the refill interval
2222+ await vi . advanceTimersByTimeAsync ( refillInterval / 2 + 1000 ) ;
2223+
2224+ // Third verification - should succeed with refilled credits
2225+ result = await auth . api . verifyApiKey ( {
2226+ body : {
2227+ key : apiKey . key ,
2228+ } ,
2229+ } ) ;
2230+ expect ( result . valid ) . toBe ( true ) ;
2231+ expect ( result . key ?. remaining ) . toBe ( refillAmount - 1 ) ;
2232+
2233+ vi . useRealTimers ( ) ;
2234+ } ) ;
2235+
2236+ it ( "should handle multiple refill cycles correctly" , async ( ) => {
2237+ vi . useRealTimers ( ) ;
2238+
2239+ const refillInterval = 3600000 ; // 1 hour in milliseconds
2240+ const refillAmount = 3 ;
2241+
2242+ const apiKey = await auth . api . createApiKey ( {
2243+ body : {
2244+ userId : user . id ,
2245+ remaining : 1 ,
2246+ refillInterval : refillInterval ,
2247+ refillAmount : refillAmount ,
2248+ } ,
2249+ } ) ;
2250+
2251+ // Use the initial credit
2252+ let result = await auth . api . verifyApiKey ( {
2253+ body : {
2254+ key : apiKey . key ,
2255+ } ,
2256+ } ) ;
2257+ expect ( result . valid ) . toBe ( true ) ;
2258+ expect ( result . key ?. remaining ) . toBe ( 0 ) ;
2259+
2260+ vi . useFakeTimers ( ) ;
2261+
2262+ // First refill cycle
2263+ await vi . advanceTimersByTimeAsync ( refillInterval + 1000 ) ;
2264+ result = await auth . api . verifyApiKey ( {
2265+ body : {
2266+ key : apiKey . key ,
2267+ } ,
2268+ } ) ;
2269+ expect ( result . valid ) . toBe ( true ) ;
2270+ expect ( result . key ?. remaining ) . toBe ( refillAmount - 1 ) ;
2271+
2272+ // Use all refilled credits
2273+ for ( let i = 0 ; i < refillAmount - 1 ; i ++ ) {
2274+ result = await auth . api . verifyApiKey ( {
2275+ body : {
2276+ key : apiKey . key ,
2277+ } ,
2278+ } ) ;
2279+ expect ( result . valid ) . toBe ( true ) ;
2280+ }
2281+
2282+ // Should be out of credits now
2283+ result = await auth . api . verifyApiKey ( {
2284+ body : {
2285+ key : apiKey . key ,
2286+ } ,
2287+ } ) ;
2288+ expect ( result . valid ) . toBe ( false ) ;
2289+ expect ( result . error ?. code ) . toBe ( "USAGE_EXCEEDED" ) ;
2290+
2291+ // Second refill cycle
2292+ await vi . advanceTimersByTimeAsync ( refillInterval + 1000 ) ;
2293+ result = await auth . api . verifyApiKey ( {
2294+ body : {
2295+ key : apiKey . key ,
2296+ } ,
2297+ } ) ;
2298+ expect ( result . valid ) . toBe ( true ) ;
2299+ expect ( result . key ?. remaining ) . toBe ( refillAmount - 1 ) ;
2300+
2301+ vi . useRealTimers ( ) ;
2302+ } ) ;
21232303} ) ;
0 commit comments