s3mini 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +214 -0
- package/dist/s3mini.d.ts +187 -0
- package/dist/s3mini.js +841 -0
- package/dist/s3mini.js.map +1 -0
- package/dist/s3mini.min.js +2 -0
- package/dist/s3mini.min.js.map +1 -0
- package/package.json +112 -0
- package/src/S3.ts +831 -0
- package/src/consts.ts +38 -0
- package/src/index.ts +20 -0
- package/src/types.ts +88 -0
- package/src/utils.ts +197 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Peter Jensen (good-lly)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# s3mini | Tiny & fast S3 client built for the edge.
|
|
2
|
+
|
|
3
|
+
`s3mini` is an ultra-lightweight TypeScript client (~14 KB minified, β15 % more ops/s) for S3-compatible object storage. It runs on Node, Bun, Cloudflare Workers, and other edge platforms. It has been tested on Cloudflare R2, Backblaze B2, DigitalOcean Spaces, and MinIO. (No Browser support!)
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- π Light and fast: averages β15 % more ops/s and only ~14 KB (minified, not gzipped).
|
|
8
|
+
- π§ Zero dependencies; supports AWS SigV4 (no pre-signed requests).
|
|
9
|
+
- π Works on Cloudflare Workers; ideal for edge computing, Node, and Bun (no browser support).
|
|
10
|
+
- π Only the essential S3 APIsβimproved list, put, get, delete, and a few more.
|
|
11
|
+
- π¦ **BYOS3** β _Bring your own S3-compatible bucket_ (tested on Cloudflare R2, Backblaze B2, DigitalOcean Spaces, MinIO; Ceph and Garage are in the queue).
|
|
12
|
+
|
|
13
|
+

|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
Dev:
|
|
17
|
+

|
|
18
|
+

