@better-media/adapter-storage-s3 0.1.0 → 0.2.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/README.md +19 -5
- package/dist/index.d.mts +107 -2
- package/dist/index.d.ts +107 -2
- package/dist/index.js +381 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +381 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -4,21 +4,35 @@ Amazon S3 and S3-compatible storage adapter for the Better Media framework.
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **S3 Support**: Works with AWS S3,
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
7
|
+
- **S3 Support**: Works with AWS S3, MinIO, DigitalOcean Spaces, Cloudflare R2, etc.
|
|
8
|
+
- **Dynamic Buckets**: Supports function-based bucket resolution dynamically per file key.
|
|
9
|
+
- **Presigned URLs**: Securely upload from or download to the browser without exposing credentials using both PUT and POST policies.
|
|
10
|
+
- **Bulk & Directory Operations**: Native support for bulk deletions, moving, copying, and directory enumeration.
|
|
11
|
+
- **Multipart Uploads**: Deeply integrated support for chunked uploading sequences.
|
|
12
|
+
- **Bucket Lifecycle & CORS**: Configure S3 buckets programmatically via the adapter.
|
|
10
13
|
|
|
11
14
|
## Usage
|
|
12
15
|
|
|
13
16
|
```ts
|
|
14
17
|
import { S3StorageAdapter } from "@better-media/adapter-storage-s3";
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
// AWS S3 Example
|
|
20
|
+
const s3Storage = new S3StorageAdapter({
|
|
17
21
|
region: "us-east-1",
|
|
18
22
|
bucket: "media-bucket",
|
|
19
23
|
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
20
24
|
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
21
25
|
});
|
|
26
|
+
|
|
27
|
+
// MinIO / Custom Endpoint Example
|
|
28
|
+
const minioStorage = new S3StorageAdapter({
|
|
29
|
+
region: "us-east-1",
|
|
30
|
+
bucket: "local-bucket",
|
|
31
|
+
accessKeyId: "minio-root-user",
|
|
32
|
+
secretAccessKey: "minio-root-password",
|
|
33
|
+
endpoint: "http://localhost:9000",
|
|
34
|
+
forcePathStyle: true,
|
|
35
|
+
});
|
|
22
36
|
```
|
|
23
37
|
|
|
24
|
-
See [better-media.
|
|
38
|
+
See [better-media-platform.vercel.app/docs/adapters/storage-s3](https://better-media-platform.vercel.app/docs/adapters/storage-s3) for more details.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Buffer } from 'node:buffer';
|
|
2
|
+
import { StorageAdapter, ListOptions, ListResult, GetUrlOptions, PresignedUploadOptions, PresignedUploadResult } from '@better-media/core';
|
|
2
3
|
|
|
3
4
|
interface S3StorageConfig {
|
|
4
5
|
/** AWS region (e.g. "us-east-1") */
|
|
@@ -21,6 +22,76 @@ interface S3StorageConfig {
|
|
|
21
22
|
forcePathStyle?: boolean;
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
declare enum EnumS3Accessibility {
|
|
26
|
+
public = "public",
|
|
27
|
+
private = "private"
|
|
28
|
+
}
|
|
29
|
+
interface S3Object {
|
|
30
|
+
bucket: string;
|
|
31
|
+
key: string;
|
|
32
|
+
cdnUrl?: string;
|
|
33
|
+
completedUrl: string;
|
|
34
|
+
mime: string;
|
|
35
|
+
extension: string;
|
|
36
|
+
access?: EnumS3Accessibility;
|
|
37
|
+
size: number;
|
|
38
|
+
data?: unknown;
|
|
39
|
+
}
|
|
40
|
+
interface S3MultipartPart {
|
|
41
|
+
size: number;
|
|
42
|
+
eTag: string;
|
|
43
|
+
partNumber: number;
|
|
44
|
+
}
|
|
45
|
+
interface S3Multipart {
|
|
46
|
+
bucket: string;
|
|
47
|
+
key: string;
|
|
48
|
+
uploadId: string;
|
|
49
|
+
lastPartNumber: number;
|
|
50
|
+
maxPartNumber: number;
|
|
51
|
+
parts: S3MultipartPart[];
|
|
52
|
+
}
|
|
53
|
+
interface S3Presign {
|
|
54
|
+
key: string;
|
|
55
|
+
mime: string;
|
|
56
|
+
extension: string;
|
|
57
|
+
presignUrl: string;
|
|
58
|
+
expiredIn: number;
|
|
59
|
+
}
|
|
60
|
+
interface S3PresignPart extends S3Presign {
|
|
61
|
+
size: number;
|
|
62
|
+
partNumber: number;
|
|
63
|
+
}
|
|
64
|
+
interface S3Options {
|
|
65
|
+
access?: EnumS3Accessibility;
|
|
66
|
+
}
|
|
67
|
+
interface S3PutItemOptions extends S3Options {
|
|
68
|
+
forceUpdate?: boolean;
|
|
69
|
+
}
|
|
70
|
+
interface S3GetItemsOptions extends S3Options {
|
|
71
|
+
continuationToken?: string;
|
|
72
|
+
}
|
|
73
|
+
type S3DeleteDirOptions = S3GetItemsOptions;
|
|
74
|
+
interface S3PresignGetItemOptions extends S3Options {
|
|
75
|
+
expired?: number;
|
|
76
|
+
}
|
|
77
|
+
interface S3PresignPutItemOptions extends S3PutItemOptions {
|
|
78
|
+
expired?: number;
|
|
79
|
+
}
|
|
80
|
+
interface S3PresignPutItemPartOptions extends S3Options {
|
|
81
|
+
expired?: number;
|
|
82
|
+
}
|
|
83
|
+
interface S3MoveItemOptions {
|
|
84
|
+
accessFrom?: EnumS3Accessibility;
|
|
85
|
+
accessTo?: EnumS3Accessibility;
|
|
86
|
+
}
|
|
87
|
+
interface S3CreateMultiplePart {
|
|
88
|
+
key: string;
|
|
89
|
+
size?: number;
|
|
90
|
+
}
|
|
91
|
+
interface S3PutItem extends S3CreateMultiplePart {
|
|
92
|
+
file: Buffer;
|
|
93
|
+
}
|
|
94
|
+
|
|
24
95
|
/**
|
|
25
96
|
* S3 storage adapter for production deployments.
|
|
26
97
|
* Supports AWS S3 and S3-compatible object storage (MinIO, etc.).
|
|
@@ -28,16 +99,50 @@ interface S3StorageConfig {
|
|
|
28
99
|
declare class S3StorageAdapter implements StorageAdapter {
|
|
29
100
|
private readonly client;
|
|
30
101
|
private readonly bucketResolver;
|
|
102
|
+
private readonly region;
|
|
103
|
+
private readonly endpoint?;
|
|
104
|
+
private readonly forcePathStyle;
|
|
31
105
|
constructor(config: S3StorageConfig);
|
|
32
106
|
private isNotFoundError;
|
|
33
107
|
private getBucket;
|
|
108
|
+
private getPublicUrl;
|
|
34
109
|
get(key: string): Promise<Buffer | null>;
|
|
35
110
|
put(key: string, value: Buffer): Promise<void>;
|
|
36
111
|
delete(key: string): Promise<void>;
|
|
37
112
|
exists(key: string): Promise<boolean>;
|
|
113
|
+
checkConnection(): Promise<boolean>;
|
|
114
|
+
checkBucket(_options?: S3Options): Promise<boolean>;
|
|
115
|
+
checkItem(key: string, _options?: S3Options): Promise<S3Object>;
|
|
116
|
+
getItem(key: string, _options?: S3Options): Promise<S3Object>;
|
|
117
|
+
putItem(file: S3PutItem, _options?: S3PutItemOptions): Promise<S3Object>;
|
|
38
118
|
getSize(key: string): Promise<number | null>;
|
|
39
119
|
getStream(key: string): Promise<ReadableStream<Uint8Array> | null>;
|
|
120
|
+
list(prefix: string, options?: ListOptions): Promise<ListResult>;
|
|
121
|
+
getItems(path: string, options?: S3GetItemsOptions): Promise<S3Object[]>;
|
|
122
|
+
deleteMany(keys: string[]): Promise<void>;
|
|
123
|
+
deleteItems(keys: string[], _options?: S3Options): Promise<void>;
|
|
124
|
+
deleteDir(path: string, options?: S3DeleteDirOptions): Promise<void>;
|
|
125
|
+
copy(source: string, destination: string): Promise<void>;
|
|
126
|
+
move(source: string, destination: string): Promise<void>;
|
|
127
|
+
moveItem(source: S3Object, destinationKey: string, _options?: S3MoveItemOptions): Promise<S3Object>;
|
|
128
|
+
moveItems(sources: S3Object[], destinationPrefix: string, _options?: S3Options): Promise<S3Object[]>;
|
|
129
|
+
createMultiPart(file: S3CreateMultiplePart, maxPartNumber: number, _options?: S3Options): Promise<S3Multipart>;
|
|
130
|
+
putItemMultiPart(multipart: S3Multipart, partNumber: number, file: Buffer, _options?: S3Options): Promise<S3Multipart>;
|
|
131
|
+
completeMultipart(key: string, uploadId: string, parts: S3MultipartPart[], _options?: S3Options): Promise<void>;
|
|
132
|
+
abortMultipart(key: string, uploadId: string, _options?: S3Options): Promise<void>;
|
|
40
133
|
getUrl(key: string, options?: GetUrlOptions): Promise<string>;
|
|
134
|
+
presignGetItem(key: string, options?: S3PresignGetItemOptions): Promise<S3Presign>;
|
|
135
|
+
presignPutItem(file: S3CreateMultiplePart, options?: S3PresignPutItemOptions): Promise<S3Presign>;
|
|
136
|
+
presignPutItemPart(file: S3CreateMultiplePart & {
|
|
137
|
+
uploadId: string;
|
|
138
|
+
partNumber: number;
|
|
139
|
+
}, options?: S3PresignPutItemPartOptions): Promise<S3PresignPart>;
|
|
140
|
+
settingBucketPolicy(_options?: S3Options): Promise<void>;
|
|
141
|
+
settingCorsConfiguration(_options?: S3Options): Promise<void>;
|
|
142
|
+
settingBucketExpiredObjectLifecycle(_options: S3Options): Promise<void>;
|
|
143
|
+
settingDisableAclConfiguration(_options?: S3Options): Promise<void>;
|
|
144
|
+
settingBlockPublicAccessConfiguration(_options?: S3Options): Promise<void>;
|
|
145
|
+
mapPresign(file: S3CreateMultiplePart, _options?: S3Options): S3Object;
|
|
41
146
|
/**
|
|
42
147
|
* Create a presigned upload for direct-to-storage upload.
|
|
43
148
|
*
|
|
@@ -54,4 +159,4 @@ declare class S3StorageAdapter implements StorageAdapter {
|
|
|
54
159
|
private _createPresignedPut;
|
|
55
160
|
}
|
|
56
161
|
|
|
57
|
-
export { S3StorageAdapter, type S3StorageConfig };
|
|
162
|
+
export { EnumS3Accessibility, type S3CreateMultiplePart, type S3DeleteDirOptions, type S3GetItemsOptions, type S3MoveItemOptions, type S3Multipart, type S3MultipartPart, type S3Object, type S3Options, type S3Presign, type S3PresignGetItemOptions, type S3PresignPart, type S3PresignPutItemOptions, type S3PresignPutItemPartOptions, type S3PutItem, type S3PutItemOptions, S3StorageAdapter, type S3StorageConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Buffer } from 'node:buffer';
|
|
2
|
+
import { StorageAdapter, ListOptions, ListResult, GetUrlOptions, PresignedUploadOptions, PresignedUploadResult } from '@better-media/core';
|
|
2
3
|
|
|
3
4
|
interface S3StorageConfig {
|
|
4
5
|
/** AWS region (e.g. "us-east-1") */
|
|
@@ -21,6 +22,76 @@ interface S3StorageConfig {
|
|
|
21
22
|
forcePathStyle?: boolean;
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
declare enum EnumS3Accessibility {
|
|
26
|
+
public = "public",
|
|
27
|
+
private = "private"
|
|
28
|
+
}
|
|
29
|
+
interface S3Object {
|
|
30
|
+
bucket: string;
|
|
31
|
+
key: string;
|
|
32
|
+
cdnUrl?: string;
|
|
33
|
+
completedUrl: string;
|
|
34
|
+
mime: string;
|
|
35
|
+
extension: string;
|
|
36
|
+
access?: EnumS3Accessibility;
|
|
37
|
+
size: number;
|
|
38
|
+
data?: unknown;
|
|
39
|
+
}
|
|
40
|
+
interface S3MultipartPart {
|
|
41
|
+
size: number;
|
|
42
|
+
eTag: string;
|
|
43
|
+
partNumber: number;
|
|
44
|
+
}
|
|
45
|
+
interface S3Multipart {
|
|
46
|
+
bucket: string;
|
|
47
|
+
key: string;
|
|
48
|
+
uploadId: string;
|
|
49
|
+
lastPartNumber: number;
|
|
50
|
+
maxPartNumber: number;
|
|
51
|
+
parts: S3MultipartPart[];
|
|
52
|
+
}
|
|
53
|
+
interface S3Presign {
|
|
54
|
+
key: string;
|
|
55
|
+
mime: string;
|
|
56
|
+
extension: string;
|
|
57
|
+
presignUrl: string;
|
|
58
|
+
expiredIn: number;
|
|
59
|
+
}
|
|
60
|
+
interface S3PresignPart extends S3Presign {
|
|
61
|
+
size: number;
|
|
62
|
+
partNumber: number;
|
|
63
|
+
}
|
|
64
|
+
interface S3Options {
|
|
65
|
+
access?: EnumS3Accessibility;
|
|
66
|
+
}
|
|
67
|
+
interface S3PutItemOptions extends S3Options {
|
|
68
|
+
forceUpdate?: boolean;
|
|
69
|
+
}
|
|
70
|
+
interface S3GetItemsOptions extends S3Options {
|
|
71
|
+
continuationToken?: string;
|
|
72
|
+
}
|
|
73
|
+
type S3DeleteDirOptions = S3GetItemsOptions;
|
|
74
|
+
interface S3PresignGetItemOptions extends S3Options {
|
|
75
|
+
expired?: number;
|
|
76
|
+
}
|
|
77
|
+
interface S3PresignPutItemOptions extends S3PutItemOptions {
|
|
78
|
+
expired?: number;
|
|
79
|
+
}
|
|
80
|
+
interface S3PresignPutItemPartOptions extends S3Options {
|
|
81
|
+
expired?: number;
|
|
82
|
+
}
|
|
83
|
+
interface S3MoveItemOptions {
|
|
84
|
+
accessFrom?: EnumS3Accessibility;
|
|
85
|
+
accessTo?: EnumS3Accessibility;
|
|
86
|
+
}
|
|
87
|
+
interface S3CreateMultiplePart {
|
|
88
|
+
key: string;
|
|
89
|
+
size?: number;
|
|
90
|
+
}
|
|
91
|
+
interface S3PutItem extends S3CreateMultiplePart {
|
|
92
|
+
file: Buffer;
|
|
93
|
+
}
|
|
94
|
+
|
|
24
95
|
/**
|
|
25
96
|
* S3 storage adapter for production deployments.
|
|
26
97
|
* Supports AWS S3 and S3-compatible object storage (MinIO, etc.).
|
|
@@ -28,16 +99,50 @@ interface S3StorageConfig {
|
|
|
28
99
|
declare class S3StorageAdapter implements StorageAdapter {
|
|
29
100
|
private readonly client;
|
|
30
101
|
private readonly bucketResolver;
|
|
102
|
+
private readonly region;
|
|
103
|
+
private readonly endpoint?;
|
|
104
|
+
private readonly forcePathStyle;
|
|
31
105
|
constructor(config: S3StorageConfig);
|
|
32
106
|
private isNotFoundError;
|
|
33
107
|
private getBucket;
|
|
108
|
+
private getPublicUrl;
|
|
34
109
|
get(key: string): Promise<Buffer | null>;
|
|
35
110
|
put(key: string, value: Buffer): Promise<void>;
|
|
36
111
|
delete(key: string): Promise<void>;
|
|
37
112
|
exists(key: string): Promise<boolean>;
|
|
113
|
+
checkConnection(): Promise<boolean>;
|
|
114
|
+
checkBucket(_options?: S3Options): Promise<boolean>;
|
|
115
|
+
checkItem(key: string, _options?: S3Options): Promise<S3Object>;
|
|
116
|
+
getItem(key: string, _options?: S3Options): Promise<S3Object>;
|
|
117
|
+
putItem(file: S3PutItem, _options?: S3PutItemOptions): Promise<S3Object>;
|
|
38
118
|
getSize(key: string): Promise<number | null>;
|
|
39
119
|
getStream(key: string): Promise<ReadableStream<Uint8Array> | null>;
|
|
120
|
+
list(prefix: string, options?: ListOptions): Promise<ListResult>;
|
|
121
|
+
getItems(path: string, options?: S3GetItemsOptions): Promise<S3Object[]>;
|
|
122
|
+
deleteMany(keys: string[]): Promise<void>;
|
|
123
|
+
deleteItems(keys: string[], _options?: S3Options): Promise<void>;
|
|
124
|
+
deleteDir(path: string, options?: S3DeleteDirOptions): Promise<void>;
|
|
125
|
+
copy(source: string, destination: string): Promise<void>;
|
|
126
|
+
move(source: string, destination: string): Promise<void>;
|
|
127
|
+
moveItem(source: S3Object, destinationKey: string, _options?: S3MoveItemOptions): Promise<S3Object>;
|
|
128
|
+
moveItems(sources: S3Object[], destinationPrefix: string, _options?: S3Options): Promise<S3Object[]>;
|
|
129
|
+
createMultiPart(file: S3CreateMultiplePart, maxPartNumber: number, _options?: S3Options): Promise<S3Multipart>;
|
|
130
|
+
putItemMultiPart(multipart: S3Multipart, partNumber: number, file: Buffer, _options?: S3Options): Promise<S3Multipart>;
|
|
131
|
+
completeMultipart(key: string, uploadId: string, parts: S3MultipartPart[], _options?: S3Options): Promise<void>;
|
|
132
|
+
abortMultipart(key: string, uploadId: string, _options?: S3Options): Promise<void>;
|
|
40
133
|
getUrl(key: string, options?: GetUrlOptions): Promise<string>;
|
|
134
|
+
presignGetItem(key: string, options?: S3PresignGetItemOptions): Promise<S3Presign>;
|
|
135
|
+
presignPutItem(file: S3CreateMultiplePart, options?: S3PresignPutItemOptions): Promise<S3Presign>;
|
|
136
|
+
presignPutItemPart(file: S3CreateMultiplePart & {
|
|
137
|
+
uploadId: string;
|
|
138
|
+
partNumber: number;
|
|
139
|
+
}, options?: S3PresignPutItemPartOptions): Promise<S3PresignPart>;
|
|
140
|
+
settingBucketPolicy(_options?: S3Options): Promise<void>;
|
|
141
|
+
settingCorsConfiguration(_options?: S3Options): Promise<void>;
|
|
142
|
+
settingBucketExpiredObjectLifecycle(_options: S3Options): Promise<void>;
|
|
143
|
+
settingDisableAclConfiguration(_options?: S3Options): Promise<void>;
|
|
144
|
+
settingBlockPublicAccessConfiguration(_options?: S3Options): Promise<void>;
|
|
145
|
+
mapPresign(file: S3CreateMultiplePart, _options?: S3Options): S3Object;
|
|
41
146
|
/**
|
|
42
147
|
* Create a presigned upload for direct-to-storage upload.
|
|
43
148
|
*
|
|
@@ -54,4 +159,4 @@ declare class S3StorageAdapter implements StorageAdapter {
|
|
|
54
159
|
private _createPresignedPut;
|
|
55
160
|
}
|
|
56
161
|
|
|
57
|
-
export { S3StorageAdapter, type S3StorageConfig };
|
|
162
|
+
export { EnumS3Accessibility, type S3CreateMultiplePart, type S3DeleteDirOptions, type S3GetItemsOptions, type S3MoveItemOptions, type S3Multipart, type S3MultipartPart, type S3Object, type S3Options, type S3Presign, type S3PresignGetItemOptions, type S3PresignPart, type S3PresignPutItemOptions, type S3PresignPutItemPartOptions, type S3PutItem, type S3PutItemOptions, S3StorageAdapter, type S3StorageConfig };
|