Skip to content

Commit

Permalink
feat: migrate to aws-sdk v3 (#265)
Browse files Browse the repository at this point in the history
* feat: migrate to aws-sdk v3

* feat: updated config

* refactor: little changes
  • Loading branch information
slaveeks authored Jul 3, 2024
1 parent 157992d commit 9433672
Show file tree
Hide file tree
Showing 6 changed files with 1,393 additions and 196 deletions.
1 change: 1 addition & 0 deletions app-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ s3:
accessKeyId: 'secret'
secretAccessKey: 'secret'
endpoint: 'http://localhost:9000'
region: 'my-region'

database:
dsn: 'postgres://codex:postgres@postgres:5432/notes'
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ services:
environment:
MINIO_ROOT_USER: codex
MINIO_ROOT_PASSWORD: minio12345
MINIO_REGION: my-region
command: server --console-address ":9001" /data
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"vitest": "^1.4.0"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.609.0",
"@codex-team/config-loader": "^1.0.0",
"@fastify/cookie": "^8.3.0",
"@fastify/cors": "^8.3.0",
Expand All @@ -48,7 +49,6 @@
"@fastify/swagger-ui": "^1.9.3",
"@testcontainers/postgresql": "^10.2.1",
"arg": "^5.0.2",
"aws-sdk": "^2.1569.0",
"fastify": "^4.17.0",
"http-status-codes": "^2.2.0",
"jsonwebtoken": "^9.0.0",
Expand Down
16 changes: 16 additions & 0 deletions src/infrastructure/utils/streamToBuffer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Readable } from 'stream';
import { Buffer } from 'buffer';

/**
* Convert stream to buffer
* @param stream - stream object
* @returns buffer data made from stream
*/
export const streamToBuffer = (stream: Readable): Promise<Buffer> =>
new Promise((resolve, reject) => {
const chunks: Buffer[] = [];

stream.on('data', (chunk: Buffer) => chunks.push(chunk));
stream.on('error', reject);
stream.on('end', () => resolve(Buffer.concat(chunks)));
});
82 changes: 44 additions & 38 deletions src/repository/storage/s3/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { getLogger } from '@infrastructure/logging/index.js';
import S3 from 'aws-sdk/clients/s3.js';
import type { Buffer } from 'buffer';
import { S3Client, GetObjectCommand, PutObjectCommand, CreateBucketCommand } from '@aws-sdk/client-s3';
import { Buffer } from 'buffer';
import { Readable } from 'stream';
import { streamToBuffer } from '@infrastructure/utils/streamToBuffer.js';
import { isEmpty } from '@infrastructure/utils/empty.js';

const s3StorageLogger = getLogger('s3Storage');

Expand All @@ -11,7 +14,7 @@ export class S3Storage {
/**
* S3 instance
*/
private readonly s3: S3;
private readonly s3: S3Client;

/**
* Constructor for S3Bucket
Expand All @@ -21,10 +24,10 @@ export class S3Storage {
* @param endpoint - AWS endpoint (in case of localstack or other S3 compatible services)
*/
constructor(accessKeyId: string, secretAccessKey: string, region?: string, endpoint?: string) {
this.s3 = new S3({
this.s3 = new S3Client({
endpoint,
region,
s3ForcePathStyle: true,
forcePathStyle: true,
credentials: {
accessKeyId,
secretAccessKey,
Expand All @@ -39,27 +42,22 @@ export class S3Storage {
* @param file - file data to upload
*/
public async uploadFile(bucket: string, key: string, file: Buffer): Promise<string | null> {
/**
* Create an upload manager to upload the file to S3
*/
const uploadManager = this.s3.upload({
Bucket: bucket,
Key: key,
Body: file,
});

/**
* Wait for the upload to complete and return the URL of the uploaded file
*/
try {
const response = await uploadManager.promise();

return response.Location;
/**
* Try to upload file data to s3
*/
await this.s3.send(new PutObjectCommand({
Bucket: bucket,
Key: key,
Body: file,
}))
} catch (error) {
s3StorageLogger.error(error);

return null;
}

return key;
}

/**
Expand All @@ -68,18 +66,24 @@ export class S3Storage {
* @param key - Key of the file in S3
*/
public async getFile(bucket: string, key: string): Promise<Buffer | null> {
const getObjectManager = this.s3.getObject({
Bucket: bucket,
Key: key,
});

try {
const response = await getObjectManager.promise();
const { Body } = await this.s3.send(new GetObjectCommand({
Bucket: bucket,
Key: key,
}));

return response.Body as Buffer;
} catch (error) {
s3StorageLogger.error(error);
/**
* Body must be readable to parse stream
*/
if (!(Body instanceof Readable)) {
s3StorageLogger.error('Expected Body to be a Readable stream');

return null;
}
const fileContent = await streamToBuffer(Body);
return fileContent;
} catch (err) {
s3StorageLogger.error(err);
return null;
}
}
Expand All @@ -89,18 +93,20 @@ export class S3Storage {
* @param name - bucket name
*/
public async createBucket(name: string): Promise<string | null> {
const createBucketManager = this.s3.createBucket({
Bucket: name,
});

try {
const response = await createBucketManager.promise();
const { Location } = await this.s3.send(new CreateBucketCommand({
Bucket: name,
}));

return response.Location as string;
} catch (error) {
s3StorageLogger.error(error);
if (isEmpty(Location)) {
return null;
}

return null;
return Location;
} catch (err) {
s3StorageLogger.error(err);

return null;
}
}
}
Loading

0 comments on commit 9433672

Please sign in to comment.