diff --git a/.changeset/shy-buckets-knock.md b/.changeset/shy-buckets-knock.md new file mode 100644 index 00000000..1e0e5d41 --- /dev/null +++ b/.changeset/shy-buckets-knock.md @@ -0,0 +1,5 @@ +--- +"@tus/s3-store": minor +--- + +Add `s3Client` option. This allows user to provide existing S3 client to datastore. diff --git a/packages/s3-store/README.md b/packages/s3-store/README.md index d2f30883..9d659035 100644 --- a/packages/s3-store/README.md +++ b/packages/s3-store/README.md @@ -91,6 +91,10 @@ Options to pass to the AWS S3 SDK. Checkout the docs for the supported options. You need to at least set the `region`, `bucket` name, and your preferred method of authentication. +### `options.s3Client` + +Option to pass existing instance of S3 client that should be used. This option has priority over `options.s3ClientConfig`, but you still need to use `options.s3ClientConfig` to set `bucket` name. + #### `options.expirationPeriodInMilliseconds` Enables the expiration extension and sets the expiration period of an upload url in diff --git a/packages/s3-store/src/index.ts b/packages/s3-store/src/index.ts index 40e1367c..15c83d16 100644 --- a/packages/s3-store/src/index.ts +++ b/packages/s3-store/src/index.ts @@ -47,6 +47,7 @@ export type Options = { expirationPeriodInMilliseconds?: number // Options to pass to the AWS S3 SDK. s3ClientConfig: S3ClientConfig & {bucket: string} + s3Client?: AWS.S3 } export type MetadataValue = { @@ -127,7 +128,7 @@ export class S3Store extends DataStore { this.expirationPeriodInMilliseconds = options.expirationPeriodInMilliseconds ?? 0 this.useTags = options.useTags ?? true this.cache = options.cache ?? new MemoryKvStore() - this.client = new S3(restS3ClientConfig) + this.client = options.s3Client ?? new S3(restS3ClientConfig) this.partUploadSemaphore = new Semaphore(options.maxConcurrentPartUploads ?? 60) } diff --git a/packages/s3-store/test/index.ts b/packages/s3-store/test/index.ts index 4a8e31af..80a13fd2 100644 --- a/packages/s3-store/test/index.ts +++ b/packages/s3-store/test/index.ts @@ -3,6 +3,7 @@ import assert from 'node:assert/strict' import {Readable} from 'node:stream' import sinon from 'sinon' +import { S3 } from '@aws-sdk/client-s3' import {S3Store} from '../src' import * as shared from 'test/stores.test' @@ -294,6 +295,25 @@ describe('S3DataStore', () => { assert.equal(store.maxMultipartParts, customMaxParts) }) + it('should use custom S3 client when specified', async () => { + const client = new S3(s3ClientConfig); + const store = new S3Store({ + s3Client: client, + s3ClientConfig, + }); + + const clientMock = sinon.mock(client); + clientMock.expects("putObject").once(); + + await store.create(new Upload({ + id: shared.testId('test-upload'), + size: 10 * 1024 * 1024, + offset: 0, + })) + + clientMock.verify(); + }) + shared.shouldHaveStoreMethods() shared.shouldCreateUploads() shared.shouldRemoveUploads() // Termination extension