@graperank/storage-s3
Version:
The S3 Storage plugin provides GrapeRank the means to store and retrieve scorecards from any S3 compatible simple storage service.
169 lines (168 loc) • 6.91 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.s3Api = void 0;
// Adapted apiS3.ts from nostrmeet.me
// FIXME env depends on being run inside svelte
const client_s3_1 = require("@aws-sdk/client-s3");
class s3Api {
bucket;
client;
constructor(config) {
if (!config)
throw ('GrapeRank : Storage : missing config required for s3 client');
let clientconfig = {
forcePathStyle: false, // Configures to use subdomain/virtual calling format.
region: config.region, // Must be "us-east-1" when creating new Spaces. Otherwise, use the region in your endpoint (for example, nyc3).
endpoint: config.endpoint, // Find your endpoint in the control panel, under Settings. Prepend "https://".
credentials: {
accessKeyId: config.key, // Access key pair. You can create access key pairs using the control panel or API.
secretAccessKey: config.secret // Secret access key defined through an environment variable.
}
};
this.client = new client_s3_1.S3Client(clientconfig);
if (!config.bucket)
throw ('missing bucket required for s3 client');
this.bucket = config.bucket;
}
async send(op, objectinput) {
let data;
let path;
try {
// let command : GetObjectCommand | PutObjectCommand | ListObjectsCommand;
switch (op) {
case 'get':
if ("Key" in objectinput)
path = objectinput.Key;
data = await this.client.send(new client_s3_1.GetObjectCommand(objectinput));
break;
case 'put':
if ("Key" in objectinput && "Body" in objectinput)
path = objectinput.Key;
data = await this.client.send(new client_s3_1.PutObjectCommand(objectinput));
break;
case 'list':
if ("Marker" in objectinput || "Prefix" in objectinput)
path = "Marker" in objectinput ? objectinput.Marker : objectinput.Prefix;
data = await this.client.send(new client_s3_1.ListObjectsCommand(objectinput));
break;
default: throw ('invalid command requested');
}
if (!data)
throw ('no data returned');
console.log("Success s3.send('" + op + "') to : " + path);
// console.log("s3.send() response : ", data);
}
catch (err) {
console.log("WARNING s3.send('" + op + "') request failed: ", path, err);
// console.log("s3.send('"+op+"') input : ", objectinput);
// console.log("s3.send('"+op+"') response : ", data);
// throw('s3.send() request failed');
}
return data;
}
async get(Key) {
try {
// if(!this.bucket) throw('s3 Bucket not specified')
let input = { Bucket: this.bucket, Key };
// console.log('s3.get('+type+','+userid+','+objid+') calling s3.send() : ',input);
return await this.send('get', input).then(async (output) => {
let getoutput = output;
if (!getoutput)
throw ('not found');
console.log('s3.get() output recieved from s3.send()');
return JSON.parse(await getoutput?.Body?.transformToString()); //Api.verify(JSON.parse(apievent));
});
}
catch (e) {
console.log('unable to get data from storage : ', Key, e);
return undefined;
}
}
// validate data BEFORE sending to s3.put()
async put(Key, data, overwrite = false) {
let input;
try {
if (!this.bucket)
throw ('s3 Bucket not specified');
// confirm allowed overwrite
if (!overwrite) {
let existing = await this.get(Key).then(data => {
try {
return data === undefined ? false : true;
}
catch {
return false;
}
});
if (existing)
throw ('overwrite is not permitted');
}
// send to storage
input = {
Bucket: this.bucket, Key,
Body: JSON.stringify(data),
ACL: "private",
Metadata: {}
};
// console.log('s3.put() recieved apievent : ',apievent);
// console.log('s3,put() passing command input to s3.send() : ',input);
return await this.send('put', input).then(() => true).catch(() => false);
}
catch (e) {
console.log('unable to put data to storage : ', Key, e);
// console.log('InputObject : ',input)
return false;
}
}
/**
* Returns S3FileList
* containing a`filenames` array of items found.
* if `nextKey` is a string, use its value to get more items
* @param type
* @param userid
* @returns s3ListObjectOutput {IsTruncated : boolean, Keys : string[]}
*/
async list(Key) {
let input;
let output;
try {
if (!this.bucket)
throw ('s3 Bucket not specified');
if (!Key.endsWith('/'))
Key = Key + '/';
let filenames = [];
input = {
Bucket: this.bucket,
Marker: Key,
Prefix: Key,
};
output = await this.send('list', input).then(s3 => {
let s3output = s3;
if (!s3output)
throw ('not found');
if (!s3output.Contents)
throw ('no list content');
let objid, next;
console.log('s3.list() found ', s3output.Contents.length, ' files matching :', Key);
s3output.Contents.forEach((obj) => {
if ("Key" in obj && typeof (obj.Key) == 'string') {
// console.log('s3.list() file : ', obj.Key);
objid = obj.Key.replace(Key, '').replace('.json', '');
filenames.push(objid);
if (!s3output?.IsTruncated)
next = objid;
}
});
return { next, list: filenames };
});
return output;
}
catch (e) {
// log details to server
console.log('unable to list data in storage : ', Key, e);
// console.log('InputObject : ',input)
return undefined;
}
}
}
exports.s3Api = s3Api;