From df943aa829640ec2e7c8a6c22b465b91e5c943a0 Mon Sep 17 00:00:00 2001 From: Surya Oktafendri Date: Wed, 29 May 2024 16:56:05 +0700 Subject: [PATCH] Commit v0.2.0 --- .gitignore | 1 + README.md | 17 ++- package.json | 9 +- pnpm-lock.yaml | 372 ++++++++++++++++++++++++++++++++++++++++++------- src/Bucket.ts | 178 +++++++++++++++++------ src/R2.ts | 2 +- src/types.ts | 9 +- 7 files changed, 488 insertions(+), 100 deletions(-) diff --git a/.gitignore b/.gitignore index 167a517..84d1b1f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ node_modules .env /coverage /lib +/tests /tests-js !.gitkeep diff --git a/README.md b/README.md index 00caafe..b88a4f9 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,22 @@ This is a wrapper of the AWS S3 client library, designed to provide a user-frien ### Installation +#### npm + ```bash npm install node-cloudflare-r2 ``` +#### pnpm + +```bash +pnpm install node-cloudflare-r2 +``` + > It is highly recommended that you use a specific version number in your installation to anticipate any breaking changes that may occur in future releases. For example: \ -> `npm install node-cloudflare-r2@1.0.0` \ +> `npm install node-cloudflare-r2@0.2.0` \ +> or \ +> `pnpm install node-cloudflare-r2@0.2.0` \ > \ > Check the latest version number in the [release page](https://github.com/f2face/cloudflare-r2/releases). @@ -24,6 +34,7 @@ npm install node-cloudflare-r2 ```javascript import { R2 } from 'node-cloudflare-r2'; +import { createReadStream } from 'fs'; const r2 = new R2({ accountId: '', @@ -39,6 +50,7 @@ bucket.provideBucketPublicUrl('https://pub-xxxxxxxxxxxxxxxxxxxxxxxxx.r2.dev'); console.log(await bucket.exists()); // true +// Upload local file const upload = await bucket.uploadFile('/path/to/file', 'destination_file_name.ext'); console.log(upload); /* @@ -50,5 +62,8 @@ console.log(upload); versionId: '', } */ + +// Upload file or stream +const uploadStream = await bucket.uploadStream(createReadStream('/path/to/file'), 'destination_file_name-stream.ext'); ``` diff --git a/package.json b/package.json index 17f4ea3..7622f00 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-cloudflare-r2", - "version": "0.1.5", + "version": "0.2.0", "description": "S3 wrapper for Cloudflare R2.", "main": "./lib/index.js", "scripts": { @@ -38,9 +38,9 @@ "url": "https://github.com/f2face/cloudflare-r2.git" }, "dependencies": { - "@aws-sdk/client-s3": "^3.529.0", - "@aws-sdk/s3-request-presigner": "^3.529.0", - "fast-xml-parser": "4.2.5" + "@aws-sdk/client-s3": "^3.529.1", + "@aws-sdk/lib-storage": "^3.583.0", + "@aws-sdk/s3-request-presigner": "^3.529.1" }, "devDependencies": { "@tsconfig/recommended": "^1.0.3", @@ -58,3 +58,4 @@ "typescript": "^5.4.2" } } + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cfea5de..e5d6c8a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,14 +6,14 @@ settings: dependencies: '@aws-sdk/client-s3': - specifier: ^3.529.0 - version: 3.529.0 + specifier: ^3.529.1 + version: 3.529.1 + '@aws-sdk/lib-storage': + specifier: ^3.583.0 + version: 3.583.0(@aws-sdk/client-s3@3.529.1) '@aws-sdk/s3-request-presigner': - specifier: ^3.529.0 - version: 3.529.0 - fast-xml-parser: - specifier: 4.2.5 - version: 4.2.5 + specifier: ^3.529.1 + version: 3.529.1 devDependencies: '@tsconfig/recommended': @@ -140,16 +140,16 @@ packages: tslib: 1.14.1 dev: false - /@aws-sdk/client-s3@3.529.0: - resolution: {integrity: sha512-+ol8eDhotGzBOTqrwAXRYhgi9i40M943nlZe2lMN0TYcP2lDMAn2J8f6JUYE54XPYPoDpoy/F+VLaB7olEGAmA==} + /@aws-sdk/client-s3@3.529.1: + resolution: {integrity: sha512-ZpvyO4w3XWo/OjXLd3fm7CLcKUUYcyady9qzTnKKSnp8a2NqO7UvU/1zhYdm+yyy8TR/9t7sDy+q6AYd4Nsr8g==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha1-browser': 3.0.0 '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.529.0(@aws-sdk/credential-provider-node@3.529.0) - '@aws-sdk/core': 3.529.0 - '@aws-sdk/credential-provider-node': 3.529.0 + '@aws-sdk/client-sts': 3.529.1(@aws-sdk/credential-provider-node@3.529.1) + '@aws-sdk/core': 3.529.1 + '@aws-sdk/credential-provider-node': 3.529.1 '@aws-sdk/middleware-bucket-endpoint': 3.525.0 '@aws-sdk/middleware-expect-continue': 3.523.0 '@aws-sdk/middleware-flexible-checksums': 3.523.0 @@ -205,17 +205,17 @@ packages: - aws-crt dev: false - /@aws-sdk/client-sso-oidc@3.529.0(@aws-sdk/credential-provider-node@3.529.0): - resolution: {integrity: sha512-pUQhuJmaDWSRr6WK5YILvpApzFXsFmWXnsinmgabf8vSa134BAbDrootFef//Zuksc9HRa4FhUEurw/yrWaWHQ==} + /@aws-sdk/client-sso-oidc@3.529.1(@aws-sdk/credential-provider-node@3.529.1): + resolution: {integrity: sha512-bimxCWAvRnVcluWEQeadXvHyzWlBWsuGVligsaVZaGF0TLSn0eLpzpN9B1EhHzTf7m0Kh/wGtPSH1JxO6PpB+A==} engines: {node: '>=14.0.0'} peerDependencies: - '@aws-sdk/credential-provider-node': ^3.529.0 + '@aws-sdk/credential-provider-node': ^3.529.1 dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.529.0(@aws-sdk/credential-provider-node@3.529.0) - '@aws-sdk/core': 3.529.0 - '@aws-sdk/credential-provider-node': 3.529.0 + '@aws-sdk/client-sts': 3.529.1(@aws-sdk/credential-provider-node@3.529.1) + '@aws-sdk/core': 3.529.1 + '@aws-sdk/credential-provider-node': 3.529.1 '@aws-sdk/middleware-host-header': 3.523.0 '@aws-sdk/middleware-logger': 3.523.0 '@aws-sdk/middleware-recursion-detection': 3.523.0 @@ -255,13 +255,13 @@ packages: - aws-crt dev: false - /@aws-sdk/client-sso@3.529.0: - resolution: {integrity: sha512-QdUmxRVjwCN81v8qb2N0fmIKmq17Rh1Is6yQ9T/dQ3rlnU4mg6b/2qk0qiZOPF4wroMALr/EaDvPXHqZR+lRqA==} + /@aws-sdk/client-sso@3.529.1: + resolution: {integrity: sha512-KT1U/ZNjDhVv2ZgjzaeAn9VM7l667yeSguMrRYC8qk5h91/61MbjZypi6eOuKuVM+0fsQvzKScTQz0Lio0eYag==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/core': 3.529.0 + '@aws-sdk/core': 3.529.1 '@aws-sdk/middleware-host-header': 3.523.0 '@aws-sdk/middleware-logger': 3.523.0 '@aws-sdk/middleware-recursion-detection': 3.523.0 @@ -301,16 +301,16 @@ packages: - aws-crt dev: false - /@aws-sdk/client-sts@3.529.0(@aws-sdk/credential-provider-node@3.529.0): - resolution: {integrity: sha512-8gWlnXisDv/mQGbvoDTwJaQEqFu/7nbPIkMOpM8JdW4ITU07tILNIqNPY3r0t2oHyK8qPP7aOXwrh1ETklYYig==} + /@aws-sdk/client-sts@3.529.1(@aws-sdk/credential-provider-node@3.529.1): + resolution: {integrity: sha512-Rvk2Sr3MACQTOtngUU+omlf4E17k47dRVXR7OFRD6Ow5iGgC9tkN2q/ExDPW/ktPOmM0lSgzWyQ6/PC/Zq3HUg==} engines: {node: '>=14.0.0'} peerDependencies: - '@aws-sdk/credential-provider-node': ^3.529.0 + '@aws-sdk/credential-provider-node': ^3.529.1 dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/core': 3.529.0 - '@aws-sdk/credential-provider-node': 3.529.0 + '@aws-sdk/core': 3.529.1 + '@aws-sdk/credential-provider-node': 3.529.1 '@aws-sdk/middleware-host-header': 3.523.0 '@aws-sdk/middleware-logger': 3.523.0 '@aws-sdk/middleware-recursion-detection': 3.523.0 @@ -350,8 +350,8 @@ packages: - aws-crt dev: false - /@aws-sdk/core@3.529.0: - resolution: {integrity: sha512-jVpc5XVDx0uX5sltNpTDCfItB54OS8+qpejItU5rStRDUZG9wJBDq8yvNbymFShGLYi5Ly1YdIyriUPc6Q4Gjw==} + /@aws-sdk/core@3.529.1: + resolution: {integrity: sha512-Sj42sYPfaL9PHvvciMICxhyrDZjqnnvFbPKDmQL5aFKyXy122qx7RdVqUOQERDmMQfvJh6+0W1zQlLnre89q4Q==} engines: {node: '>=14.0.0'} dependencies: '@smithy/core': 1.3.7 @@ -359,6 +359,7 @@ packages: '@smithy/signature-v4': 2.1.4 '@smithy/smithy-client': 2.4.4 '@smithy/types': 2.11.0 + fast-xml-parser: 4.2.5 tslib: 2.6.2 dev: false @@ -387,15 +388,15 @@ packages: tslib: 2.6.2 dev: false - /@aws-sdk/credential-provider-ini@3.529.0(@aws-sdk/credential-provider-node@3.529.0): - resolution: {integrity: sha512-JnK4H4TjD5MMX31idkJ5oQgSygZ+cMrc9syZ81jN+Kru94WHYoMKlvAU4VXTA2HjL0grM9wo6UeNadD9qWjLrQ==} + /@aws-sdk/credential-provider-ini@3.529.1(@aws-sdk/credential-provider-node@3.529.1): + resolution: {integrity: sha512-RjHsuTvHIwXG7a/3ERexemiD3c9riKMCZQzY2/b0Gg0ButEVbBcMfERtUzWmQ0V4ufe/PEZjP68MH1gupcoF9A==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/client-sts': 3.529.0(@aws-sdk/credential-provider-node@3.529.0) + '@aws-sdk/client-sts': 3.529.1(@aws-sdk/credential-provider-node@3.529.1) '@aws-sdk/credential-provider-env': 3.523.0 '@aws-sdk/credential-provider-process': 3.523.0 - '@aws-sdk/credential-provider-sso': 3.529.0(@aws-sdk/credential-provider-node@3.529.0) - '@aws-sdk/credential-provider-web-identity': 3.529.0(@aws-sdk/credential-provider-node@3.529.0) + '@aws-sdk/credential-provider-sso': 3.529.1(@aws-sdk/credential-provider-node@3.529.1) + '@aws-sdk/credential-provider-web-identity': 3.529.1(@aws-sdk/credential-provider-node@3.529.1) '@aws-sdk/types': 3.523.0 '@smithy/credential-provider-imds': 2.2.6 '@smithy/property-provider': 2.1.4 @@ -407,16 +408,16 @@ packages: - aws-crt dev: false - /@aws-sdk/credential-provider-node@3.529.0: - resolution: {integrity: sha512-GrrF3uxovxZ23bZYcSUAa+b0c1UYHkn4XFVnO3tlpx6GmTVWIgQ2zzdw4mwPoTsS9LRKkV/RCyKqf8Cvmkgyeg==} + /@aws-sdk/credential-provider-node@3.529.1: + resolution: {integrity: sha512-mvY7F3dMmk/0dZOCfl5sUI1bG0osureBjxhELGCF0KkJqhWI0hIzh8UnPkYytSg3vdc97CMv7pTcozxrdA3b0g==} engines: {node: '>=14.0.0'} dependencies: '@aws-sdk/credential-provider-env': 3.523.0 '@aws-sdk/credential-provider-http': 3.525.0 - '@aws-sdk/credential-provider-ini': 3.529.0(@aws-sdk/credential-provider-node@3.529.0) + '@aws-sdk/credential-provider-ini': 3.529.1(@aws-sdk/credential-provider-node@3.529.1) '@aws-sdk/credential-provider-process': 3.523.0 - '@aws-sdk/credential-provider-sso': 3.529.0(@aws-sdk/credential-provider-node@3.529.0) - '@aws-sdk/credential-provider-web-identity': 3.529.0(@aws-sdk/credential-provider-node@3.529.0) + '@aws-sdk/credential-provider-sso': 3.529.1(@aws-sdk/credential-provider-node@3.529.1) + '@aws-sdk/credential-provider-web-identity': 3.529.1(@aws-sdk/credential-provider-node@3.529.1) '@aws-sdk/types': 3.523.0 '@smithy/credential-provider-imds': 2.2.6 '@smithy/property-provider': 2.1.4 @@ -438,12 +439,12 @@ packages: tslib: 2.6.2 dev: false - /@aws-sdk/credential-provider-sso@3.529.0(@aws-sdk/credential-provider-node@3.529.0): - resolution: {integrity: sha512-UwG0fmggIlrxCKyD6oSMGL+LN8uq/DSkg4pCQo0uuEB6qGFDnnyvXsQ5lFtBngnmo3PLk34OAZvkz7IS35cl8A==} + /@aws-sdk/credential-provider-sso@3.529.1(@aws-sdk/credential-provider-node@3.529.1): + resolution: {integrity: sha512-KFMKkaoTGDgSJG+o9Ii7AglWG5JQeF6IFw9cXLMwDdIrp3KUmRcUIqe0cjOoCqeQEDGy0VHsimHmKKJ3894i/A==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/client-sso': 3.529.0 - '@aws-sdk/token-providers': 3.529.0(@aws-sdk/credential-provider-node@3.529.0) + '@aws-sdk/client-sso': 3.529.1 + '@aws-sdk/token-providers': 3.529.1(@aws-sdk/credential-provider-node@3.529.1) '@aws-sdk/types': 3.523.0 '@smithy/property-provider': 2.1.4 '@smithy/shared-ini-file-loader': 2.3.5 @@ -454,11 +455,11 @@ packages: - aws-crt dev: false - /@aws-sdk/credential-provider-web-identity@3.529.0(@aws-sdk/credential-provider-node@3.529.0): - resolution: {integrity: sha512-rtSzWA7HW7iTfd0QvRtoBBFVOwR2xxcvHGdRxj0IczxhjT0aJCadLDuNfr1Y/8tO5TPLcFAoDmcnshQ5Agqp8Q==} + /@aws-sdk/credential-provider-web-identity@3.529.1(@aws-sdk/credential-provider-node@3.529.1): + resolution: {integrity: sha512-AGuZDOKN+AttjwTjrF47WLqzeEut2YynyxjkXZhxZF/xn8i5Y51kUAUdXsXw1bgR25pAeXQIdhsrQlRa1Pm5kw==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/client-sts': 3.529.0(@aws-sdk/credential-provider-node@3.529.0) + '@aws-sdk/client-sts': 3.529.1(@aws-sdk/credential-provider-node@3.529.1) '@aws-sdk/types': 3.523.0 '@smithy/property-provider': 2.1.4 '@smithy/types': 2.11.0 @@ -468,6 +469,22 @@ packages: - aws-crt dev: false + /@aws-sdk/lib-storage@3.583.0(@aws-sdk/client-s3@3.529.1): + resolution: {integrity: sha512-To3mCeSpJiHWxAh00S5+cRfx8BkbdmWvZG2Rvcz20Qqh/GmhMWeDbN4OjDTqcewWpqNhU0n1ShZY/GcIWSn+Pg==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@aws-sdk/client-s3': ^3.583.0 + dependencies: + '@aws-sdk/client-s3': 3.529.1 + '@smithy/abort-controller': 3.0.0 + '@smithy/middleware-endpoint': 3.0.0 + '@smithy/smithy-client': 3.0.1 + buffer: 5.6.0 + events: 3.3.0 + stream-browserify: 3.0.0 + tslib: 2.6.2 + dev: false + /@aws-sdk/middleware-bucket-endpoint@3.525.0: resolution: {integrity: sha512-nYfQ2Xspfef7j8mZO7varUWLPH6HQlXateH7tBVtBNUAazyQE4UJEvC0fbQ+Y01e+FKlirim/m2umkdMXqAlTg==} engines: {node: '>=14.0.0'} @@ -603,8 +620,8 @@ packages: tslib: 2.6.2 dev: false - /@aws-sdk/s3-request-presigner@3.529.0: - resolution: {integrity: sha512-vF7u8pKxFF//oTnZuQ2r8KEaUt1pgv7aYNC6sLCatC7DxQ+9jrmJki9zzFKOAA0oxcepOtgNx+I/G6ljFP2/zg==} + /@aws-sdk/s3-request-presigner@3.529.1: + resolution: {integrity: sha512-54nNN/LjqlyUDTLO3U9D7xkYK4/UttcqfKoHQuPI6QabqZGT1hMFs5SzsyihNchgxci6ZTo4pqQQ3lGfE/HHOA==} engines: {node: '>=14.0.0'} dependencies: '@aws-sdk/signature-v4-multi-region': 3.525.0 @@ -629,11 +646,11 @@ packages: tslib: 2.6.2 dev: false - /@aws-sdk/token-providers@3.529.0(@aws-sdk/credential-provider-node@3.529.0): - resolution: {integrity: sha512-mQrqF9YwApeh5AkUpZqvGhpXzQyUFm6Yxh3/cOTXd5cBjttcAlenyc75BTYb4kYXj1xW5dktnlnFD7sS+s7e8g==} + /@aws-sdk/token-providers@3.529.1(@aws-sdk/credential-provider-node@3.529.1): + resolution: {integrity: sha512-NpgMjsfpqiugbxrYGXtta914N43Mx/H0niidqv8wKMTgWQEtsJvYtOni+kuLXB+LmpjaMFNlpadooFU/bK4buA==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/client-sso-oidc': 3.529.0(@aws-sdk/credential-provider-node@3.529.0) + '@aws-sdk/client-sso-oidc': 3.529.1(@aws-sdk/credential-provider-node@3.529.1) '@aws-sdk/types': 3.523.0 '@smithy/property-provider': 2.1.4 '@smithy/shared-ini-file-loader': 2.3.5 @@ -1434,6 +1451,14 @@ packages: tslib: 2.6.2 dev: false + /@smithy/abort-controller@3.0.0: + resolution: {integrity: sha512-p6GlFGBt9K4MYLu72YuJ523NVR4A8oHlC5M2JO6OmQqN8kAc/uh1JqLE+FizTokrSJGg0CSvC+BrsmGzKtsZKA==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/chunked-blob-reader-native@2.1.2: resolution: {integrity: sha512-KwR9fFc/t5jH9RQFbrA9DHSmI+URTmB4v+i7H08UNET9AcN6GGBTBMiDKpA56Crw6CN7cSaSDXaRS/AsfOuupQ==} dependencies: @@ -1537,6 +1562,16 @@ packages: tslib: 2.6.2 dev: false + /@smithy/fetch-http-handler@3.0.1: + resolution: {integrity: sha512-uaH74i5BDj+rBwoQaXioKpI0SHBJFtOVwzrCpxZxphOW0ki5jhj7dXvDMYM2IJem8TpdFvS2iC08sjOblfFGFg==} + dependencies: + '@smithy/protocol-http': 4.0.0 + '@smithy/querystring-builder': 3.0.0 + '@smithy/types': 3.0.0 + '@smithy/util-base64': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/hash-blob-browser@2.1.4: resolution: {integrity: sha512-bDugS1DortnriGDdp0sqdq7dLI5if8CEOF9rKtpJa1ZYMq6fxOtTId//dlilS5QgUtUs6GHN5aMQVxEjhBzzQA==} dependencies: @@ -1579,6 +1614,13 @@ packages: tslib: 2.6.2 dev: false + /@smithy/is-array-buffer@3.0.0: + resolution: {integrity: sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==} + engines: {node: '>=16.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + /@smithy/md5-js@2.1.4: resolution: {integrity: sha512-WHTnnYJPKE7Sy49DogLuox42TnlwD3cQ6TObPD6WFWjKocWIdpEpIvdJHwWUfSFf0JIi8ON8z6ZEhsnyKVCcLQ==} dependencies: @@ -1609,6 +1651,19 @@ packages: tslib: 2.6.2 dev: false + /@smithy/middleware-endpoint@3.0.0: + resolution: {integrity: sha512-aXOAWztw/5qAfp0NcA2OWpv6ZI/E+Dh9mByif7i91D/0iyYNUcKvskmXiowKESFkuZ7PIMd3VOR4fTibZDs2OQ==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/middleware-serde': 3.0.0 + '@smithy/node-config-provider': 3.0.0 + '@smithy/shared-ini-file-loader': 3.0.0 + '@smithy/types': 3.0.0 + '@smithy/url-parser': 3.0.0 + '@smithy/util-middleware': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/middleware-retry@2.1.6: resolution: {integrity: sha512-khpSV0NxqMHfa06kfG4WYv+978sVvfTFmn0hIFKKwOXtIxyYtPKiQWFT4nnwZD07fGdYGbtCBu3YALc8SsA5mA==} engines: {node: '>=14.0.0'} @@ -1632,6 +1687,14 @@ packages: tslib: 2.6.2 dev: false + /@smithy/middleware-serde@3.0.0: + resolution: {integrity: sha512-I1vKG1foI+oPgG9r7IMY1S+xBnmAn1ISqployvqkwHoSb8VPsngHDTOgYGYBonuOKndaWRUGJZrKYYLB+Ane6w==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/middleware-stack@2.1.4: resolution: {integrity: sha512-Qqs2ba8Ax1rGKOSGJS2JN23fhhox2WMdRuzx0NYHtXzhxbJOIMmz9uQY6Hf4PY8FPteBPp1+h0j5Fmr+oW12sg==} engines: {node: '>=14.0.0'} @@ -1640,6 +1703,14 @@ packages: tslib: 2.6.2 dev: false + /@smithy/middleware-stack@3.0.0: + resolution: {integrity: sha512-+H0jmyfAyHRFXm6wunskuNAqtj7yfmwFB6Fp37enytp2q047/Od9xetEaUbluyImOlGnGpaVGaVfjwawSr+i6Q==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/node-config-provider@2.2.5: resolution: {integrity: sha512-CxPf2CXhjO79IypHJLBATB66Dw6suvr1Yc2ccY39hpR6wdse3pZ3E8RF83SODiNH0Wjmkd0ze4OF8exugEixgA==} engines: {node: '>=14.0.0'} @@ -1650,6 +1721,16 @@ packages: tslib: 2.6.2 dev: false + /@smithy/node-config-provider@3.0.0: + resolution: {integrity: sha512-buqfaSdDh0zo62EPLf8rGDvcpKwGpO5ho4bXS2cdFhlOta7tBkWJt+O5uiaAeICfIOfPclNOndshDNSanX2X9g==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/property-provider': 3.0.0 + '@smithy/shared-ini-file-loader': 3.0.0 + '@smithy/types': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/node-http-handler@2.4.2: resolution: {integrity: sha512-yrj3c1g145uiK5io+1UPbJAHo8BSGORkBzrmzvAsOmBKb+1p3jmM8ZwNLDH/HTTxVLm9iM5rMszx+iAh1HUC4Q==} engines: {node: '>=14.0.0'} @@ -1661,6 +1742,17 @@ packages: tslib: 2.6.2 dev: false + /@smithy/node-http-handler@3.0.0: + resolution: {integrity: sha512-3trD4r7NOMygwLbUJo4eodyQuypAWr7uvPnebNJ9a70dQhVn+US8j/lCnvoJS6BXfZeF7PkkkI0DemVJw+n+eQ==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/abort-controller': 3.0.0 + '@smithy/protocol-http': 4.0.0 + '@smithy/querystring-builder': 3.0.0 + '@smithy/types': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/property-provider@2.1.4: resolution: {integrity: sha512-nWaY/MImj1BiXZ9WY65h45dcxOx8pl06KYoHxwojDxDL+Q9yLU1YnZpgv8zsHhEftlj9KhePENjQTlNowWVyug==} engines: {node: '>=14.0.0'} @@ -1669,6 +1761,14 @@ packages: tslib: 2.6.2 dev: false + /@smithy/property-provider@3.0.0: + resolution: {integrity: sha512-LmbPgHBswdXCrkWWuUwBm9w72S2iLWyC/5jet9/Y9cGHtzqxi+GVjfCfahkvNV4KXEwgnH8EMpcrD9RUYe0eLQ==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/protocol-http@3.2.2: resolution: {integrity: sha512-xYBlllOQcOuLoxzhF2u8kRHhIFGQpDeTQj/dBSnw4kfI29WMKL5RnW1m9YjnJAJ49miuIvrkJR+gW5bCQ+Mchw==} engines: {node: '>=14.0.0'} @@ -1677,6 +1777,14 @@ packages: tslib: 2.6.2 dev: false + /@smithy/protocol-http@4.0.0: + resolution: {integrity: sha512-qOQZOEI2XLWRWBO9AgIYuHuqjZ2csyr8/IlgFDHDNuIgLAMRx2Bl8ck5U5D6Vh9DPdoaVpuzwWMa0xcdL4O/AQ==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/querystring-builder@2.1.4: resolution: {integrity: sha512-LXSL0J/nRWvGT+jIj+Fip3j0J1ZmHkUyBFRzg/4SmPNCLeDrtVu7ptKOnTboPsFZu5BxmpYok3kJuQzzRdrhbw==} engines: {node: '>=14.0.0'} @@ -1686,6 +1794,15 @@ packages: tslib: 2.6.2 dev: false + /@smithy/querystring-builder@3.0.0: + resolution: {integrity: sha512-bW8Fi0NzyfkE0TmQphDXr1AmBDbK01cA4C1Z7ggwMAU5RDz5AAv/KmoRwzQAS0kxXNf/D2ALTEgwK0U2c4LtRg==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/types': 3.0.0 + '@smithy/util-uri-escape': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/querystring-parser@2.1.4: resolution: {integrity: sha512-U2b8olKXgZAs0eRo7Op11jTNmmcC/sqYmsA7vN6A+jkGnDvJlEl7AetUegbBzU8q3D6WzC5rhR/joIy8tXPzIg==} engines: {node: '>=14.0.0'} @@ -1694,6 +1811,14 @@ packages: tslib: 2.6.2 dev: false + /@smithy/querystring-parser@3.0.0: + resolution: {integrity: sha512-UzHwthk0UEccV4dHzPySnBy34AWw3V9lIqUTxmozQ+wPDAO9csCWMfOLe7V9A2agNYy7xE+Pb0S6K/J23JSzfQ==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/service-error-classification@2.1.4: resolution: {integrity: sha512-JW2Hthy21evnvDmYYk1kItOmbp3X5XI5iqorXgFEunb6hQfSDZ7O1g0Clyxg7k/Pcr9pfLk5xDIR2To/IohlsQ==} engines: {node: '>=14.0.0'} @@ -1709,6 +1834,14 @@ packages: tslib: 2.6.2 dev: false + /@smithy/shared-ini-file-loader@3.0.0: + resolution: {integrity: sha512-REVw6XauXk8xE4zo5aGL7Rz4ywA8qNMUn8RtWeTRQsgAlmlvbJ7CEPBcaXU2NDC3AYBgYAXrGyWD8XrN8UGDog==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/signature-v4@2.1.4: resolution: {integrity: sha512-gnu9gCn0qQ8IdhNjs6o3QVCXzUs33znSDYwVMWo3nX4dM6j7z9u6FC302ShYyVWfO4MkVMuGCCJ6nl3PcH7V1Q==} engines: {node: '>=14.0.0'} @@ -1735,6 +1868,18 @@ packages: tslib: 2.6.2 dev: false + /@smithy/smithy-client@3.0.1: + resolution: {integrity: sha512-KAiFY4Y4jdHxR+4zerH/VBhaFKM8pbaVmJZ/CWJRwtM/CmwzTfXfvYwf6GoUwiHepdv+lwiOXCuOl6UBDUEINw==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/middleware-endpoint': 3.0.0 + '@smithy/middleware-stack': 3.0.0 + '@smithy/protocol-http': 4.0.0 + '@smithy/types': 3.0.0 + '@smithy/util-stream': 3.0.1 + tslib: 2.6.2 + dev: false + /@smithy/types@2.11.0: resolution: {integrity: sha512-AR0SXO7FuAskfNhyGfSTThpLRntDI5bOrU0xrpVYU0rZyjl3LBXInZFMTP/NNSd7IS6Ksdtar0QvnrPRIhVrLQ==} engines: {node: '>=14.0.0'} @@ -1742,6 +1887,13 @@ packages: tslib: 2.6.2 dev: false + /@smithy/types@3.0.0: + resolution: {integrity: sha512-VvWuQk2RKFuOr98gFhjca7fkBS+xLLURT8bUjk5XQoV0ZLm7WPwWPPY3/AwzTLuUBDeoKDCthfe1AsTUWaSEhw==} + engines: {node: '>=16.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + /@smithy/url-parser@2.1.4: resolution: {integrity: sha512-1hTy6UYRYqOZlHKH2/2NzdNQ4NNmW2Lp0sYYvztKy+dEQuLvZL9w88zCzFQqqFer3DMcscYOshImxkJTGdV+rg==} dependencies: @@ -1750,6 +1902,14 @@ packages: tslib: 2.6.2 dev: false + /@smithy/url-parser@3.0.0: + resolution: {integrity: sha512-2XLazFgUu+YOGHtWihB3FSLAfCUajVfNBXGGYjOaVKjLAuAxx3pSBY3hBgLzIgB17haf59gOG3imKqTy8mcrjw==} + dependencies: + '@smithy/querystring-parser': 3.0.0 + '@smithy/types': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/util-base64@2.2.0: resolution: {integrity: sha512-RiQI/Txu0SxCR38Ky5BMEVaFfkNTBjpbxlr2UhhxggSmnsHDQPZJWMtPoXs7TWZaseslIlAWMiHmqRT3AV/P2w==} engines: {node: '>=14.0.0'} @@ -1759,6 +1919,15 @@ packages: tslib: 2.6.2 dev: false + /@smithy/util-base64@3.0.0: + resolution: {integrity: sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/util-buffer-from': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/util-body-length-browser@2.1.1: resolution: {integrity: sha512-ekOGBLvs1VS2d1zM2ER4JEeBWAvIOUKeaFch29UjjJsxmZ/f0L3K3x0dEETgh3Q9bkZNHgT+rkdl/J/VUqSRag==} dependencies: @@ -1780,6 +1949,14 @@ packages: tslib: 2.6.2 dev: false + /@smithy/util-buffer-from@3.0.0: + resolution: {integrity: sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/is-array-buffer': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/util-config-provider@2.2.1: resolution: {integrity: sha512-50VL/tx9oYYcjJn/qKqNy7sCtpD0+s8XEBamIFo4mFFTclKMNp+rsnymD796uybjiIquB7VCB/DeafduL0y2kw==} engines: {node: '>=14.0.0'} @@ -1827,6 +2004,13 @@ packages: tslib: 2.6.2 dev: false + /@smithy/util-hex-encoding@3.0.0: + resolution: {integrity: sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==} + engines: {node: '>=16.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + /@smithy/util-middleware@2.1.4: resolution: {integrity: sha512-5yYNOgCN0DL0OplME0pthoUR/sCfipnROkbTO7m872o0GHCVNJj5xOFJ143rvHNA54+pIPMLum4z2DhPC2pVGA==} engines: {node: '>=14.0.0'} @@ -1835,6 +2019,14 @@ packages: tslib: 2.6.2 dev: false + /@smithy/util-middleware@3.0.0: + resolution: {integrity: sha512-q5ITdOnV2pXHSVDnKWrwgSNTDBAMHLptFE07ua/5Ty5WJ11bvr0vk2a7agu7qRhrCFRQlno5u3CneU5EELK+DQ==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/types': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/util-retry@2.1.4: resolution: {integrity: sha512-JRZwhA3fhkdenSEYIWatC8oLwt4Bdf2LhHbNQApqb7yFoIGMl4twcYI3BcJZ7YIBZrACA9jGveW6tuCd836XzQ==} engines: {node: '>= 14.0.0'} @@ -1858,6 +2050,20 @@ packages: tslib: 2.6.2 dev: false + /@smithy/util-stream@3.0.1: + resolution: {integrity: sha512-7F7VNNhAsfMRA8I986YdOY5fE0/T1/ZjFF6OLsqkvQVNP3vZ/szYDfGCyphb7ioA09r32K/0qbSFfNFU68aSzA==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/fetch-http-handler': 3.0.1 + '@smithy/node-http-handler': 3.0.0 + '@smithy/types': 3.0.0 + '@smithy/util-base64': 3.0.0 + '@smithy/util-buffer-from': 3.0.0 + '@smithy/util-hex-encoding': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/util-uri-escape@2.1.1: resolution: {integrity: sha512-saVzI1h6iRBUVSqtnlOnc9ssU09ypo7n+shdQ8hBTZno/9rZ3AuRYvoHInV57VF7Qn7B+pFJG7qTzFiHxWlWBw==} engines: {node: '>=14.0.0'} @@ -1865,6 +2071,13 @@ packages: tslib: 2.6.2 dev: false + /@smithy/util-uri-escape@3.0.0: + resolution: {integrity: sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==} + engines: {node: '>=16.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + /@smithy/util-utf8@2.2.0: resolution: {integrity: sha512-hBsKr5BqrDrKS8qy+YcV7/htmMGxriA1PREOf/8AGBhHIZnfilVv1Waf1OyKhSbFW15U/8+gcMUQ9/Kk5qwpHQ==} engines: {node: '>=14.0.0'} @@ -1873,6 +2086,14 @@ packages: tslib: 2.6.2 dev: false + /@smithy/util-utf8@3.0.0: + resolution: {integrity: sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==} + engines: {node: '>=16.0.0'} + dependencies: + '@smithy/util-buffer-from': 3.0.0 + tslib: 2.6.2 + dev: false + /@smithy/util-waiter@2.1.4: resolution: {integrity: sha512-AK17WaC0hx1wR9juAOsQkJ6DjDxBGEf5TrKhpXtNFEn+cVto9Li3MVsdpAO97AF7bhFXSyC8tJA3F4ThhqwCdg==} engines: {node: '>=14.0.0'} @@ -2271,6 +2492,10 @@ packages: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: false + /bowser@2.11.0: resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} dev: false @@ -2323,6 +2548,13 @@ packages: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true + /buffer@5.6.0: + resolution: {integrity: sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -2662,6 +2894,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: false + /execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -2917,6 +3154,10 @@ packages: engines: {node: '>=10.17.0'} dev: true + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: false + /ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} @@ -2953,7 +3194,6 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true /is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} @@ -3857,6 +4097,15 @@ packages: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} dev: true + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -3919,6 +4168,10 @@ packages: queue-microtask: 1.2.3 dev: true + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -3985,6 +4238,13 @@ packages: escape-string-regexp: 2.0.0 dev: true + /stream-browserify@3.0.0: + resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: false + /string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -4011,6 +4271,12 @@ packages: strip-ansi: 7.1.0 dev: true + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: false + /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -4199,6 +4465,10 @@ packages: punycode: 2.3.1 dev: true + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: false + /uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true diff --git a/src/Bucket.ts b/src/Bucket.ts index c07d95c..8a5a786 100644 --- a/src/Bucket.ts +++ b/src/Bucket.ts @@ -11,9 +11,12 @@ import { PutObjectCommand, type S3Client as R2, } from '@aws-sdk/client-s3'; +import { Upload, type Progress } from '@aws-sdk/lib-storage'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; -import { createReadStream, PathLike } from 'fs'; -import { CORSPolicy, HeadObjectResponse, ObjectListResponse, UploadFileResponse } from './types'; +import { ReadStream, createReadStream, type PathLike } from 'fs'; +import { basename } from 'path'; +import type { Readable } from 'stream'; +import type { CORSPolicy, HeadObjectResponse, ObjectListResponse, UploadFileResponse } from './types'; export class Bucket { private r2: R2; @@ -61,7 +64,6 @@ export class Bucket { public provideBucketPublicUrl(bucketPublicUrl: string): this; public provideBucketPublicUrl(bucketPublicUrls: string[]): this; - public provideBucketPublicUrl(...bucketPublicUrls: string[]): this; /** * Sets the public URL for the current bucket. If public access to the bucket is allowed, use this method to provide bucket public URL to this `Bucket` object. @@ -70,12 +72,11 @@ export class Bucket { */ public provideBucketPublicUrl(bucketPublicUrl: string | string[]): this { if (typeof bucketPublicUrl === 'string') { - this.bucketPublicUrls.push(new URL(bucketPublicUrl).origin); + const origin = new URL(bucketPublicUrl).origin; + this.bucketPublicUrls.push(origin); } else if (Array.isArray(bucketPublicUrl)) { for (const url of bucketPublicUrl) { - if (typeof url === 'string') { - this.provideBucketPublicUrl(url); - } + if (typeof url === 'string') this.provideBucketPublicUrl(url); } } @@ -83,6 +84,8 @@ export class Bucket { } /** + * **DEPRECATED. This method will be removed in the next major version. Use `getPublicUrls()` instead.** + * * Returns the bucket public URL if it's set with `provideBucketPublicUrl` method. * @deprecated */ @@ -91,19 +94,18 @@ export class Bucket { } /** - * Returns all public URLs of the bucket if it's set with `provideBucketPublicUrl` method. + * Returns all public URLs of the bucket if it's set with `provideBucketPublicUrl()` method. */ public getPublicUrls(): string[] { return this.bucketPublicUrls; } /** - * Returns the signed URL of an object. + * Returns the signed URL of an object. This method does not check whether the object exists or not. * @param objectKey * @param expiresIn Expiration time in seconds. - * @returns */ - public async getObjectSignedUrl(objectKey: string, expiresIn: number) { + public async getObjectSignedUrl(objectKey: string, expiresIn: number): Promise { const obj = new GetObjectCommand({ Bucket: this.name, Key: objectKey, @@ -115,7 +117,6 @@ export class Bucket { /** * Generates object public URL if the bucket public URL is set with `provideBucketPublicUrl` method. * @param objectKey - * @returns */ protected generateObjectPublicUrl(objectKey: string): string | null { if (!this.bucketPublicUrls.length) return null; @@ -124,7 +125,25 @@ export class Bucket { } /** - * Determines if the bucket exists and you have permission to access it. + * Generates object public URLs if the bucket public URL is set with `provideBucketPublicUrl` method. + * @param objectKey + */ + protected generateObjectPublicUrls(objectKey: string): Array { + if (!this.bucketPublicUrls.length) return []; + + return this.bucketPublicUrls.map((publicUrl) => `${publicUrl}/${objectKey}`); + } + + /** + * Returns all public URL of an object in the bucket. + * @param objectKey + */ + public getObjectPublicUrls(objectKey: string): string[] { + return this.bucketPublicUrls.map((bucketPublicUrl) => `${bucketPublicUrl}/${objectKey}`); + } + + /** + * Checks if the bucket exists and you have permission to access it. * @param bucketName */ public async exists(): Promise { @@ -142,9 +161,19 @@ export class Bucket { } /** + * **DEPRECATED. This method will be remove in the next major version. Use `getCorsPolicies()` instead.** + * * Returns Cross-Origin Resource Sharing (CORS) policies of the bucket. + * @deprecated */ public async getCors(): Promise { + return this.getCorsPolicies(); + } + + /** + * Returns Cross-Origin Resource Sharing (CORS) policies of the bucket. + */ + public async getCorsPolicies(): Promise { try { const result = await this.r2.send( new GetBucketCorsCommand({ @@ -179,7 +208,7 @@ export class Bucket { } /** - * Returns the region the bucket resides in. For `Cloudflare R2`, the region is always `auto`. + * Returns the region the bucket resides in. * @param bucketName */ public async getRegion() { @@ -191,6 +220,9 @@ export class Bucket { return result.LocationConstraint || 'auto'; } + /** + * Returns the encryption configuration of the bucket. + */ public async getEncryption() { const result = await this.r2.send( new GetBucketEncryptionCommand({ @@ -213,7 +245,7 @@ export class Bucket { } /** - * Upload a file to the bucket. + * Upload a local file to the bucket. If the file already exists in the bucket, it will be overwritten. * @param file File location. * @param destination Name of the file to put in the bucket. If `destination` contains slash character(s), this will put the file inside directories. * @param customMetadata Custom metadata to set to the uploaded file. @@ -221,32 +253,15 @@ export class Bucket { */ public async uploadFile( file: PathLike, - destination: string, + destination?: string, customMetadata?: Record, mimeType?: string ): Promise { const fileStream = createReadStream(file); try { - destination = destination.startsWith('/') ? destination.replace(/^\/+/, '') : destination; - const result = await this.r2.send( - new PutObjectCommand({ - Bucket: this.name, - Key: destination, - Body: fileStream, - ContentType: mimeType || 'application/octet-stream', - Metadata: customMetadata, - }) - ); - + const result = this.upload(fileStream, destination || basename(file.toString()), customMetadata, mimeType); fileStream.close(); - - return { - objectKey: destination, - uri: `${this.uri}/${destination}`, - publicUrl: this.generateObjectPublicUrl(destination), - etag: result.ETag, - versionId: result.VersionId, - }; + return result; } catch (error) { fileStream.close(); throw error; @@ -254,7 +269,84 @@ export class Bucket { } /** - * **DEPRECATED. Use `deleteObject()` instead.** + * Upload an object to the bucket. + * @param contents The object contents to upload. + * @param destination The name of the file to put in the bucket. If `destination` contains slash character(s), this will put the file inside directories. If the file already exists in the bucket, it will be overwritten. + * @param customMetadata Custom metadata to set to the uploaded file. + * @param mimeType Optional mime type. (Default: `application/octet-stream`) + */ + public async upload( + contents: string | Uint8Array | Buffer | Readable | ReadStream, + destination: string, + customMetadata?: Record, + mimeType?: string + ): Promise { + destination = destination.startsWith('/') ? destination.replace(/^\/+/, '') : destination; + + const result = await this.r2.send( + new PutObjectCommand({ + Bucket: this.name, + Key: destination, + Body: contents, + ContentType: mimeType || 'application/octet-stream', + Metadata: customMetadata, + }) + ); + + return { + objectKey: destination, + uri: `${this.uri}/${destination}`, + publicUrl: this.generateObjectPublicUrl(destination), + publicUrls: this.generateObjectPublicUrls(destination), + etag: result.ETag, + versionId: result.VersionId, + }; + } + + /** + * Upload an object or stream to the bucket. This is a new method to put object to the bucket using multipart upload. + * @param contents The object contents to upload. + * @param destination The name of the file to put in the bucket. If `destination` contains slash character(s), this will put the file inside directories. If the file already exists in the bucket, it will be overwritten. + * @param customMetadata Custom metadata to set to the uploaded file. + * @param mimeType Optional mime type. (Default: `application/octet-stream`) + * @param onProgress A callback to handle progress data. + */ + public async uploadStream( + contents: string | Uint8Array | Buffer | Readable | ReadStream, + destination: string, + customMetadata?: Record, + mimeType?: string, + onProgress?: (progress: Progress) => void + ): Promise { + destination = destination.startsWith('/') ? destination.replace(/^\/+/, '') : destination; + + const upload = new Upload({ + client: this.r2, + params: { + Bucket: this.name, + Key: destination, + Body: contents, + ContentType: mimeType || 'application/octet-stream', + Metadata: customMetadata, + }, + }); + + if (onProgress) upload.on('httpUploadProgress', (progress) => onProgress(progress)); + + const result = await upload.done(); + + return { + objectKey: destination, + uri: `${this.uri}/${destination}`, + publicUrl: this.generateObjectPublicUrl(destination), + publicUrls: this.generateObjectPublicUrls(destination), + etag: result.ETag, + versionId: result.VersionId, + }; + } + + /** + * **DEPRECATED. This method will be removed in the next major version. Use `deleteObject()` instead.** * * Deletes a file in the bucket. * @param file @@ -349,21 +441,25 @@ export class Bucket { /** * Copies an object from the current storage bucket to a new destination object in the same bucket. - * @param source The key of the source object to be copied. - * @param destination The key of the destination object where the source object will be copied to. + * @param sourceObjectKey The key of the source object to be copied. + * @param destinationObjectKey The key of the destination object where the source object will be copied to. */ - public async copyObject(source: string, destination: string) { + public async copyObject(sourceObjectKey: string, destinationObjectKey: string) { const result = await this.r2.send( new CopyObjectCommand({ Bucket: this.name, - CopySource: source, - Key: destination, + CopySource: sourceObjectKey, + Key: destinationObjectKey, }) ); return result; } + /** + * Checks if an object exists in the bucket. + * @param objectkey + */ public async objectExists(objectkey: string): Promise { try { const result = await this.headObject(objectkey); diff --git a/src/R2.ts b/src/R2.ts index 7bc0f17..4abc823 100644 --- a/src/R2.ts +++ b/src/R2.ts @@ -1,6 +1,6 @@ import { CreateBucketCommand, DeleteBucketCommand, ListBucketsCommand, S3Client } from '@aws-sdk/client-s3'; import { Bucket } from './Bucket'; -import { BucketList, CORSPolicy, CloudflareR2Config } from './types'; +import type { BucketList, CORSPolicy, CloudflareR2Config } from './types'; export class R2 { private config: CloudflareR2Config; diff --git a/src/types.ts b/src/types.ts index 68a30b2..c8fc870 100644 --- a/src/types.ts +++ b/src/types.ts @@ -15,18 +15,23 @@ export type BucketList = { }; }; -export enum LocationHint { +/* export enum RegionHint { WesternNorthAmerica = 'wnam', EasternNorthAmerica = 'enam', WesternEurope = 'weur', EasternEurope = 'eeur', AsiaPacific = 'apac', -} +} */ export type UploadFileResponse = { objectKey: string; uri: string; + /** + * **DEPRECATED. This property will be remove in the next major version. Use `publicUrls` property instead.** + * @deprecated + */ publicUrl: string | null; + publicUrls: Array; etag?: string; versionId?: string; };