2022-08-30 14:42:49 +02:00
import {
Integration ,
QueryType ,
IntegrationBase ,
DatasourceFieldType ,
} from "@budibase/types"
2021-06-24 19:16:48 +02:00
module S3Module {
const AWS = require ( "aws-sdk" )
2022-08-30 14:42:49 +02:00
const csv = require ( "csvtojson" )
2021-06-24 19:16:48 +02:00
interface S3Config {
2021-06-24 19:17:26 +02:00
region : string
accessKeyId : string
secretAccessKey : string
2021-12-31 17:15:49 +01:00
s3ForcePathStyle : boolean
endpoint? : string
2021-06-24 19:16:48 +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" ,
2022-06-23 12:35:57 +02:00
type : "Object store" ,
2021-06-24 19:16:48 +02:00
datasource : {
region : {
type : "string" ,
2021-12-31 17:15:49 +01:00
required : false ,
2021-06-24 19:16:48 +02:00
default : "us-east-1" ,
} ,
accessKeyId : {
type : "password" ,
required : true ,
} ,
secretAccessKey : {
type : "password" ,
required : true ,
} ,
2021-12-30 18:44:27 +01:00
endpoint : {
type : "string" ,
required : false ,
} ,
signatureVersion : {
type : "string" ,
required : false ,
2022-01-13 18:24:52 +01:00
default : "v4" ,
2021-12-30 18:44:27 +01:00
} ,
2021-06-24 19:16:48 +02:00
} ,
query : {
2022-08-30 17:56:56 +02:00
create : {
type : QueryType . FIELDS ,
fields : {
bucket : {
display : "New Bucket" ,
type : DatasourceFieldType . STRING ,
required : true ,
} ,
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
read : {
2022-08-11 14:50:05 +02:00
type : QueryType . FIELDS ,
2021-06-24 19:16:48 +02:00
fields : {
bucket : {
2022-08-30 12:17:11 +02:00
type : DatasourceFieldType . STRING ,
2021-06-24 19:16:48 +02:00
required : true ,
} ,
2022-08-30 12:17:11 +02:00
delimiter : {
type : DatasourceFieldType . STRING ,
} ,
marker : {
type : DatasourceFieldType . STRING ,
} ,
maxKeys : {
type : DatasourceFieldType . NUMBER ,
display : "Max Keys" ,
} ,
prefix : {
type : DatasourceFieldType . STRING ,
} ,
2021-06-24 19:16:48 +02:00
} ,
2022-08-30 14:42:49 +02:00
} ,
readCsv : {
displayName : "Read CSV" ,
type : QueryType . FIELDS ,
fields : {
bucket : {
type : DatasourceFieldType . STRING ,
required : true ,
} ,
key : {
type : DatasourceFieldType . STRING ,
required : true ,
} ,
} ,
} ,
2022-08-30 20:56:08 +02:00
delete : {
type : QueryType . FIELDS ,
fields : {
bucket : {
type : DatasourceFieldType . STRING ,
required : true ,
} ,
delete : {
type : DatasourceFieldType . JSON ,
required : true ,
} ,
} ,
}
2022-08-30 14:42:49 +02:00
} ,
2022-08-30 17:56:56 +02:00
extra : {
acl : {
required : false ,
displayName : "ACL" ,
type : DatasourceFieldType . LIST ,
data : {
create : [
"private" ,
"public-read" ,
"public-read-write" ,
"authenticated-read" ,
] ,
} ,
} ,
2022-08-30 20:17:10 +02:00
} ,
2021-06-24 19:16:48 +02:00
}
2021-11-10 20:35:09 +01:00
class S3Integration implements IntegrationBase {
2021-06-24 19:16:48 +02:00
private readonly config : S3Config
private client : any
constructor ( config : S3Config ) {
this . config = config
2021-12-31 17:15:49 +01:00
if ( this . config . endpoint ) {
this . config . s3ForcePathStyle = true
} else {
delete this . config . endpoint
}
2021-06-24 19:16:48 +02:00
2021-12-31 17:15:49 +01:00
this . client = new AWS . S3 ( this . config )
2021-06-24 19:16:48 +02:00
}
2022-08-30 17:56:56 +02:00
async create ( query : {
2022-08-30 20:17:10 +02:00
bucket : string
location : string
grantFullControl : string
grantRead : string
grantReadAcp : string
grantWrite : string
grantWriteAcp : string
2022-08-30 17:56:56 +02:00
extra : {
2022-08-30 20:17:10 +02:00
acl : string
}
} ) {
let params : any = {
2022-08-30 17:56:56 +02:00
Bucket : query.bucket ,
2022-08-30 20:17:10 +02:00
ACL : query.extra?.acl ,
2022-08-30 17:56:56 +02:00
GrantFullControl : query.grantFullControl ,
GrantRead : query.grantRead ,
GrantReadACP : query.grantReadAcp ,
GrantWrite : query.grantWrite ,
GrantWriteACP : query.grantWriteAcp ,
2022-08-30 20:17:10 +02:00
}
if ( query . location ) {
params [ "CreateBucketConfiguration" ] = {
LocationConstraint : query.location ,
}
}
2022-08-30 20:56:08 +02:00
return await this . client . createBucket ( params ) . promise ( )
2022-08-30 17:56:56 +02:00
}
2022-08-30 14:42:49 +02:00
async read ( query : {
bucket : string
delimiter : string
expectedBucketOwner : string
marker : string
maxKeys : number
prefix : string
2022-08-30 12:17:11 +02:00
} ) {
2021-06-24 19:16:48 +02:00
const response = await this . client
. listObjects ( {
Bucket : query.bucket ,
2022-08-30 12:17:11 +02:00
Delimiter : query.delimiter ,
Marker : query.marker ,
MaxKeys : query.maxKeys ,
Prefix : query.prefix ,
2021-06-24 19:16:48 +02:00
} )
. promise ( )
return response . Contents
}
2022-08-30 14:42:49 +02:00
async readCsv ( query : { bucket : string ; key : string } ) {
const stream = this . client
. getObject ( {
Bucket : query.bucket ,
Key : query.key ,
} )
. createReadStream ( )
2022-08-30 16:18:44 +02:00
let csvError = false
2022-08-30 16:19:18 +02:00
return new Promise ( ( resolve , reject ) = > {
2022-08-30 16:18:44 +02:00
stream . on ( "error" , ( err : Error ) = > {
reject ( err )
} )
const response = csv ( )
. fromStream ( stream )
. on ( "error" , ( ) = > {
csvError = true
2022-08-30 14:55:55 +02:00
} )
2022-08-30 16:18:44 +02:00
stream . on ( "finish" , ( ) = > {
resolve ( response )
} )
} ) . catch ( err = > {
if ( csvError ) {
throw new Error ( "Could not read CSV" )
} else {
throw err
}
2022-08-30 14:55:55 +02:00
} )
2022-08-30 14:42:49 +02:00
}
2022-08-30 20:56:08 +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
}
module .exports = {
schema : SCHEMA ,
integration : S3Integration ,
}
}