Compare commits

..

2 Commits

Author SHA1 Message Date
873e372bad refactor: update S3StorageAdapter to use publicUrl for object retrieval
Some checks failed
Build and Test / run-test (20.x) (push) Failing after 1m51s
2026-04-16 20:21:22 -03:00
4e61e4bff5 refactor: restructure UpdateArticlePage to use Suspense for loading state 2026-04-16 19:26:23 -03:00
3 changed files with 44 additions and 12 deletions

View File

@@ -4,20 +4,28 @@ import { UUIDv4 } from '@/utils/types/uuid';
import { ArrowLeftIcon } from 'lucide-react';
import Link from 'next/link';
import { notFound } from 'next/navigation';
import { Suspense } from 'react';
interface UpdateArticlePageProps {
params: Promise<{ externalId: string }>;
}
const UpdateArticlePage = async ({ params }: UpdateArticlePageProps) => {
const ArticleFormContent = async ({
params,
}: {
params: Promise<{ externalId: string }>;
}) => {
const { externalId } = await params;
const result = await getArticleByExternalId(externalId as UUIDv4);
if (!result.ok) throw result.error;
const article = result.value;
if (!article) notFound();
return <UpdateArticleForm article={article} />;
};
const UpdateArticlePage = ({ params }: UpdateArticlePageProps) => {
return (
<div className='container mx-auto px-4 py-10 min-h-3/4'>
<div className='mb-6'>
@@ -31,7 +39,9 @@ const UpdateArticlePage = async ({ params }: UpdateArticlePageProps) => {
</div>
<div className='rounded-lg border border-border p-6'>
<h2 className='mb-6 text-2xl font-bold'>Edit Article</h2>
<UpdateArticleForm article={article} />
<Suspense fallback={<div>Loading...</div>}>
<ArticleFormContent params={params} />
</Suspense>
</div>
</div>
);

View File

@@ -1,14 +1,30 @@
import { StorageProvider } from '@/lib/storage/storage.interface';
import { TypedResult, wrap } from '@/utils/types/results';
import {
DeleteObjectCommand,
HeadObjectCommand,
PutObjectCommand,
S3Client,
} from '@aws-sdk/client-s3';
import { DeleteObjectCommand, HeadObjectCommand, PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import { z } from 'zod';
/**
* Configuration for S3 storage adapter
*/
@@ -18,6 +34,7 @@ export const S3StorageConfig = z.object({
region: z.string(),
accessKey: z.string(),
secretKey: z.string(),
publicUrl: z.string().optional(),
});
export type S3StorageConfig = z.infer<typeof S3StorageConfig>;
@@ -27,7 +44,7 @@ export type S3StorageConfig = z.infer<typeof S3StorageConfig>;
*/
export class S3StorageAdapter implements StorageProvider {
private readonly s3Client: S3Client;
private readonly endpoint: string;
private readonly publicUrl: string;
private readonly bucketName: string;
readonly get: (
@@ -44,8 +61,9 @@ export class S3StorageAdapter implements StorageProvider {
) => Promise<TypedResult<void>>;
constructor(config: S3StorageConfig, s3Client?: S3Client) {
this.endpoint = config.endpoint;
this.bucketName = config.bucket;
this.publicUrl = config.publicUrl || config.endpoint;
this.s3Client =
s3Client ||
new S3Client({
@@ -56,6 +74,8 @@ export class S3StorageAdapter implements StorageProvider {
accessKeyId: config.accessKey,
secretAccessKey: config.secretKey,
},
requestChecksumCalculation: 'WHEN_REQUIRED',
responseChecksumValidation: 'WHEN_REQUIRED',
});
this.get = wrap(this._get.bind(this));
@@ -65,7 +85,7 @@ export class S3StorageAdapter implements StorageProvider {
}
private async _get(key: string): Promise<string> {
return `${this.endpoint}/${this.bucketName}/${key}`;
return `${this.publicUrl}/${key}`;
}
private async _put(key: string, contentType: string): Promise<string> {
@@ -109,6 +129,7 @@ export const new_s3_storage_adapter = (): S3StorageAdapter => {
region: process.env.S3_REGION,
accessKey: process.env.S3_ACCESS_KEY,
secretKey: process.env.S3_SECRET_KEY,
publicUrl: process.env.S3_PUBLIC_URL,
});
return new S3StorageAdapter(config);
};

View File

@@ -37,6 +37,7 @@ export const uploadFile = wrap(async (file: File) => {
if (!result.ok) {
throw new Error('File upload failed');
}
console.log(result.value);
const response = await fetch(result.value, {
method: 'PUT',