@@ -63,6 +63,8 @@ export async function loader({ context }: Route.LoaderArgs) {
6363 year : 'numeric' ,
6464 month : 'short' ,
6565 day : 'numeric' ,
66+ hour : '2-digit' ,
67+ minute : '2-digit' ,
6668 } ) ,
6769 }
6870 } ) ,
@@ -76,7 +78,37 @@ export async function loader({ context }: Route.LoaderArgs) {
7678 return { ...user , entries : validEntries , tags : validTags }
7779 } ) ,
7880 )
79- return { users : usersWithTheirData }
81+
82+ // Get KV data
83+ const { cloudflare } = context
84+ const { env } = cloudflare
85+ const kvList = await env . OAUTH_KV . list ( )
86+
87+ // Get all KV entries with their data
88+ const kvEntries = await Promise . all (
89+ kvList . keys . map ( async ( key ) => {
90+ try {
91+ const value = await env . OAUTH_KV . get ( key . name , { type : 'json' } )
92+ return {
93+ key : key . name ,
94+ value : value ,
95+ expiration : key . expiration ,
96+ metadata : key . metadata ,
97+ }
98+ } catch {
99+ // If JSON parsing fails, try to get as text
100+ const value = await env . OAUTH_KV . get ( key . name , { type : 'text' } )
101+ return {
102+ key : key . name ,
103+ value : value ,
104+ expiration : key . expiration ,
105+ metadata : key . metadata ,
106+ }
107+ }
108+ } ) ,
109+ )
110+
111+ return { users : usersWithTheirData , kvEntries }
80112}
81113
82114export async function action ( { request, context } : Route . ActionArgs ) {
@@ -125,7 +157,7 @@ export async function action({ request, context }: Route.ActionArgs) {
125157}
126158
127159export default function Home ( { loaderData } : Route . ComponentProps ) {
128- const { users } = loaderData
160+ const { users, kvEntries } = loaderData
129161
130162 return (
131163 < div className = "min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 p-8 dark:from-gray-900 dark:to-gray-800" >
@@ -247,9 +279,14 @@ export default function Home({ loaderData }: Route.ComponentProps) {
247279 key = { tag . id }
248280 className = "flex items-center justify-between rounded-lg border border-gray-200 bg-gray-50 px-3 py-2 dark:border-gray-700 dark:bg-gray-700"
249281 >
250- < span className = "inline-flex items-center rounded-full bg-blue-100 px-2 py-1 text-xs font-medium text-blue-800 dark:bg-blue-900 dark:text-blue-200" >
251- { tag . name }
252- </ span >
282+ < div className = "flex items-center gap-3" >
283+ < span className = "text-xs text-gray-500 dark:text-gray-400" >
284+ ID: { tag . id }
285+ </ span >
286+ < span className = "inline-flex items-center rounded-full bg-blue-100 px-2 py-1 text-xs font-medium text-blue-800 dark:bg-blue-900 dark:text-blue-200" >
287+ { tag . name }
288+ </ span >
289+ </ div >
253290 < span className = "flex items-center gap-1 text-xs text-gray-500 dark:text-gray-400" >
254291 < svg
255292 className = "h-3 w-3"
@@ -278,6 +315,95 @@ export default function Home({ loaderData }: Route.ComponentProps) {
278315
279316 < hr className = "my-6" />
280317
318+ < section >
319+ < h2 className = "mb-6 text-2xl font-bold text-gray-900 dark:text-white" >
320+ KV Store Entries ({ kvEntries . length } )
321+ </ h2 >
322+ { kvEntries . length > 0 ? (
323+ < div className = "grid gap-6" >
324+ { kvEntries . map ( ( kvEntry ) => (
325+ < div
326+ key = { kvEntry . key }
327+ className = "rounded-lg border border-gray-200 bg-white p-6 shadow-lg dark:border-gray-700 dark:bg-gray-800 dark:shadow-gray-900/50"
328+ >
329+ < div className = "mb-4 flex items-center justify-between" >
330+ < h3 className = "text-lg font-semibold text-gray-900 dark:text-white" >
331+ { kvEntry . key }
332+ </ h3 >
333+ < span className = "rounded-full bg-blue-100 px-2 py-1 text-xs font-medium text-blue-800 dark:bg-blue-900 dark:text-blue-200" >
334+ KV Entry
335+ </ span >
336+ </ div >
337+
338+ < div className = "space-y-3" >
339+ < div >
340+ < h4 className = "text-sm font-medium text-gray-600 dark:text-gray-400" >
341+ Value
342+ </ h4 >
343+ < pre className = "mt-1 rounded bg-gray-100 p-3 text-sm dark:bg-gray-700" >
344+ { JSON . stringify ( kvEntry . value , null , 2 ) }
345+ </ pre >
346+ </ div >
347+
348+ < div className = "grid grid-cols-2 gap-4 text-sm" >
349+ < div >
350+ < span className = "font-medium text-gray-600 dark:text-gray-400" >
351+ Expiration:
352+ </ span >
353+ < span className = "ml-2 text-gray-900 dark:text-white" >
354+ { kvEntry . expiration
355+ ? new Date (
356+ kvEntry . expiration * 1000 ,
357+ ) . toLocaleDateString ( 'en-US' , {
358+ year : 'numeric' ,
359+ month : 'short' ,
360+ day : 'numeric' ,
361+ hour : '2-digit' ,
362+ minute : '2-digit' ,
363+ } )
364+ : 'Never' }
365+ </ span >
366+ </ div >
367+
368+ { kvEntry . metadata && (
369+ < div >
370+ < span className = "font-medium text-gray-600 dark:text-gray-400" >
371+ Metadata:
372+ </ span >
373+ < span className = "ml-2 text-gray-900 dark:text-white" >
374+ { JSON . stringify ( kvEntry . metadata ) }
375+ </ span >
376+ </ div >
377+ ) }
378+ </ div >
379+ </ div >
380+ </ div >
381+ ) ) }
382+ </ div >
383+ ) : (
384+ < div className = "rounded-lg border-2 border-dashed border-gray-300 p-8 text-center dark:border-gray-600" >
385+ < svg
386+ className = "mx-auto h-12 w-12 text-gray-400 dark:text-gray-500"
387+ fill = "none"
388+ stroke = "currentColor"
389+ viewBox = "0 0 24 24"
390+ >
391+ < path
392+ strokeLinecap = "round"
393+ strokeLinejoin = "round"
394+ strokeWidth = { 2 }
395+ d = "M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4"
396+ />
397+ </ svg >
398+ < p className = "mt-2 text-sm text-gray-500 dark:text-gray-400" >
399+ No KV entries found
400+ </ p >
401+ </ div >
402+ ) }
403+ </ section >
404+
405+ < hr className = "my-6" />
406+
281407 < section >
282408 < h2 className = "mb-6 text-2xl font-bold text-gray-900 dark:text-white" >
283409 Database Reset
0 commit comments