2022-08-30 14:42:49 +02:00
import {
Integration ,
QueryType ,
IntegrationBase ,
DatasourceFieldType ,
} from "@budibase/types"
2021-06-24 19:16:48 +02:00
2022-10-26 17:44:25 +02:00
const AWS = require ( "aws-sdk" )
const csv = require ( "csvtojson" )
2021-06-24 19:16:48 +02:00
2022-08-12 18:03:06 +02:00
interface S3Config {
region : string
accessKeyId : string
secretAccessKey : string
s3ForcePathStyle : boolean
endpoint? : string
}
2021-06-24 19:16:48 +02:00
2022-10-26 17:44:25 +02:00
const SCHEMA : Integration = {
docs : "https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html" ,
description :
"Amazon Simple Storage Service (Amazon S3) is an object storage service that offers industry-leading scalability, data availability, security, and performance." ,
friendlyName : "Amazon S3" ,
type : "Object store" ,
datasource : {
region : {
type : "string" ,
required : false ,
default : "us-east-1" ,
} ,
accessKeyId : {
type : "password" ,
required : true ,
} ,
secretAccessKey : {
type : "password" ,
required : true ,
2021-06-24 19:16:48 +02:00
} ,
2022-10-26 17:44:25 +02:00
endpoint : {
type : "string" ,
required : false ,
} ,
signatureVersion : {
type : "string" ,
required : false ,
default : "v4" ,
} ,
} ,
query : {
create : {
type : QueryType . FIELDS ,
fields : {
bucket : {
display : "New Bucket" ,
type : DatasourceFieldType . STRING ,
required : true ,
2022-08-30 17:56:56 +02:00
} ,
2022-10-26 17:44:25 +02:00
location : {
required : true ,
default : "us-east-1" ,
type : DatasourceFieldType . STRING ,
} ,
grantFullControl : {
display : "Grant full control" ,
type : DatasourceFieldType . STRING ,
} ,
grantRead : {
display : "Grant read" ,
type : DatasourceFieldType . STRING ,
} ,
grantReadAcp : {
display : "Grant read ACP" ,
type : DatasourceFieldType . STRING ,
} ,
grantWrite : {
display : "Grant write" ,
type : DatasourceFieldType . STRING ,
} ,
grantWriteAcp : {
display : "Grant write ACP" ,
type : DatasourceFieldType . STRING ,
2021-06-24 19:16:48 +02:00
} ,
2022-08-30 14:42:49 +02:00
} ,
2022-10-26 17:44:25 +02:00
} ,
read : {
type : QueryType . FIELDS ,
fields : {
bucket : {
type : DatasourceFieldType . STRING ,
required : true ,
} ,
delimiter : {
type : DatasourceFieldType . STRING ,
} ,
marker : {
type : DatasourceFieldType . STRING ,
} ,
maxKeys : {
type : DatasourceFieldType . NUMBER ,
display : "Max Keys" ,
} ,
prefix : {
type : DatasourceFieldType . STRING ,
2022-08-30 14:42:49 +02:00
} ,
} ,
2022-10-26 17:44:25 +02:00
} ,
readCsv : {
displayName : "Read CSV" ,
type : QueryType . FIELDS ,
2023-03-14 11:06:01 +01:00
readable : true ,
2022-10-26 17:44:25 +02:00
fields : {
bucket : {
type : DatasourceFieldType . STRING ,
required : true ,
} ,
key : {
type : DatasourceFieldType . STRING ,
required : true ,
2022-08-30 20:56:08 +02:00
} ,
2022-08-30 20:56:38 +02:00
} ,
2022-08-30 14:42:49 +02:00
} ,
2022-10-26 17:44:25 +02:00
delete : {
type : QueryType . FIELDS ,
fields : {
bucket : {
type : DatasourceFieldType . STRING ,
required : true ,
} ,
delete : {
type : DatasourceFieldType . JSON ,
required : true ,
2022-08-30 17:56:56 +02:00
} ,
} ,
2022-08-30 20:17:10 +02:00
} ,
2022-10-26 17:44:25 +02:00
} ,
extra : {
acl : {
required : false ,
displayName : "ACL" ,
type : DatasourceFieldType . LIST ,
data : {
create : [
"private" ,
"public-read" ,
"public-read-write" ,
"authenticated-read" ,
] ,
} ,
} ,
} ,
}
2021-06-24 19:16:48 +02:00
2022-08-12 18:03:06 +02:00
class S3Integration implements IntegrationBase {
private readonly config : S3Config
private client : any
2021-06-24 19:16:48 +02:00
2022-08-12 18:03:06 +02:00
constructor ( config : S3Config ) {
this . config = config
if ( this . config . endpoint ) {
this . config . s3ForcePathStyle = true
} else {
delete this . config . endpoint
2021-06-24 19:16:48 +02:00
}
2022-08-12 18:03:06 +02:00
this . client = new AWS . S3 ( this . config )
2021-06-24 19:16:48 +02:00
}
2022-10-26 17:44:25 +02:00
async create ( query : {
bucket : string
location : string
grantFullControl : string
grantRead : string
grantReadAcp : string
grantWrite : string
grantWriteAcp : string
extra : {
acl : string
}
} ) {
let params : any = {
Bucket : query.bucket ,
ACL : query.extra?.acl ,
GrantFullControl : query.grantFullControl ,
GrantRead : query.grantRead ,
GrantReadACP : query.grantReadAcp ,
GrantWrite : query.grantWrite ,
GrantWriteACP : query.grantWriteAcp ,
}
if ( query . location ) {
params [ "CreateBucketConfiguration" ] = {
LocationConstraint : query.location ,
2022-08-30 20:17:10 +02:00
}
2022-08-30 17:56:56 +02:00
}
2022-10-26 17:44:25 +02:00
return await this . client . createBucket ( params ) . promise ( )
}
2022-08-30 17:56:56 +02:00
2022-10-26 17:44:25 +02:00
async read ( query : {
bucket : string
delimiter : string
expectedBucketOwner : string
marker : string
maxKeys : number
prefix : string
} ) {
const response = await this . client
. listObjects ( {
Bucket : query.bucket ,
Delimiter : query.delimiter ,
Marker : query.marker ,
MaxKeys : query.maxKeys ,
Prefix : query.prefix ,
} )
. promise ( )
return response . Contents
}
2022-08-30 14:42:49 +02:00
2022-10-26 17:44:25 +02:00
async readCsv ( query : { bucket : string ; key : string } ) {
const stream = this . client
. getObject ( {
Bucket : query.bucket ,
Key : query.key ,
} )
. createReadStream ( )
2022-08-30 14:42:49 +02:00
2022-10-26 17:44:25 +02:00
let csvError = false
return new Promise ( ( resolve , reject ) = > {
stream . on ( "error" , ( err : Error ) = > {
reject ( err )
} )
const response = csv ( )
. fromStream ( stream )
. on ( "error" , ( ) = > {
csvError = true
2022-08-30 16:18:44 +02:00
} )
2022-10-26 17:44:25 +02:00
stream . on ( "finish" , ( ) = > {
resolve ( response )
2022-08-30 14:55:55 +02:00
} )
2022-10-26 17:44:25 +02:00
} ) . catch ( err = > {
if ( csvError ) {
throw new Error ( "Could not read CSV" )
} else {
throw err
}
} )
}
2022-08-30 20:56:08 +02:00
2022-10-26 17:44:25 +02:00
async delete ( query : { bucket : string ; delete : string } ) {
return await this . client
. deleteObjects ( {
Bucket : query.bucket ,
Delete : JSON.parse ( query . delete ) ,
} )
. promise ( )
2021-06-24 19:16:48 +02:00
}
2022-10-26 17:44:25 +02:00
}
2021-06-24 19:16:48 +02:00
2022-08-12 18:03:06 +02:00
export default {
schema : SCHEMA ,
integration : S3Integration ,
2021-06-24 19:16:48 +02:00
}