@geekmidas/storage 0.0.1
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 +371 -0
- package/dist/AmazonStorageClient-DJMWn8vO.mjs +112 -0
- package/dist/AmazonStorageClient-DT9DeKVz.cjs +124 -0
- package/dist/AmazonStorageClient.cjs +5 -0
- package/dist/AmazonStorageClient.mjs +4 -0
- package/dist/StorageClient-BDRVrMJj.cjs +16 -0
- package/dist/StorageClient-CZGIC_fz.mjs +10 -0
- package/dist/StorageClient.cjs +3 -0
- package/dist/StorageClient.mjs +3 -0
- package/dist/__tests__/AmazonStorageClient.spec.cjs +234 -0
- package/dist/__tests__/AmazonStorageClient.spec.mjs +233 -0
- package/dist/__tests__/StorageClient.spec.cjs +81 -0
- package/dist/__tests__/StorageClient.spec.mjs +81 -0
- package/dist/aws.cjs +5 -0
- package/dist/aws.mjs +4 -0
- package/dist/chunk-DWy1uDak.cjs +39 -0
- package/dist/index.cjs +0 -0
- package/dist/index.mjs +0 -0
- package/dist/magic-string.es-BvJNBYzY.mjs +1014 -0
- package/dist/magic-string.es-CKiDiYoS.cjs +1015 -0
- package/dist/vi.bdSIJ99Y-B0LMQgq6.mjs +14928 -0
- package/dist/vi.bdSIJ99Y-wDZVsqf8.cjs +14926 -0
- package/package.json +31 -0
- package/src/AmazonStorageClient.ts +176 -0
- package/src/StorageClient.ts +89 -0
- package/src/__tests__/AmazonStorageClient.spec.ts +327 -0
- package/src/__tests__/StorageClient.spec.ts +86 -0
- package/src/aws.ts +2 -0
- package/src/index.ts +1 -0
- package/tsdown.config.ts +9 -0
package/README.md
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
# @geekmidas/storage
|
|
2
|
+
|
|
3
|
+
A comprehensive, type-safe storage client for cloud storage services with support for multiple providers and advanced features like versioning and presigned URLs.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multi-provider support**: AWS S3, with extensible interface for Google Cloud Storage and Azure Blob Storage
|
|
8
|
+
- **Type-safe**: Full TypeScript support with comprehensive type definitions
|
|
9
|
+
- **Presigned URLs**: Generate secure upload and download URLs without exposing credentials
|
|
10
|
+
- **File versioning**: Support for retrieving and managing file versions
|
|
11
|
+
- **Direct uploads**: Upload files directly to storage without intermediate servers
|
|
12
|
+
- **Flexible configuration**: Support for custom endpoints (useful for MinIO, LocalStack, etc.)
|
|
13
|
+
- **Modern async/await API**: Promise-based interface throughout
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @geekmidas/storage
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Peer Dependencies
|
|
22
|
+
|
|
23
|
+
For AWS S3 support, you'll need to install the AWS SDK v3 packages:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install @aws-sdk/client-s3 @aws-sdk/s3-presigned-post @aws-sdk/s3-request-presigner
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
### AWS S3
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { AmazonStorageClient } from '@geekmidas/storage/aws';
|
|
35
|
+
|
|
36
|
+
// Create client with credentials
|
|
37
|
+
const storage = AmazonStorageClient.create({
|
|
38
|
+
bucket: 'my-bucket',
|
|
39
|
+
region: 'us-east-1',
|
|
40
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
|
41
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Upload a file directly
|
|
45
|
+
await storage.upload('documents/readme.txt', 'Hello, World!', 'text/plain');
|
|
46
|
+
|
|
47
|
+
// Generate a download URL
|
|
48
|
+
const downloadUrl = await storage.getDownloadURL({
|
|
49
|
+
path: 'documents/readme.txt',
|
|
50
|
+
name: 'README.txt' // Optional: sets Content-Disposition header
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Generate a presigned upload URL
|
|
54
|
+
const uploadUrl = await storage.getUploadURL({
|
|
55
|
+
path: 'uploads/new-file.pdf',
|
|
56
|
+
contentType: 'application/pdf',
|
|
57
|
+
contentLength: 1024 * 1024, // 1MB
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### MinIO / LocalStack
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { AmazonStorageClient } from '@geekmidas/storage/aws';
|
|
65
|
+
|
|
66
|
+
// For local development with MinIO
|
|
67
|
+
const storage = AmazonStorageClient.create({
|
|
68
|
+
bucket: 'test-bucket',
|
|
69
|
+
region: 'us-east-1',
|
|
70
|
+
accessKeyId: 'minioadmin',
|
|
71
|
+
secretAccessKey: 'minioadmin',
|
|
72
|
+
endpoint: 'http://localhost:9000',
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## API Reference
|
|
77
|
+
|
|
78
|
+
### StorageClient Interface
|
|
79
|
+
|
|
80
|
+
The core interface that all storage providers implement:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
interface StorageClient {
|
|
84
|
+
readonly provider: StorageProvider;
|
|
85
|
+
|
|
86
|
+
// Direct upload
|
|
87
|
+
upload(key: string, data: string | Buffer, contentType: string): Promise<void>;
|
|
88
|
+
|
|
89
|
+
// Download URLs
|
|
90
|
+
getDownloadURL(file: File, expiresIn?: number): Promise<string>;
|
|
91
|
+
|
|
92
|
+
// Upload URLs
|
|
93
|
+
getUploadURL(params: GetUploadParams, expiresIn?: number): Promise<string>;
|
|
94
|
+
getUpload(params: GetUploadParams, expiresIn?: number): Promise<GetUploadResponse>;
|
|
95
|
+
|
|
96
|
+
// Versioning
|
|
97
|
+
getVersions(key: string): Promise<DocumentVersion[]>;
|
|
98
|
+
getVersionDownloadURL(file: File, versionId: string): Promise<string>;
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### AmazonStorageClient
|
|
103
|
+
|
|
104
|
+
#### Factory Method
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
AmazonStorageClient.create(options: AmazonStorageClientCreateOptions)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Options:**
|
|
111
|
+
- `bucket` (required): S3 bucket name
|
|
112
|
+
- `region`: AWS region (default: uses AWS SDK default)
|
|
113
|
+
- `accessKeyId`: AWS access key ID
|
|
114
|
+
- `secretAccessKey`: AWS secret access key
|
|
115
|
+
- `endpoint`: Custom S3 endpoint (useful for MinIO, LocalStack)
|
|
116
|
+
- `acl`: Canned ACL for uploads (default: `authenticated-read`)
|
|
117
|
+
|
|
118
|
+
#### Methods
|
|
119
|
+
|
|
120
|
+
##### `upload(key: string, data: string | Buffer, contentType: string): Promise<void>`
|
|
121
|
+
|
|
122
|
+
Upload data directly to storage.
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
// Upload text
|
|
126
|
+
await storage.upload('documents/hello.txt', 'Hello, World!', 'text/plain');
|
|
127
|
+
|
|
128
|
+
// Upload binary data
|
|
129
|
+
const buffer = Buffer.from('binary data');
|
|
130
|
+
await storage.upload('files/binary.dat', buffer, 'application/octet-stream');
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
##### `getDownloadURL(file: File, expiresIn?: number): Promise<string>`
|
|
134
|
+
|
|
135
|
+
Generate a presigned download URL.
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// Simple download URL
|
|
139
|
+
const url = await storage.getDownloadURL({ path: 'documents/file.pdf' });
|
|
140
|
+
|
|
141
|
+
// With custom filename in Content-Disposition
|
|
142
|
+
const url = await storage.getDownloadURL({
|
|
143
|
+
path: 'documents/file.pdf',
|
|
144
|
+
name: 'My Document.pdf'
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Custom expiration (in seconds)
|
|
148
|
+
const url = await storage.getDownloadURL({ path: 'documents/file.pdf' }, 3600);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
##### `getUploadURL(params: GetUploadParams, expiresIn?: number): Promise<string>`
|
|
152
|
+
|
|
153
|
+
Generate a presigned PUT upload URL.
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
const uploadUrl = await storage.getUploadURL({
|
|
157
|
+
path: 'uploads/new-file.pdf',
|
|
158
|
+
contentType: 'application/pdf',
|
|
159
|
+
contentLength: 1024 * 1024,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Use the URL to upload
|
|
163
|
+
const response = await fetch(uploadUrl, {
|
|
164
|
+
method: 'PUT',
|
|
165
|
+
headers: {
|
|
166
|
+
'Content-Type': 'application/pdf',
|
|
167
|
+
'Content-Length': '1048576',
|
|
168
|
+
},
|
|
169
|
+
body: fileData,
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
##### `getUpload(params: GetUploadParams, expiresIn?: number): Promise<GetUploadResponse>`
|
|
174
|
+
|
|
175
|
+
Generate a presigned POST upload with form fields.
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
const upload = await storage.getUpload({
|
|
179
|
+
path: 'uploads/form-upload.jpg',
|
|
180
|
+
contentType: 'image/jpeg',
|
|
181
|
+
contentLength: 500000,
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Use with HTML form
|
|
185
|
+
const formData = new FormData();
|
|
186
|
+
upload.fields.forEach(({ key, value }) => {
|
|
187
|
+
formData.append(key, value);
|
|
188
|
+
});
|
|
189
|
+
formData.append('file', fileInput.files[0]);
|
|
190
|
+
|
|
191
|
+
const response = await fetch(upload.url, {
|
|
192
|
+
method: 'POST',
|
|
193
|
+
body: formData,
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
##### `getVersions(key: string): Promise<DocumentVersion[]>`
|
|
198
|
+
|
|
199
|
+
Get all versions of a file (requires S3 versioning).
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
const versions = await storage.getVersions('documents/versioned-file.txt');
|
|
203
|
+
console.log(versions); // [{ id: 'version-1', createdAt: Date }, ...]
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
##### `getVersionDownloadURL(file: File, versionId: string): Promise<string>`
|
|
207
|
+
|
|
208
|
+
Generate download URL for a specific version.
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
const url = await storage.getVersionDownloadURL(
|
|
212
|
+
{ path: 'documents/file.txt' },
|
|
213
|
+
'version-12345'
|
|
214
|
+
);
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Types
|
|
218
|
+
|
|
219
|
+
#### File
|
|
220
|
+
```typescript
|
|
221
|
+
interface File {
|
|
222
|
+
path: string;
|
|
223
|
+
name?: string; // Optional display name for Content-Disposition
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
#### GetUploadParams
|
|
228
|
+
```typescript
|
|
229
|
+
interface GetUploadParams {
|
|
230
|
+
path: string;
|
|
231
|
+
contentType: string;
|
|
232
|
+
contentLength: number;
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
#### DocumentVersion
|
|
237
|
+
```typescript
|
|
238
|
+
interface DocumentVersion {
|
|
239
|
+
id: string;
|
|
240
|
+
createdAt: Date;
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
#### StorageProvider
|
|
245
|
+
```typescript
|
|
246
|
+
enum StorageProvider {
|
|
247
|
+
AWSS3 = 'geekimdas.toolbox.storage.aws.s3',
|
|
248
|
+
GCP = 'geekimdas.toolbox.storage.gcp',
|
|
249
|
+
AZURE = 'geekimdas.toolbox.storage.azure',
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Advanced Usage
|
|
254
|
+
|
|
255
|
+
### Custom S3 Client
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
259
|
+
import { AmazonStorageClient, AmazonCannedAccessControlList } from '@geekmidas/storage/aws';
|
|
260
|
+
|
|
261
|
+
const s3Client = new S3Client({
|
|
262
|
+
region: 'us-east-1',
|
|
263
|
+
credentials: {
|
|
264
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
265
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
266
|
+
},
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
const storage = new AmazonStorageClient(
|
|
270
|
+
s3Client,
|
|
271
|
+
'my-bucket',
|
|
272
|
+
AmazonCannedAccessControlList.PublicRead
|
|
273
|
+
);
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Access Control Lists (ACLs)
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
import { AmazonCannedAccessControlList } from '@geekmidas/storage/aws';
|
|
280
|
+
|
|
281
|
+
const storage = AmazonStorageClient.create({
|
|
282
|
+
bucket: 'my-bucket',
|
|
283
|
+
acl: AmazonCannedAccessControlList.PublicRead, // Files will be publicly readable
|
|
284
|
+
});
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Available ACLs:
|
|
288
|
+
- `Private` - Owner gets full control, no one else has access
|
|
289
|
+
- `PublicRead` - Owner gets full control, everyone else gets read access
|
|
290
|
+
- `PublicReadWrite` - Owner gets full control, everyone else gets read/write access
|
|
291
|
+
- `AuthenticatedRead` - Owner gets full control, authenticated users get read access
|
|
292
|
+
- `BucketOwnerRead` - Object owner gets full control, bucket owner gets read access
|
|
293
|
+
- `BucketOwnerFullControl` - Object and bucket owner get full control
|
|
294
|
+
- `LogDeliveryWrite` - Log delivery service gets write access
|
|
295
|
+
- `AwsExecRead` - Amazon EC2 gets read access for AMI bundles
|
|
296
|
+
|
|
297
|
+
### Error Handling
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
try {
|
|
301
|
+
await storage.upload('documents/file.txt', 'content', 'text/plain');
|
|
302
|
+
} catch (error) {
|
|
303
|
+
if (error.name === 'NoSuchBucket') {
|
|
304
|
+
console.error('Bucket does not exist');
|
|
305
|
+
} else if (error.name === 'AccessDenied') {
|
|
306
|
+
console.error('Access denied');
|
|
307
|
+
} else {
|
|
308
|
+
console.error('Upload failed:', error);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## Development
|
|
314
|
+
|
|
315
|
+
### Running Tests
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
# Run all tests
|
|
319
|
+
npm test
|
|
320
|
+
|
|
321
|
+
# Run unit tests only
|
|
322
|
+
npm run test:unit
|
|
323
|
+
|
|
324
|
+
# Run integration tests only (requires MinIO)
|
|
325
|
+
npm run test:integration
|
|
326
|
+
|
|
327
|
+
# Run tests once
|
|
328
|
+
npm run test:once
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Local Development with MinIO
|
|
332
|
+
|
|
333
|
+
1. Start MinIO using Docker Compose:
|
|
334
|
+
```bash
|
|
335
|
+
docker-compose up -d minio
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
2. MinIO will be available at:
|
|
339
|
+
- API: http://localhost:9000
|
|
340
|
+
- Console: http://localhost:9001
|
|
341
|
+
- Credentials: minioadmin/minioadmin
|
|
342
|
+
|
|
343
|
+
3. Run integration tests:
|
|
344
|
+
```bash
|
|
345
|
+
npm run test:integration
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Project Structure
|
|
349
|
+
|
|
350
|
+
```
|
|
351
|
+
src/
|
|
352
|
+
├── index.ts # Main exports
|
|
353
|
+
├── aws.ts # AWS-specific exports
|
|
354
|
+
├── StorageClient.ts # Core interfaces and types
|
|
355
|
+
├── AmazonStorageClient.ts # AWS S3 implementation
|
|
356
|
+
└── __tests__/
|
|
357
|
+
├── StorageClient.spec.ts # Interface tests
|
|
358
|
+
├── AmazonStorageClient.spec.ts # Unit tests
|
|
359
|
+
└── AmazonStorageClient.integration.spec.ts # Integration tests
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
## Contributing
|
|
363
|
+
|
|
364
|
+
1. Follow the existing code style (2 spaces, single quotes, semicolons)
|
|
365
|
+
2. Add comprehensive tests for new features
|
|
366
|
+
3. Update documentation for API changes
|
|
367
|
+
4. Use the "Integration over Unit" testing philosophy - prefer real dependencies over mocks
|
|
368
|
+
|
|
369
|
+
## License
|
|
370
|
+
|
|
371
|
+
MIT License - see the LICENSE file for details.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { StorageProvider } from "./StorageClient-CZGIC_fz.mjs";
|
|
2
|
+
import { GetObjectCommand, ListObjectVersionsCommand, PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
3
|
+
import { createPresignedPost } from "@aws-sdk/s3-presigned-post";
|
|
4
|
+
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
|
5
|
+
|
|
6
|
+
//#region src/AmazonStorageClient.ts
|
|
7
|
+
var AmazonStorageClient = class AmazonStorageClient {
|
|
8
|
+
provider = StorageProvider.AWSS3;
|
|
9
|
+
static create(options) {
|
|
10
|
+
const { bucket, region, accessKeyId, acl, endpoint, secretAccessKey, forcePathStyle = false } = options;
|
|
11
|
+
const hasCredentials = accessKeyId && secretAccessKey;
|
|
12
|
+
const credentials = hasCredentials ? {
|
|
13
|
+
accessKeyId,
|
|
14
|
+
secretAccessKey
|
|
15
|
+
} : void 0;
|
|
16
|
+
const client = new S3Client({
|
|
17
|
+
region,
|
|
18
|
+
credentials,
|
|
19
|
+
endpoint,
|
|
20
|
+
forcePathStyle
|
|
21
|
+
});
|
|
22
|
+
return new AmazonStorageClient(client, bucket, acl);
|
|
23
|
+
}
|
|
24
|
+
constructor(client, bucket, acl = AmazonCannedAccessControlList.AuthenticatedRead) {
|
|
25
|
+
this.client = client;
|
|
26
|
+
this.bucket = bucket;
|
|
27
|
+
this.acl = acl;
|
|
28
|
+
}
|
|
29
|
+
getVersionDownloadURL(file, versionId) {
|
|
30
|
+
const ResponseContentDisposition = file.name ? `attachment; filename=${encodeURIComponent(file.name)}` : void 0;
|
|
31
|
+
const command = new GetObjectCommand({
|
|
32
|
+
Bucket: this.bucket,
|
|
33
|
+
Key: file.path,
|
|
34
|
+
ResponseContentDisposition,
|
|
35
|
+
VersionId: versionId
|
|
36
|
+
});
|
|
37
|
+
return getSignedUrl(this.client, command, { expiresIn: 60 * 60 * 24 });
|
|
38
|
+
}
|
|
39
|
+
async getVersions(key) {
|
|
40
|
+
const command = new ListObjectVersionsCommand({
|
|
41
|
+
Bucket: this.bucket,
|
|
42
|
+
Prefix: key
|
|
43
|
+
});
|
|
44
|
+
const { Versions = [] } = await this.client.send(command);
|
|
45
|
+
return Versions.map((version) => ({
|
|
46
|
+
id: version.VersionId || "",
|
|
47
|
+
createdAt: version.LastModified || /* @__PURE__ */ new Date()
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
getDownloadURL(file, expiresIn = 60 * 60) {
|
|
51
|
+
const ResponseContentDisposition = file.name ? `attachment; filename=${encodeURIComponent(file.name)}` : void 0;
|
|
52
|
+
const command = new GetObjectCommand({
|
|
53
|
+
Bucket: this.bucket,
|
|
54
|
+
Key: file.path,
|
|
55
|
+
ResponseContentDisposition
|
|
56
|
+
});
|
|
57
|
+
return getSignedUrl(this.client, command, { expiresIn });
|
|
58
|
+
}
|
|
59
|
+
async getUploadURL(params, expiresIn = 60 * 60) {
|
|
60
|
+
const command = new PutObjectCommand({
|
|
61
|
+
Bucket: this.bucket,
|
|
62
|
+
Key: params.path,
|
|
63
|
+
ContentType: params.contentType,
|
|
64
|
+
ContentLength: params.contentLength
|
|
65
|
+
});
|
|
66
|
+
return getSignedUrl(this.client, command, { expiresIn });
|
|
67
|
+
}
|
|
68
|
+
async getUpload(params, expiresIn = 5) {
|
|
69
|
+
const { path } = params;
|
|
70
|
+
const { fields: values, url } = await createPresignedPost(this.client, {
|
|
71
|
+
Expires: expiresIn * 60,
|
|
72
|
+
Bucket: this.bucket,
|
|
73
|
+
Fields: { acl: this.acl },
|
|
74
|
+
Conditions: [],
|
|
75
|
+
Key: path
|
|
76
|
+
});
|
|
77
|
+
const keys = Object.keys(values);
|
|
78
|
+
const fields = keys.map((key) => ({
|
|
79
|
+
key,
|
|
80
|
+
value: values[key] || ""
|
|
81
|
+
}));
|
|
82
|
+
return {
|
|
83
|
+
url,
|
|
84
|
+
fields
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
async upload(key, data, contentType) {
|
|
88
|
+
const Body = typeof data === "string" ? Buffer.from(data, "base64") : data;
|
|
89
|
+
const params = {
|
|
90
|
+
Bucket: this.bucket,
|
|
91
|
+
Key: key,
|
|
92
|
+
Body,
|
|
93
|
+
ContentType: contentType
|
|
94
|
+
};
|
|
95
|
+
const command = new PutObjectCommand(params);
|
|
96
|
+
await this.client.send(command);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
let AmazonCannedAccessControlList = /* @__PURE__ */ function(AmazonCannedAccessControlList$1) {
|
|
100
|
+
AmazonCannedAccessControlList$1["AuthenticatedRead"] = "authenticated-read";
|
|
101
|
+
AmazonCannedAccessControlList$1["Private"] = "private";
|
|
102
|
+
AmazonCannedAccessControlList$1["PublicRead"] = "public-read";
|
|
103
|
+
AmazonCannedAccessControlList$1["PublicReadWrite"] = "public-read-write";
|
|
104
|
+
AmazonCannedAccessControlList$1["AwsExecRead"] = "aws-exec-read";
|
|
105
|
+
AmazonCannedAccessControlList$1["BucketOwnerRead"] = "bucket-owner-read";
|
|
106
|
+
AmazonCannedAccessControlList$1["BucketOwnerFullControl"] = "bucket-owner-full-control";
|
|
107
|
+
AmazonCannedAccessControlList$1["LogDeliveryWrite"] = "log-delivery-write";
|
|
108
|
+
return AmazonCannedAccessControlList$1;
|
|
109
|
+
}({});
|
|
110
|
+
|
|
111
|
+
//#endregion
|
|
112
|
+
export { AmazonCannedAccessControlList, AmazonStorageClient };
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
const require_chunk = require('./chunk-DWy1uDak.cjs');
|
|
2
|
+
const require_StorageClient = require('./StorageClient-BDRVrMJj.cjs');
|
|
3
|
+
const __aws_sdk_client_s3 = require_chunk.__toESM(require("@aws-sdk/client-s3"));
|
|
4
|
+
const __aws_sdk_s3_presigned_post = require_chunk.__toESM(require("@aws-sdk/s3-presigned-post"));
|
|
5
|
+
const __aws_sdk_s3_request_presigner = require_chunk.__toESM(require("@aws-sdk/s3-request-presigner"));
|
|
6
|
+
|
|
7
|
+
//#region src/AmazonStorageClient.ts
|
|
8
|
+
var AmazonStorageClient = class AmazonStorageClient {
|
|
9
|
+
provider = require_StorageClient.StorageProvider.AWSS3;
|
|
10
|
+
static create(options) {
|
|
11
|
+
const { bucket, region, accessKeyId, acl, endpoint, secretAccessKey, forcePathStyle = false } = options;
|
|
12
|
+
const hasCredentials = accessKeyId && secretAccessKey;
|
|
13
|
+
const credentials = hasCredentials ? {
|
|
14
|
+
accessKeyId,
|
|
15
|
+
secretAccessKey
|
|
16
|
+
} : void 0;
|
|
17
|
+
const client = new __aws_sdk_client_s3.S3Client({
|
|
18
|
+
region,
|
|
19
|
+
credentials,
|
|
20
|
+
endpoint,
|
|
21
|
+
forcePathStyle
|
|
22
|
+
});
|
|
23
|
+
return new AmazonStorageClient(client, bucket, acl);
|
|
24
|
+
}
|
|
25
|
+
constructor(client, bucket, acl = AmazonCannedAccessControlList.AuthenticatedRead) {
|
|
26
|
+
this.client = client;
|
|
27
|
+
this.bucket = bucket;
|
|
28
|
+
this.acl = acl;
|
|
29
|
+
}
|
|
30
|
+
getVersionDownloadURL(file, versionId) {
|
|
31
|
+
const ResponseContentDisposition = file.name ? `attachment; filename=${encodeURIComponent(file.name)}` : void 0;
|
|
32
|
+
const command = new __aws_sdk_client_s3.GetObjectCommand({
|
|
33
|
+
Bucket: this.bucket,
|
|
34
|
+
Key: file.path,
|
|
35
|
+
ResponseContentDisposition,
|
|
36
|
+
VersionId: versionId
|
|
37
|
+
});
|
|
38
|
+
return (0, __aws_sdk_s3_request_presigner.getSignedUrl)(this.client, command, { expiresIn: 60 * 60 * 24 });
|
|
39
|
+
}
|
|
40
|
+
async getVersions(key) {
|
|
41
|
+
const command = new __aws_sdk_client_s3.ListObjectVersionsCommand({
|
|
42
|
+
Bucket: this.bucket,
|
|
43
|
+
Prefix: key
|
|
44
|
+
});
|
|
45
|
+
const { Versions = [] } = await this.client.send(command);
|
|
46
|
+
return Versions.map((version) => ({
|
|
47
|
+
id: version.VersionId || "",
|
|
48
|
+
createdAt: version.LastModified || /* @__PURE__ */ new Date()
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
getDownloadURL(file, expiresIn = 60 * 60) {
|
|
52
|
+
const ResponseContentDisposition = file.name ? `attachment; filename=${encodeURIComponent(file.name)}` : void 0;
|
|
53
|
+
const command = new __aws_sdk_client_s3.GetObjectCommand({
|
|
54
|
+
Bucket: this.bucket,
|
|
55
|
+
Key: file.path,
|
|
56
|
+
ResponseContentDisposition
|
|
57
|
+
});
|
|
58
|
+
return (0, __aws_sdk_s3_request_presigner.getSignedUrl)(this.client, command, { expiresIn });
|
|
59
|
+
}
|
|
60
|
+
async getUploadURL(params, expiresIn = 60 * 60) {
|
|
61
|
+
const command = new __aws_sdk_client_s3.PutObjectCommand({
|
|
62
|
+
Bucket: this.bucket,
|
|
63
|
+
Key: params.path,
|
|
64
|
+
ContentType: params.contentType,
|
|
65
|
+
ContentLength: params.contentLength
|
|
66
|
+
});
|
|
67
|
+
return (0, __aws_sdk_s3_request_presigner.getSignedUrl)(this.client, command, { expiresIn });
|
|
68
|
+
}
|
|
69
|
+
async getUpload(params, expiresIn = 5) {
|
|
70
|
+
const { path } = params;
|
|
71
|
+
const { fields: values, url } = await (0, __aws_sdk_s3_presigned_post.createPresignedPost)(this.client, {
|
|
72
|
+
Expires: expiresIn * 60,
|
|
73
|
+
Bucket: this.bucket,
|
|
74
|
+
Fields: { acl: this.acl },
|
|
75
|
+
Conditions: [],
|
|
76
|
+
Key: path
|
|
77
|
+
});
|
|
78
|
+
const keys = Object.keys(values);
|
|
79
|
+
const fields = keys.map((key) => ({
|
|
80
|
+
key,
|
|
81
|
+
value: values[key] || ""
|
|
82
|
+
}));
|
|
83
|
+
return {
|
|
84
|
+
url,
|
|
85
|
+
fields
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
async upload(key, data, contentType) {
|
|
89
|
+
const Body = typeof data === "string" ? Buffer.from(data, "base64") : data;
|
|
90
|
+
const params = {
|
|
91
|
+
Bucket: this.bucket,
|
|
92
|
+
Key: key,
|
|
93
|
+
Body,
|
|
94
|
+
ContentType: contentType
|
|
95
|
+
};
|
|
96
|
+
const command = new __aws_sdk_client_s3.PutObjectCommand(params);
|
|
97
|
+
await this.client.send(command);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
let AmazonCannedAccessControlList = /* @__PURE__ */ function(AmazonCannedAccessControlList$1) {
|
|
101
|
+
AmazonCannedAccessControlList$1["AuthenticatedRead"] = "authenticated-read";
|
|
102
|
+
AmazonCannedAccessControlList$1["Private"] = "private";
|
|
103
|
+
AmazonCannedAccessControlList$1["PublicRead"] = "public-read";
|
|
104
|
+
AmazonCannedAccessControlList$1["PublicReadWrite"] = "public-read-write";
|
|
105
|
+
AmazonCannedAccessControlList$1["AwsExecRead"] = "aws-exec-read";
|
|
106
|
+
AmazonCannedAccessControlList$1["BucketOwnerRead"] = "bucket-owner-read";
|
|
107
|
+
AmazonCannedAccessControlList$1["BucketOwnerFullControl"] = "bucket-owner-full-control";
|
|
108
|
+
AmazonCannedAccessControlList$1["LogDeliveryWrite"] = "log-delivery-write";
|
|
109
|
+
return AmazonCannedAccessControlList$1;
|
|
110
|
+
}({});
|
|
111
|
+
|
|
112
|
+
//#endregion
|
|
113
|
+
Object.defineProperty(exports, 'AmazonCannedAccessControlList', {
|
|
114
|
+
enumerable: true,
|
|
115
|
+
get: function () {
|
|
116
|
+
return AmazonCannedAccessControlList;
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
Object.defineProperty(exports, 'AmazonStorageClient', {
|
|
120
|
+
enumerable: true,
|
|
121
|
+
get: function () {
|
|
122
|
+
return AmazonStorageClient;
|
|
123
|
+
}
|
|
124
|
+
});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
require('./StorageClient-BDRVrMJj.cjs');
|
|
2
|
+
const require_AmazonStorageClient = require('./AmazonStorageClient-DT9DeKVz.cjs');
|
|
3
|
+
|
|
4
|
+
exports.AmazonCannedAccessControlList = require_AmazonStorageClient.AmazonCannedAccessControlList;
|
|
5
|
+
exports.AmazonStorageClient = require_AmazonStorageClient.AmazonStorageClient;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/StorageClient.ts
|
|
3
|
+
let StorageProvider = /* @__PURE__ */ function(StorageProvider$1) {
|
|
4
|
+
StorageProvider$1["AWSS3"] = "geekimdas.toolbox.storage.aws.s3";
|
|
5
|
+
StorageProvider$1["GCP"] = "geekimdas.toolbox.storage.gcp";
|
|
6
|
+
StorageProvider$1["AZURE"] = "geekimdas.toolbox.storage.azure";
|
|
7
|
+
return StorageProvider$1;
|
|
8
|
+
}({});
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
Object.defineProperty(exports, 'StorageProvider', {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: function () {
|
|
14
|
+
return StorageProvider;
|
|
15
|
+
}
|
|
16
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/StorageClient.ts
|
|
2
|
+
let StorageProvider = /* @__PURE__ */ function(StorageProvider$1) {
|
|
3
|
+
StorageProvider$1["AWSS3"] = "geekimdas.toolbox.storage.aws.s3";
|
|
4
|
+
StorageProvider$1["GCP"] = "geekimdas.toolbox.storage.gcp";
|
|
5
|
+
StorageProvider$1["AZURE"] = "geekimdas.toolbox.storage.azure";
|
|
6
|
+
return StorageProvider$1;
|
|
7
|
+
}({});
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
10
|
+
export { StorageProvider };
|