add delete and upload functions

This commit is contained in:
Nils Knappmeier
2023-08-05 13:57:00 +02:00
parent ab920cc1ce
commit 1c75903eaf
10 changed files with 149 additions and 46 deletions
@@ -0,0 +1,23 @@
const { S3Client } = require('@aws-sdk/client-s3');
function requiredEnvVar(name) {
if (!process.env[name]) {
throw new Error(`Environment variable "${name}" is required.`);
}
return process.env[name];
}
function createS3Client() {
// https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-environment.html
requiredEnvVar('AWS_ACCESS_KEY_ID');
requiredEnvVar('AWS_SECRET_ACCESS_KEY');
return {
bucket: requiredEnvVar('S3_BUCKET_NAME'),
s3Client: new S3Client({
region: 'us-east-1'
})
};
}
module.exports = { createS3Client };
+13
View File
@@ -0,0 +1,13 @@
const { createS3Client } = require('./createS3Client');
const { DeleteObjectCommand } = require('@aws-sdk/client-s3');
async function deleteFile(name) {
const { s3Client, bucket } = createS3Client();
const command = new DeleteObjectCommand({
Bucket: bucket,
Key: name
});
await s3Client.send(command);
}
module.exports = { deleteFile };
+4 -2
View File
@@ -1,3 +1,5 @@
const { listBucketFiles } = require('./list-bucket-files');
const { listFiles } = require('./listFiles');
const { uploadFile } = require('./uploadFile');
const { deleteFile } = require('./deleteFile');
module.exports = { listBucketFiles };
module.exports = { listFiles, uploadFile, deleteFile };
@@ -1,35 +0,0 @@
const { S3Client, ListObjectsV2Command } = require('@aws-sdk/client-s3');
const bucket = process.env.S3_BUCKET_NAME;
if (!process.env.AWS_ACCESS_KEY_ID || !process.env.AWS_SECRET_ACCESS_KEY) {
// https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-environment.html
throw new Error(
'AWS credentials must be present in environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY'
);
}
const client = new S3Client({
region: 'us-east-1'
});
async function listBucketFiles() {
const command = new ListObjectsV2Command({
Bucket: bucket
});
let isTruncated = true;
const files = [];
while (isTruncated) {
const { Contents, IsTruncated, NextContinuationToken } = await client.send(
command
);
files.push(...Contents.map(s3obj => s3obj.Key));
isTruncated = IsTruncated;
command.input.ContinuationToken = NextContinuationToken;
}
return files
}
module.exports = { listBucketFiles}
+26
View File
@@ -0,0 +1,26 @@
const { ListObjectsV2Command } = require('@aws-sdk/client-s3');
const { createS3Client } = require('./createS3Client');
async function listFiles() {
const { s3Client, bucket } = createS3Client();
const command = new ListObjectsV2Command({
Bucket: bucket
});
let isTruncated = true;
const files = [];
while (isTruncated) {
const {
Contents,
IsTruncated,
NextContinuationToken
} = await s3Client.send(command);
files.push(...Contents.map(s3obj => s3obj.Key));
isTruncated = IsTruncated;
command.input.ContinuationToken = NextContinuationToken;
}
return files;
}
module.exports = { listFiles };
+65
View File
@@ -0,0 +1,65 @@
/* eslint-disable no-console */
const { listFiles, uploadFile, deleteFile } = require('./index');
const crypto = require('crypto');
const uuid = crypto.randomUUID();
const BUCKET_BASE_URL = `https://s3.amazonaws.com/${process.env.S3_BUCKET_NAME}`;
async function run() {
const filename = `test-file-${uuid}`;
console.log(`Starting test with target file "${filename}"`);
console.log(`Uploading "${filename}"`);
await uploadFile('package.json', filename);
console.log(`Check if uploaded "${filename}"`);
const listing = await listFiles();
if (!listing.includes(filename)) {
throw new Error(`File "${filename}" has not been uploaded`);
}
console.log(`Check contents of "${filename}"`);
const uploadedContents = await (
await fetch(BUCKET_BASE_URL + '/' + filename)
).text();
expectStringContains('"name": "handlebars"', uploadedContents);
console.log(`Delete "${filename}"`);
await deleteFile(filename);
console.log(`Check if deleted "${filename}"`);
const listingAfterDelete = await listFiles();
if (listingAfterDelete.includes(filename)) {
throw new Error(`File "${filename}" has not been deleted`);
}
}
run()
.finally(logTestFilesInBucket)
.catch(error => {
console.error(error);
process.exit(1);
});
function expectStringContains(needle, haystack) {
if (!haystack.includes(needle)) {
throw new Error(`Expecting to find "${needle}" in string "${haystack}"`);
}
}
async function logTestFilesInBucket() {
const listing = await listFiles();
const testFilesInBucket = listing.filter(name =>
name.startsWith('test-file-')
);
for (const filename of testFilesInBucket) {
console.log(`Detected surplus file "${filename}"`);
if (process.argv[2] === '--delete-surplus') {
await deleteFile(filename);
} else {
console.log(`run with --delete-surplus to delete it`);
}
}
console.log('DONE');
}
-7
View File
@@ -1,7 +0,0 @@
const { listBucketFiles } = require('./index');
const main = async () => {
console.log(await listBucketFiles());
};
main().catch(console.error);
+16
View File
@@ -0,0 +1,16 @@
const { createS3Client } = require('./createS3Client');
const { PutObjectCommand } = require('@aws-sdk/client-s3');
const fs = require('node:fs/promises');
async function uploadFile(localName, targetName) {
const { s3Client, bucket } = createS3Client();
const fileContents = await fs.readFile(localName);
const command = new PutObjectCommand({
Bucket: bucket,
Key: targetName,
Body: fileContents
});
await s3Client.send(command);
}
module.exports = { uploadFile };
@@ -3,7 +3,7 @@ const fs = require('fs');
const testFiles = fs.readdirSync('src');
const entryPoints = {};
testFiles
.filter(file => file.match(/-test.js$/))
.filter(file => file.match(/-cli.js$/))
.forEach(file => {
entryPoints[file] = `./src/${file}`;
});
@@ -3,7 +3,7 @@ const fs = require('fs');
const testFiles = fs.readdirSync('src');
const entryPoints = {};
testFiles
.filter(file => file.match(/-test.js$/))
.filter(file => file.match(/-cli.js$/))
.forEach(file => {
entryPoints[file] = `./src/${file}`;
});