|  | 
|  | 1 | +import { S3Client, ListObjectsV2Command } from '@aws-sdk/client-s3'; | 
|  | 2 | +import { useCallback, useEffect, useState } from 'react'; | 
|  | 3 | + | 
|  | 4 | +import s3Config from 'configs/app/s3'; | 
|  | 5 | + | 
|  | 6 | +export function createS3Client(): S3Client | null { | 
|  | 7 | +  if (!s3Config.region || !s3Config.endpoint || !s3Config.accessKeyId || !s3Config.secretAccessKey) { | 
|  | 8 | +    return null; | 
|  | 9 | +  } | 
|  | 10 | + | 
|  | 11 | +  return new S3Client({ | 
|  | 12 | +    region: s3Config.region, | 
|  | 13 | +    endpoint: s3Config.endpoint, | 
|  | 14 | +    credentials: { | 
|  | 15 | +      accessKeyId: s3Config.accessKeyId, | 
|  | 16 | +      secretAccessKey: s3Config.secretAccessKey, | 
|  | 17 | +    }, | 
|  | 18 | +    forcePathStyle: true, | 
|  | 19 | +  }); | 
|  | 20 | +} | 
|  | 21 | + | 
|  | 22 | +export function useS3DataItems(limit = 25) { | 
|  | 23 | +  const [ items, setItems ] = useState<Array<{ Key?: string; LastModified?: Date }>>([]); | 
|  | 24 | +  const [ isLoading, setIsLoading ] = useState(true); | 
|  | 25 | +  const [ error, setError ] = useState<Error | null>(null); | 
|  | 26 | + | 
|  | 27 | +  const fetchItems = useCallback(async() => { | 
|  | 28 | +    try { | 
|  | 29 | +      setIsLoading(true); | 
|  | 30 | +      const client = createS3Client(); | 
|  | 31 | +      if (!client) { | 
|  | 32 | +        throw new Error('Failed to initialize S3 client'); | 
|  | 33 | +      } | 
|  | 34 | +      const command = new ListObjectsV2Command({ | 
|  | 35 | +        Bucket: 'offchain-dataitems', | 
|  | 36 | +        Prefix: 'dataitems/', | 
|  | 37 | +        MaxKeys: limit, | 
|  | 38 | +      }); | 
|  | 39 | + | 
|  | 40 | +      const response = await client.send(command); | 
|  | 41 | +      if (response.Contents) { | 
|  | 42 | +        // Sort by last modified date, most recent first | 
|  | 43 | +        const sortedItems = response.Contents.sort((a, b) => { | 
|  | 44 | +          return (b.LastModified?.getTime() || 0) - (a.LastModified?.getTime() || 0); | 
|  | 45 | +        }); | 
|  | 46 | +        setItems(sortedItems); | 
|  | 47 | +      } | 
|  | 48 | + | 
|  | 49 | +      setError(null); | 
|  | 50 | +    } catch (err) { | 
|  | 51 | +      setError(err instanceof Error ? err : new Error('Failed to fetch S3 items')); | 
|  | 52 | +    } finally { | 
|  | 53 | +      setIsLoading(false); | 
|  | 54 | +    } | 
|  | 55 | +  }, [ limit ]); | 
|  | 56 | + | 
|  | 57 | +  useEffect(() => { | 
|  | 58 | +    fetchItems(); | 
|  | 59 | +  }, [ fetchItems ]); | 
|  | 60 | + | 
|  | 61 | +  return { | 
|  | 62 | +    items, | 
|  | 63 | +    isLoading, | 
|  | 64 | +    error, | 
|  | 65 | +    refetch: fetchItems, | 
|  | 66 | +  }; | 
|  | 67 | +} | 
0 commit comments