Skip to content

Commit 991d347

Browse files
committed
feat: latest data items on index
1 parent 81f0b41 commit 991d347

File tree

15 files changed

+1338
-13
lines changed

15 files changed

+1338
-13
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ yarn-error.log*
3535

3636
# local env files
3737
.env*.local
38+
.env
39+
.env.registry
3840
/configs/envs/.env.secrets
3941
/configs/envs/.samples
4042

configs/app/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import chain from './chain';
44
import * as features from './features';
55
import googleCloud from './gcp';
66
import meta from './meta';
7+
import s3 from './s3';
78
import services from './services';
89
import UI from './ui';
910

@@ -16,6 +17,7 @@ const config = Object.freeze({
1617
services,
1718
meta,
1819
googleCloud,
20+
s3,
1921
});
2022

2123
export default config;

configs/app/s3.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { getEnvValue } from './utils';
2+
3+
const s3 = Object.freeze({
4+
region: getEnvValue('NEXT_PUBLIC_S3_REGION'),
5+
endpoint: getEnvValue('NEXT_PUBLIC_S3_ENDPOINT'),
6+
accessKeyId: getEnvValue('NEXT_PUBLIC_S3_ACCESS_KEY_ID'),
7+
secretAccessKey: getEnvValue('NEXT_PUBLIC_S3_SECRET_ACCESS_KEY'),
8+
});
9+
10+
export default s3;

deploy/tools/envs-validator/schema.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,12 @@ const schema = yup
658658
),
659659
}),
660660

661+
// S3 configuration
662+
NEXT_PUBLIC_S3_REGION: yup.string(),
663+
NEXT_PUBLIC_S3_ENDPOINT: yup.string().test(urlTest),
664+
NEXT_PUBLIC_S3_ACCESS_KEY_ID: yup.string(),
665+
NEXT_PUBLIC_S3_SECRET_ACCESS_KEY: yup.string(),
666+
661667
// 6. External services envs
662668
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: yup.string(),
663669
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY: yup.string(),

docs/ENVS.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,17 @@ Please be aware that all environment variables prefixed with `NEXT_PUBLIC_` will
106106

107107
 
108108

109+
## S3 configuration
110+
111+
| Variable | Type| Description | Compulsoriness | Default value | Example value |
112+
| --- | --- | --- | --- | --- | --- |
113+
| NEXT_PUBLIC_S3_REGION | `string` | S3 bucket region | Required | - | `eu-west-2` |
114+
| NEXT_PUBLIC_S3_ENDPOINT | `string` | S3 endpoint URL | Required | - | `https://s3-hb-test.load.rs/[email protected]` |
115+
| NEXT_PUBLIC_S3_ACCESS_KEY_ID | `string` | S3 access key ID | Required | - | `PyzhuEthFmhKM367YiTP` |
116+
| NEXT_PUBLIC_S3_SECRET_ACCESS_KEY | `string` | S3 secret access key | Required | - | `dvfWzw4NgsM9rwjLhMp69ORoVcHmlAm0a7v2kF3j` |
117+
118+
 
119+
109120
## UI configuration
110121

111122
### Homepage

lib/hooks/useS3DataItems.tsx

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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+
}

nextjs/csp/generateCspPolicy.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ function generateCspPolicy() {
1616
descriptors.sentry(),
1717
descriptors.walletConnect(),
1818
descriptors.arweaveIdApi(),
19+
descriptors.s3(),
1920
);
2021

2122
return makePolicyString(policyDescriptor);

nextjs/csp/policies/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ export { safe } from './safe';
1111
export { sentry } from './sentry';
1212
export { walletConnect } from './walletConnect';
1313
export { arweaveIdApi } from './arweaveApi';
14+
export { s3 } from './s3';

nextjs/csp/policies/s3.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import type CspDev from 'csp-dev';
2+
3+
export function s3(): CspDev.DirectiveDescriptor {
4+
return {
5+
'connect-src': [ 'https://s3-hb-test.load.rs' ],
6+
};
7+
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"monitoring:grafana:local": "docker run -d -p 4000:3000 --name=blockscout_grafana --user $(id -u) --volume $(pwd)/grafana:/var/lib/grafana grafana/grafana-enterprise"
3737
},
3838
"dependencies": {
39+
"@aws-sdk/client-s3": "^3.864.0",
3940
"@chakra-ui/react": "2.7.1",
4041
"@chakra-ui/theme-tools": "^2.0.18",
4142
"@emotion/react": "^11.10.4",

0 commit comments

Comments
 (0)