|
|
19
|
+
[](https://github.com/good-lly/s3mini/actions/workflows/codeql.yml)
|
|
20
|
+
[](https://github.com/good-lly/s3mini/actions/workflows/test-e2e.yml)
|
|
21
|
+
|
|
22
|
+

|
|
23
|
+
|
|
24
|
+
## Table of Contents
|
|
25
|
+
|
|
26
|
+
- [Supported Ops](#supported-ops)
|
|
27
|
+
- [Installation](#installation)
|
|
28
|
+
- [Usage](#usage)
|
|
29
|
+
- [Security Notes](#security-notes)
|
|
30
|
+
- [π Contributions welcomed!](#contributions-welcomed)
|
|
31
|
+
- [License](#license)
|
|
32
|
+
|
|
33
|
+
## Supported Ops
|
|
34
|
+
|
|
35
|
+
The library supports a subset of S3 operations, focusing on essential features, making it suitable for environments with limited resources.
|
|
36
|
+
|
|
37
|
+
#### Bucket ops
|
|
38
|
+
|
|
39
|
+
- β
HeadBucket (bucketExists)
|
|
40
|
+
- β
createBucket (createBucket)
|
|
41
|
+
|
|
42
|
+
#### Objects ops
|
|
43
|
+
|
|
44
|
+
- β
ListObjectsV2 (listObjects)
|
|
45
|
+
- β
GetObject (getObject, getObjectWithETag, getObjectRaw, getObjectArrayBuffer)
|
|
46
|
+
- β
PutObject (putObject)
|
|
47
|
+
- β
DeleteObject (deleteObject)
|
|
48
|
+
- β
HeadObject (objectExists, getEtag, getContentLength)
|
|
49
|
+
- β
listMultipartUploads
|
|
50
|
+
- β
CreateMultipartUpload (getMultipartUploadId)
|
|
51
|
+
- β
completeMultipartUpload
|
|
52
|
+
- β
abortMultipartUpload
|
|
53
|
+
- β
uploadPart
|
|
54
|
+
- β CopyObject: Not implemented (tbd)
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install s3mini
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
yarn add s3mini
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pnpm add s3mini
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Usage
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { s3mini, sanitizeETag } from 's3mini';
|
|
74
|
+
|
|
75
|
+
const s3client = new s3mini({
|
|
76
|
+
accessKeyId: config.accessKeyId,
|
|
77
|
+
secretAccessKey: config.secretAccessKey,
|
|
78
|
+
endpoint: config.endpoint,
|
|
79
|
+
region: config.region,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Basic bucket ops
|
|
83
|
+
let exists: boolean = false;
|
|
84
|
+
try {
|
|
85
|
+
// Check if the bucket exists
|
|
86
|
+
exists = await s3client.bucketExists();
|
|
87
|
+
} catch (err) {
|
|
88
|
+
throw new Error(`Failed bucketExists() call, wrong credentials maybe: ${err.message}`);
|
|
89
|
+
}
|
|
90
|
+
if (!exists) {
|
|
91
|
+
// Create the bucket based on the endpoint bucket name
|
|
92
|
+
await s3client.createBucket();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Basic object ops
|
|
96
|
+
// key is the name of the object in the bucket
|
|
97
|
+
const smallObjectKey: string = 'small-object.txt';
|
|
98
|
+
// content is the data you want to store in the object
|
|
99
|
+
// it can be a string or Buffer (recommended for large objects)
|
|
100
|
+
const smallObjectContent: string = 'Hello, world!';
|
|
101
|
+
|
|
102
|
+
// check if the object exists
|
|
103
|
+
const objectExists: boolean = await s3client.objectExists(smallObjectKey);
|
|
104
|
+
let etag: string | null = null;
|
|
105
|
+
if (!objectExists) {
|
|
106
|
+
// put/upload the object, content can be a string or Buffer
|
|
107
|
+
// to add object into "folder", use "folder/filename.txt" as key
|
|
108
|
+
const resp: Response = await s3client.putObject(smallObjectKey, smallObjectContent);
|
|
109
|
+
// you can also get etag via getEtag method
|
|
110
|
+
// const etag: string = await s3client.getEtag(smallObjectKey);
|
|
111
|
+
etag = sanitizeETag(resp.headers.get('etag'));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// get the object, null if not found
|
|
115
|
+
const objectData: string | null = await s3client.getObject(smallObjectKey);
|
|
116
|
+
console.log('Object data:', objectData);
|
|
117
|
+
|
|
118
|
+
// get the object with ETag, null if not found
|
|
119
|
+
const response2: Response = await s3mini.getObject(smallObjectKey, { 'if-none-match': etag });
|
|
120
|
+
if (response2) {
|
|
121
|
+
// ETag changed so we can get the object data and new ETag
|
|
122
|
+
// Note: ETag is not guaranteed to be the same as the MD5 hash of the object
|
|
123
|
+
// ETag is sanitized to remove quotes
|
|
124
|
+
const etag2: string = sanitizeETag(response2.headers.get('etag'));
|
|
125
|
+
console.log('Object data with ETag:', response2.body, 'ETag:', etag2);
|
|
126
|
+
} else {
|
|
127
|
+
console.log('Object not found or ETag does match.');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// list objects in the bucket, null if bucket is empty
|
|
131
|
+
// Note: listObjects uses listObjectsV2 API and iterate over all pages
|
|
132
|
+
// so it will return all objects in the bucket which can take a while
|
|
133
|
+
// If you want to limit the number of objects returned, use the maxKeys option
|
|
134
|
+
// If you want to list objects in a specific "folder", use "folder/" as prefix
|
|
135
|
+
// Example s3client.listObjects({"/" "myfolder/"})
|
|
136
|
+
const list: object[] | null = await s3client.listObjects();
|
|
137
|
+
if (list) {
|
|
138
|
+
console.log('List of objects:', list);
|
|
139
|
+
} else {
|
|
140
|
+
console.log('No objects found in the bucket.');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// delete the object
|
|
144
|
+
const wasDeleted: boolean = await s3client.deleteObject(smallObjectKey);
|
|
145
|
+
|
|
146
|
+
// Multipart upload
|
|
147
|
+
const multipartKey = 'multipart-object.txt';
|
|
148
|
+
const large_buffer = new Uint8Array(1024 * 1024 * 15); // 15 MB buffer
|
|
149
|
+
const partSize = 8 * 1024 * 1024; // 8 MB
|
|
150
|
+
const totalParts = Math.ceil(large_buffer.length / partSize);
|
|
151
|
+
// Beware! This will return always a new uploadId
|
|
152
|
+
// if you want to use the same uploadId, you need to store it somewhere
|
|
153
|
+
const uploadId = await s3client.getMultipartUploadId(multipartKey);
|
|
154
|
+
const uploadPromises = [];
|
|
155
|
+
for (let i = 0; i < totalParts; i++) {
|
|
156
|
+
const partBuffer = large_buffer.subarray(i * partSize, (i + 1) * partSize);
|
|
157
|
+
// upload each part
|
|
158
|
+
// Note: uploadPart returns a promise, so you can use Promise.all to upload all parts in parallel
|
|
159
|
+
// but be careful with the number of parallel uploads, it can cause throttling
|
|
160
|
+
// or errors if you upload too many parts at once
|
|
161
|
+
// You can also use generator functions to upload parts in batches
|
|
162
|
+
uploadPromises.push(s3client.uploadPart(multipartKey, uploadId, partBuffer, i + 1));
|
|
163
|
+
}
|
|
164
|
+
const uploadResponses = await Promise.all(uploadPromises);
|
|
165
|
+
const parts = uploadResponses.map((response, index) => ({
|
|
166
|
+
partNumber: index + 1,
|
|
167
|
+
etag: response.etag,
|
|
168
|
+
}));
|
|
169
|
+
// Complete the multipart upload
|
|
170
|
+
const completeResponse = await s3client.completeMultipartUpload(multipartKey, uploadId, parts);
|
|
171
|
+
const completeEtag = completeResponse.etag;
|
|
172
|
+
|
|
173
|
+
// List multipart uploads
|
|
174
|
+
// returns object with uploadId and key
|
|
175
|
+
const multipartUploads: object = await s3client.listMultipartUploads();
|
|
176
|
+
// Abort the multipart upload
|
|
177
|
+
const abortResponse = await s3client.abortMultipartUpload(multipartUploads.key, multipartUploads.uploadId);
|
|
178
|
+
|
|
179
|
+
// Multipart download
|
|
180
|
+
// lets test getObjectRaw with range
|
|
181
|
+
const rangeStart = 2048 * 1024; // 2 MB
|
|
182
|
+
const rangeEnd = 8 * 1024 * 1024 * 2; // 16 MB
|
|
183
|
+
const rangeResponse = await s3client.getObjectRaw(multipartKey, false, rangeStart, rangeEnd);
|
|
184
|
+
const rangeData = await rangeResponse.arrayBuffer();
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
For more check [USAGE.md](USAGE.md) file, examples and tests.
|
|
188
|
+
|
|
189
|
+
## Security Notes
|
|
190
|
+
|
|
191
|
+
- The library masks sensitive information (access keys, session tokens, etc.) when logging.
|
|
192
|
+
- Always protect your AWS credentials and avoid hard-coding them in your application (!!!). Use environment variables. Use environment variables or a secure vault for storing credentials.
|
|
193
|
+
- Ensure you have the necessary permissions to access the S3 bucket and perform operations.
|
|
194
|
+
- Be cautious when using multipart uploads, as they can incur additional costs if not managed properly.
|
|
195
|
+
- Authors are not responsible for any data loss or security breaches resulting from improper usage of the library.
|
|
196
|
+
- If you find a security vulnerability, please report it to us directly via email. For more details, please refer to the [SECURITY.md](SECURITY.md) file.
|
|
197
|
+
|
|
198
|
+
## Contributions welcomed!
|
|
199
|
+
|
|
200
|
+
Contributions are greatly appreciated! If you have an idea for a new feature or have found a bug, we encourage you to get involved:
|
|
201
|
+
|
|
202
|
+
- _Report Issues_: If you encounter a problem or have a feature request, please open an issue on GitHub. Include as much detail as possible (environment, error messages, logs, steps to reproduce, etc.) so we can understand and address the issue.
|
|
203
|
+
|
|
204
|
+
- _Pull Requests_: We welcome PRs! If you want to implement a new feature or fix a bug, feel free to submit a pull request to the latest `dev branch`. For major changes, it's a good idea to discuss your plans in an issue first.
|
|
205
|
+
|
|
206
|
+
- _Lightweight Philosophy_: When contributing, keep in mind that s3mini aims to remain lightweight and dependency-free. Please avoid adding heavy dependencies. New features should provide significant value to justify any increase in size.
|
|
207
|
+
|
|
208
|
+
- _Community Conduct_: Be respectful and constructive in communications. We want a welcoming environment for all contributors. For more details, please refer to our [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). No one reads it, but it's there for a reason.
|
|
209
|
+
|
|
210
|
+
If you figure out a solution to your question or problem on your own, please consider posting the answer or closing the issue with an explanation. It could help the next person who runs into the same thing!
|
|
211
|
+
|
|
212
|
+
## License
|
|
213
|
+
|
|
214
|
+
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.
|
package/dist/s3mini.d.ts
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
interface S3Config {
|
|
2
|
+
accessKeyId: string;
|
|
3
|
+
secretAccessKey: string;
|
|
4
|
+
endpoint: string;
|
|
5
|
+
region?: string;
|
|
6
|
+
requestSizeInBytes?: number;
|
|
7
|
+
requestAbortTimeout?: number;
|
|
8
|
+
logger?: Logger;
|
|
9
|
+
}
|
|
10
|
+
interface Logger {
|
|
11
|
+
info: (message: string, ...args: unknown[]) => void;
|
|
12
|
+
warn: (message: string, ...args: unknown[]) => void;
|
|
13
|
+
error: (message: string, ...args: unknown[]) => void;
|
|
14
|
+
}
|
|
15
|
+
interface UploadPart {
|
|
16
|
+
partNumber: number;
|
|
17
|
+
etag: string;
|
|
18
|
+
}
|
|
19
|
+
interface CompleteMultipartUploadResult {
|
|
20
|
+
location: string;
|
|
21
|
+
bucket: string;
|
|
22
|
+
key: string;
|
|
23
|
+
etag: string;
|
|
24
|
+
eTag: string;
|
|
25
|
+
ETag: string;
|
|
26
|
+
}
|
|
27
|
+
interface ListBucketResult {
|
|
28
|
+
keyCount: string;
|
|
29
|
+
contents?: Array<Record<string, unknown>>;
|
|
30
|
+
}
|
|
31
|
+
interface ListBucketError {
|
|
32
|
+
error: {
|
|
33
|
+
code: string;
|
|
34
|
+
message: string;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
type ListBucketResponse = {
|
|
38
|
+
listBucketResult: ListBucketResult;
|
|
39
|
+
} | {
|
|
40
|
+
error: ListBucketError;
|
|
41
|
+
};
|
|
42
|
+
interface ListMultipartUploadSuccess {
|
|
43
|
+
listMultipartUploadsResult: {
|
|
44
|
+
bucket: string;
|
|
45
|
+
key: string;
|
|
46
|
+
uploadId: string;
|
|
47
|
+
size?: number;
|
|
48
|
+
mtime?: Date | undefined;
|
|
49
|
+
etag?: string;
|
|
50
|
+
eTag?: string;
|
|
51
|
+
parts: UploadPart[];
|
|
52
|
+
isTruncated: boolean;
|
|
53
|
+
uploads: UploadPart[];
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
interface MultipartUploadError {
|
|
57
|
+
error: {
|
|
58
|
+
code: string;
|
|
59
|
+
message: string;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
interface ErrorWithCode {
|
|
63
|
+
code?: string;
|
|
64
|
+
cause?: {
|
|
65
|
+
code?: string;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
type ListMultipartUploadResponse = ListMultipartUploadSuccess | MultipartUploadError;
|
|
69
|
+
type HttpMethod = 'POST' | 'GET' | 'HEAD' | 'PUT' | 'DELETE';
|
|
70
|
+
type ExistResponseCode = false | true | null;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* S3 class for interacting with S3-compatible object storage services.
|
|
74
|
+
* This class provides methods for common S3 operations such as uploading, downloading,
|
|
75
|
+
* and deleting objects, as well as multipart uploads.
|
|
76
|
+
*
|
|
77
|
+
* @class
|
|
78
|
+
* @example
|
|
79
|
+
* const s3 = new CoreS3({
|
|
80
|
+
* accessKeyId: 'your-access-key',
|
|
81
|
+
* secretAccessKey: 'your-secret-key',
|
|
82
|
+
* endpoint: 'https://your-s3-endpoint.com',
|
|
83
|
+
* region: 'us-east-1' // by default is auto
|
|
84
|
+
* });
|
|
85
|
+
*
|
|
86
|
+
* // Upload a file
|
|
87
|
+
* await s3.putObject('example.txt', 'Hello, World!');
|
|
88
|
+
*
|
|
89
|
+
* // Download a file
|
|
90
|
+
* const content = await s3.getObject('example.txt');
|
|
91
|
+
*
|
|
92
|
+
* // Delete a file
|
|
93
|
+
* await s3.deleteObject('example.txt');
|
|
94
|
+
*/
|
|
95
|
+
declare class s3mini {
|
|
96
|
+
/**
|
|
97
|
+
* Creates an instance of the S3 class.
|
|
98
|
+
*
|
|
99
|
+
* @constructor
|
|
100
|
+
* @param {Object} config - Configuration options for the S3 instance.
|
|
101
|
+
* @param {string} config.accessKeyId - The access key ID for authentication.
|
|
102
|
+
* @param {string} config.secretAccessKey - The secret access key for authentication.
|
|
103
|
+
* @param {string} config.endpoint - The endpoint URL of the S3-compatible service.
|
|
104
|
+
* @param {string} [config.region='auto'] - The region of the S3 service.
|
|
105
|
+
* @param {number} [config.requestSizeInBytes=8388608] - The request size of a single request in bytes (AWS S3 is 8MB).
|
|
106
|
+
* @param {number} [config.requestAbortTimeout=undefined] - The timeout in milliseconds after which a request should be aborted (careful on streamed requests).
|
|
107
|
+
* @param {Object} [config.logger=null] - A logger object with methods like info, warn, error.
|
|
108
|
+
* @throws {TypeError} Will throw an error if required parameters are missing or of incorrect type.
|
|
109
|
+
*/
|
|
110
|
+
private accessKeyId;
|
|
111
|
+
private secretAccessKey;
|
|
112
|
+
private endpoint;
|
|
113
|
+
private region;
|
|
114
|
+
private requestSizeInBytes;
|
|
115
|
+
private requestAbortTimeout?;
|
|
116
|
+
private logger?;
|
|
117
|
+
private fullDatetime;
|
|
118
|
+
private shortDatetime;
|
|
119
|
+
private signingKey;
|
|
120
|
+
private credentialScope;
|
|
121
|
+
constructor({ accessKeyId, secretAccessKey, endpoint, region, requestSizeInBytes, requestAbortTimeout, logger, }: S3Config);
|
|
122
|
+
private _sanitize;
|
|
123
|
+
private _log;
|
|
124
|
+
private _validateConstructorParams;
|
|
125
|
+
private _ensureValidUrl;
|
|
126
|
+
private _validateMethodIsGetOrHead;
|
|
127
|
+
private _checkKey;
|
|
128
|
+
private _checkDelimiter;
|
|
129
|
+
private _checkPrefix;
|
|
130
|
+
private _checkOpts;
|
|
131
|
+
private _filterIfHeaders;
|
|
132
|
+
private _validateUploadPartParams;
|
|
133
|
+
private _sign;
|
|
134
|
+
private _buildCanonicalHeaders;
|
|
135
|
+
private _buildCanonicalRequest;
|
|
136
|
+
private _buildStringToSign;
|
|
137
|
+
private _calculateSignature;
|
|
138
|
+
private _buildAuthorizationHeader;
|
|
139
|
+
private _signedRequest;
|
|
140
|
+
getProps(): S3Config;
|
|
141
|
+
setProps(props: S3Config): void;
|
|
142
|
+
sanitizeETag(etag: string): string;
|
|
143
|
+
createBucket(): Promise<boolean>;
|
|
144
|
+
bucketExists(): Promise<boolean>;
|
|
145
|
+
listObjects(delimiter?: string, prefix?: string, maxKeys?: number, opts?: Record<string, unknown>): Promise<object[] | null>;
|
|
146
|
+
listMultipartUploads(delimiter?: string, prefix?: string, method?: HttpMethod, opts?: Record<string, string | number | boolean | undefined>): Promise<ListMultipartUploadSuccess | MultipartUploadError>;
|
|
147
|
+
getObject(key: string, opts?: Record<string, unknown>): Promise<string | null>;
|
|
148
|
+
getObjectArrayBuffer(key: string, opts?: Record<string, unknown>): Promise<ArrayBuffer | null>;
|
|
149
|
+
getObjectWithETag(key: string, opts?: Record<string, unknown>): Promise<{
|
|
150
|
+
etag: string | null;
|
|
151
|
+
data: ArrayBuffer | null;
|
|
152
|
+
}>;
|
|
153
|
+
getObjectRaw(key: string, wholeFile?: boolean, rangeFrom?: number, rangeTo?: number, opts?: Record<string, unknown>): Promise<Response>;
|
|
154
|
+
getContentLength(key: string): Promise<number>;
|
|
155
|
+
objectExists(key: string, opts?: Record<string, unknown>): Promise<ExistResponseCode>;
|
|
156
|
+
getEtag(key: string, opts?: Record<string, unknown>): Promise<string | null>;
|
|
157
|
+
putObject(key: string, data: string | Buffer): Promise<Response>;
|
|
158
|
+
getMultipartUploadId(key: string, fileType?: string): Promise<string>;
|
|
159
|
+
uploadPart(key: string, uploadId: string, data: Buffer | string, partNumber: number, opts?: Record<string, unknown>): Promise<UploadPart>;
|
|
160
|
+
completeMultipartUpload(key: string, uploadId: string, parts: Array<UploadPart>): Promise<CompleteMultipartUploadResult>;
|
|
161
|
+
abortMultipartUpload(key: string, uploadId: string): Promise<object>;
|
|
162
|
+
private _buildCompleteMultipartUploadXml;
|
|
163
|
+
deleteObject(key: string): Promise<boolean>;
|
|
164
|
+
private _sendRequest;
|
|
165
|
+
private _handleErrorResponse;
|
|
166
|
+
private _buildCanonicalQueryString;
|
|
167
|
+
private _getSignatureKey;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Sanitize ETag value by removing quotes and XML entities
|
|
172
|
+
* @param etag ETag value to sanitize
|
|
173
|
+
* @returns Sanitized ETag
|
|
174
|
+
*/
|
|
175
|
+
declare const sanitizeETag: (etag: string) => string;
|
|
176
|
+
/**
|
|
177
|
+
* Run async-returning tasks in batches with an *optional* minimum
|
|
178
|
+
* spacing (minIntervalMs) between the *start* times of successive batches.
|
|
179
|
+
*
|
|
180
|
+
* @param {Iterable<() => Promise<unknonw>>} tasks β functions returning Promises
|
|
181
|
+
* @param {number} [batchSize=30] β max concurrent requests
|
|
182
|
+
* @param {number} [minIntervalMs=0] β β₯0; 0 means βno pacingβ
|
|
183
|
+
* @returns {Promise<Array<PromiseSettledResult<unknonw>>>}
|
|
184
|
+
*/
|
|
185
|
+
declare const runInBatches: (tasks: Iterable<() => Promise<unknown>>, batchSize?: number, minIntervalMs?: number) => Promise<Array<PromiseSettledResult<unknown>>>;
|
|
186
|
+
|
|
187
|
+
export { type CompleteMultipartUploadResult, type ErrorWithCode, type ExistResponseCode, type ListBucketResponse, type ListMultipartUploadResponse, type Logger, type S3Config, type UploadPart, s3mini as default, runInBatches, s3mini, sanitizeETag };
|