diff --git a/README.md b/README.md index 41883b3..13edc4a 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,16 @@ Require in the same format as Node.js `fs`, specifying an S3 Bucket: const fs = require('@cyclic.sh/s3fs/promises')(S3_BUCKET_NAME) ``` +- On cyclic.sh + - Alternatively, when using with cyclic.sh or if the environment variable `CYCLIC_BUCKET_NAME` is set to an S3 bucket name, initialization can happen without specifying a bucket: + ```js + const fs = require('@cyclic.sh/s3fs') + ``` + or + ```js + const fs = require('@cyclic.sh/s3fs/promises') + ``` + ### Authentication Authenticating the client: diff --git a/src/CyclicS3FSPromises.js b/src/CyclicS3FSPromises.js index b3ad367..5711065 100644 --- a/src/CyclicS3FSPromises.js +++ b/src/CyclicS3FSPromises.js @@ -22,11 +22,24 @@ function streamToBuffer(stream) { }); } -class CyclicS3FSPromises{ - constructor(bucketName, config={}) { - this.bucket = bucketName - this.config = config - this.s3 = new S3Client({...config}); +class CyclicS3FSPromises extends Function{ + constructor(bucket, config={}) { + super('...args', 'return this._bound._call(...args)') + this._bound = this.bind(this) + if(process.env.CYCLIC_BUCKET_NAME){ + this._bound.bucket = process.env.CYCLIC_BUCKET_NAME + } + if(bucket){ + this._bound.bucket = bucket + } + this._bound.s3 = new S3Client({...config}); + + return this._bound + } + + _call(bucketName, config) { + let client = new CyclicS3FSPromises(bucketName, config) + return client } async readFile(fileName ,options){ diff --git a/src/index.js b/src/index.js index 5971fd7..49a5421 100644 --- a/src/index.js +++ b/src/index.js @@ -21,7 +21,19 @@ function makeCallback(cb) { class CyclicS3FS extends CyclicS3FSPromises { constructor(bucketName, config={}) { - super(bucketName, config={}) + super() + if(process.env.CYCLIC_BUCKET_NAME){ + this.bucket = process.env.CYCLIC_BUCKET_NAME + } + this.config = config + if(bucketName){ + this.bucket = bucketName + } + } + + _call(bucketName, config) { + let client = new CyclicS3FS(bucketName, config) + return client } @@ -186,12 +198,24 @@ class CyclicS3FS extends CyclicS3FSPromises { } -const client = function(bucketName, config={}){ - if(!process.env.AWS_SECRET_ACCESS_KEY){ - console.warn('[s3fs] WARNING: AWS credentials are not set. Using local file system') - return fs +var client = new CyclicS3FS() +class FSFallback extends Function{ + constructor() { + super('...args', 'return this._bound._call(...args)') + this._bound = this.bind(this) + Object.assign(this._bound,{...fs}) + return this._bound + } + _call() { + let client = new FSFallback() + return client } - return new CyclicS3FS(bucketName, config) } +if(!process.env.AWS_SECRET_ACCESS_KEY){ + console.warn('[s3fs] WARNING: AWS credentials are not set. Using local file system') + client = new FSFallback() +} + + module.exports = client diff --git a/src/promises.js b/src/promises.js index 2a0b3e6..6581c40 100644 --- a/src/promises.js +++ b/src/promises.js @@ -1,11 +1,22 @@ const fs = require('fs/promises') const CyclicS3FSPromises = require('./CyclicS3FSPromises') -const client = function(bucketName, config={}){ - if(!process.env.AWS_SECRET_ACCESS_KEY){ - console.warn('[s3fs] WARNING: AWS credentials are not set. Using local file system') - return fs +var client = new CyclicS3FSPromises() +class FSPromisesFallback extends Function{ + constructor() { + super('...args', 'return this._bound._call(...args)') + this._bound = this.bind(this) + Object.assign(this._bound,{...fs}) + return this._bound + } + _call() { + let client = new FSPromisesFallback() + return client } - return new CyclicS3FSPromises(bucketName, config) +} + +if(!process.env.AWS_SECRET_ACCESS_KEY){ + console.warn('[s3fs] WARNING: AWS credentials are not set. Using local file system') + client = new FSPromisesFallback() } module.exports = client diff --git a/src/sync_interface.js b/src/sync_interface.js index 2da9252..c566256 100644 --- a/src/sync_interface.js +++ b/src/sync_interface.js @@ -48,6 +48,7 @@ module.exports = { runSync, } const run = async function(bucket, config, method, args){ + const fs = new CyclicS3FSPromises(bucket, config) let result = await fs[method](...args) if(typeof result !== 'undefined'){ diff --git a/test/index.test.js b/test/index.test.js index 677d4bd..9e9550b 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -7,7 +7,7 @@ const { } = require("@aws-sdk/client-s3"); const s3 = new S3Client({}); -const s3fs = require("../src") +const s3fs = require("../src") const s3fs_promises = require("../src/promises") afterAll(async () => { @@ -116,7 +116,7 @@ describe("Basic smoke tests", () => { test("readFileSync(jpeg)", async () => { const d = require("fs").readFileSync('test/_read.jpeg') - const fs = new s3fs(BUCKET) + const fs = s3fs(BUCKET) const _d = fs.readFileSync('test/_read.jpeg') expect(Buffer.compare(d, _d)).toEqual(0) @@ -127,7 +127,7 @@ describe("Basic smoke tests", () => { [Date.now()]: Date.now(), }) - const fs = new s3fs(BUCKET) + const fs = s3fs(BUCKET) fs.writeFileSync('test/_write.json', content) let x = fs.readFileSync('test/_write.json') @@ -137,7 +137,7 @@ describe("Basic smoke tests", () => { test("writeFileSync(big_text)", async () => { const big_text = require("fs").readFileSync('test/_read_big.txt') - const fs = new s3fs(BUCKET) + const fs = s3fs(BUCKET) fs.writeFileSync('test/_write_big.txt', big_text) let x = fs.readFileSync('test/_write_big.txt') @@ -147,7 +147,7 @@ describe("Basic smoke tests", () => { test("writeFileSync(jpeg)", async () => { const jpeg = require("fs").readFileSync('test/_read.jpeg') - const fs = new s3fs(BUCKET) + const fs = s3fs(BUCKET) fs.writeFileSync('test/_write.jpeg', jpeg) let jpeg_s3 = fs.readFileSync('test/_write.jpeg') @@ -509,6 +509,20 @@ describe("Basic smoke tests", () => { }) + + test("object mode / function mode", async () => { + let as_object = Object.getOwnPropertyNames(Object.getPrototypeOf(require('../src'))) + let as_function = Object.getOwnPropertyNames(Object.getPrototypeOf(require('../src')(BUCKET))) + expect(as_function).toEqual(as_object) + }) + + test("object mode / function mode - promises", async () => { + let as_object = Object.getOwnPropertyNames(Object.getPrototypeOf(require('../src/promises'))) + let as_function = Object.getOwnPropertyNames(Object.getPrototypeOf(require('../src/promises')(BUCKET))) + expect(as_function).toEqual(as_object) + }) + + test("empty_bucket", async () => { const fs = s3fs(BUCKET) let dir_name = `/nested/dir_${Date.now()}` @@ -522,6 +536,8 @@ describe("Basic smoke tests", () => { }) + + })