@zola_do/seaweed 0.2.5 → 0.2.7

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 CHANGED
@@ -1,7 +1,21 @@
1
1
  # @zola_do/seaweed
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@zola_do/seaweed.svg)](https://www.npmjs.com/package/@zola_do/seaweed)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@zola_do/seaweed.svg)](https://www.npmjs.com/package/@zola_do/seaweed)
5
+ [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
6
+
3
7
  AWS S3-compatible object storage for NestJS (SeaweedFS, MinIO, or AWS S3).
4
8
 
9
+ ## Overview
10
+
11
+ `@zola_do/seaweed` provides a unified interface for S3-compatible storage:
12
+
13
+ - **Upload** — Files, buffers, and streams
14
+ - **Download** — Streaming and buffered downloads
15
+ - **Presigned URLs** — Secure upload/download links
16
+ - **Abstract S3 Class** — Implement custom providers
17
+ - **TypeScript Types** — Full type safety
18
+
5
19
  ## Installation
6
20
 
7
21
  ```bash
@@ -12,25 +26,29 @@ npm install @zola_do/seaweed
12
26
  npm install @zola_do/nestjs-shared
13
27
  ```
14
28
 
15
- ## Recommended Imports
16
-
17
- `@zola_do/seaweed` root imports remain fully supported for backward compatibility.
18
- For new code, prefer focused subpath imports:
29
+ ### Dependencies
19
30
 
20
- ```typescript
21
- import { StorageModule } from '@zola_do/seaweed/module';
22
- import { StorageService, AwsS3 } from '@zola_do/seaweed/services';
23
- import type { FileInfo } from '@zola_do/seaweed/types';
24
- import { FileNotFoundException } from '@zola_do/seaweed/exceptions';
31
+ ```bash
32
+ npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner
25
33
  ```
26
34
 
27
- ## Usage
35
+ ## Quick Start
28
36
 
29
- ### Module Setup
37
+ ### 1. Configure Environment
38
+
39
+ ```bash
40
+ # .env
41
+ AWS_ACCESS_KEY_ID=your-access-key
42
+ AWS_SECRET_ACCESS_KEY=your-secret-key
43
+ AWS_ENDPOINT=https://your-s3-endpoint.com
44
+ AWS_REGION=us-east-1
45
+ ```
46
+
47
+ ### 2. Register Module
30
48
 
31
49
  ```typescript
32
- import { Module } from '@nestjs/common';
33
- import { StorageModule } from '@zola_do/seaweed';
50
+ import { Module } from "@nestjs/common";
51
+ import { StorageModule } from "@zola_do/seaweed";
34
52
 
35
53
  @Module({
36
54
  imports: [StorageModule],
@@ -38,61 +56,373 @@ import { StorageModule } from '@zola_do/seaweed';
38
56
  export class AppModule {}
39
57
  ```
40
58
 
41
- ### Uploading Files
59
+ ### 3. Use Storage Service
42
60
 
43
61
  ```typescript
44
- import { Injectable } from '@nestjs/common';
45
- import { StorageService } from '@zola_do/seaweed';
62
+ import { Injectable } from "@nestjs/common";
63
+ import { StorageService } from "@zola_do/seaweed";
46
64
 
47
65
  @Injectable()
48
66
  export class FileService {
49
67
  constructor(private readonly storageService: StorageService) {}
50
68
 
51
- async upload(file: Express.Multer.File, bucketName: string) {
69
+ async uploadFile(file: Express.Multer.File, bucketName: string) {
52
70
  return await this.storageService.upload(file, bucketName);
53
- // Returns FileInfo: { filepath, bucketName, contentType, originalname }
54
71
  }
72
+
73
+ async downloadFile(fileInfo: FileInfo, response: Response) {
74
+ await this.storageService.download(fileInfo, response);
75
+ }
76
+ }
77
+ ```
78
+
79
+ ## Storage Architecture
80
+
81
+ ```
82
+ ┌─────────────────────────────────────────────────────────────────────┐
83
+ │ Storage Flow │
84
+ ├─────────────────────────────────────────────────────────────────────┤
85
+ │ │
86
+ │ ┌──────────┐ │
87
+ │ │ Client │ │
88
+ │ └────┬─────┘ │
89
+ │ │ │
90
+ │ │ 1. Request presigned URL │
91
+ │ ├─────────────────────────────────────┐ │
92
+ │ │ │ │
93
+ │ ▼ ▼ │
94
+ │ ┌───────────────┐ ┌───────────────┐ │
95
+ │ │ Controller │ │ Storage │ │
96
+ │ │ GET /upload │ │ Service │ │
97
+ │ └───────┬───────┘ └───────┬───────┘ │
98
+ │ │ │ │
99
+ │ │ 2. Generate presigned URL │ │
100
+ │ ├─────────────────────────────────────┤ │
101
+ │ │ │ │
102
+ │ ▼ ▼ │
103
+ │ ┌───────────────┐ ┌───────────────┐ │
104
+ │ │ Response │ │ AWS SDK │ │
105
+ │ │ { url } │ │ S3Client │ │
106
+ │ └───────────────┘ └───────┬───────┘ │
107
+ │ │ │
108
+ │ │ │
109
+ │ ┌─────────────────────────────────────┤ │
110
+ │ │ │ │
111
+ │ ▼ ▼ │
112
+ │ ┌───────────────┐ ┌───────────────┐ │
113
+ │ │ Direct PUT │───────────────────► │ S3 Bucket │ │
114
+ │ │ to S3 │ 3. Upload file │ (any S3) │ │
115
+ │ └───────────────┘ └───────────────┘ │
116
+ │ │
117
+ └─────────────────────────────────────────────────────────────────────┘
118
+ ```
119
+
120
+ ## Upload Operations
121
+
122
+ ### File Upload
123
+
124
+ ```typescript
125
+ async uploadFile(file: Express.Multer.File, bucketName: string) {
126
+ const result = await this.storageService.upload(file, bucketName);
127
+ return result;
128
+ // Returns: { filepath, bucketName, contentType, originalname }
129
+ }
130
+ ```
131
+
132
+ ### Buffer Upload
133
+
134
+ ```typescript
135
+ async uploadBuffer(
136
+ buffer: Buffer,
137
+ originalname: string,
138
+ mimetype: string,
139
+ bucketName: string,
140
+ ) {
141
+ const result = await this.storageService.uploadBuffer(
142
+ buffer,
143
+ originalname,
144
+ mimetype,
145
+ bucketName,
146
+ );
147
+ return result;
55
148
  }
56
149
  ```
57
150
 
58
- ### Downloading Files
151
+ ### Stream Upload
59
152
 
60
153
  ```typescript
61
- await this.storageService.download(fileInfo, response);
62
- // Streams file to Express Response with appropriate headers
154
+ async uploadStream(
155
+ stream: ReadableStream,
156
+ filename: string,
157
+ mimetype: string,
158
+ bucketName: string,
159
+ ) {
160
+ return await this.storageService.uploadStream(
161
+ stream,
162
+ filename,
163
+ mimetype,
164
+ bucketName,
165
+ );
166
+ }
63
167
  ```
64
168
 
65
- ### Presigned URLs
169
+ ## Download Operations
170
+
171
+ ### Download to Response
66
172
 
67
173
  ```typescript
68
- // Upload
69
- const uploadUrl = await this.storageService.generatePresignedUploadUrl(fileInfo);
174
+ async downloadToResponse(fileInfo: FileInfo, response: Response) {
175
+ response.setHeader('Content-Type', fileInfo.contentType);
176
+ response.setHeader('Content-Disposition', `attachment; filename="${fileInfo.originalname}"`);
177
+
178
+ await this.storageService.download(fileInfo, response);
179
+ }
180
+ ```
181
+
182
+ ### Download to Buffer
70
183
 
71
- // Download
72
- const downloadUrl = await this.storageService.generatePresignedDownloadUrl(fileInfo);
184
+ ```typescript
185
+ async downloadToBuffer(fileInfo: FileInfo): Promise<Buffer> {
186
+ return await this.storageService.downloadBuffer(fileInfo);
187
+ }
188
+ ```
189
+
190
+ ## Presigned URLs
191
+
192
+ ### Generate Upload URL
193
+
194
+ ```typescript
195
+ async getUploadUrl(fileInfo: FileInfo): Promise<string> {
196
+ const presignedUrl = await this.storageService.generatePresignedUploadUrl(
197
+ fileInfo,
198
+ 3600, // URL expires in 1 hour
199
+ );
200
+ return presignedUrl;
201
+ }
202
+ ```
203
+
204
+ ### Generate Download URL
205
+
206
+ ```typescript
207
+ async getDownloadUrl(fileInfo: FileInfo): Promise<string> {
208
+ const downloadUrl = await this.storageService.generatePresignedDownloadUrl(
209
+ fileInfo,
210
+ 3600, // URL expires in 1 hour
211
+ );
212
+ return downloadUrl;
213
+ }
214
+ ```
215
+
216
+ ### Usage with Client
217
+
218
+ ```typescript
219
+ // Server generates URL
220
+ const { presignedUrl, file } =
221
+ await this.storageService.generatePresignedUploadUrl({
222
+ originalname: "document.pdf",
223
+ contentType: "application/pdf",
224
+ });
225
+
226
+ // Client uploads directly
227
+ fetch(presignedUrl, {
228
+ method: "PUT",
229
+ body: fileBuffer,
230
+ headers: { "Content-Type": "application/pdf" },
231
+ });
232
+ ```
233
+
234
+ ## FileInfo Type
235
+
236
+ ```typescript
237
+ interface FileInfo {
238
+ filepath: string; // Key/path in bucket
239
+ bucketName: string; // Target bucket
240
+ contentType: string; // MIME type
241
+ originalname: string; // Original filename
242
+ }
243
+ ```
244
+
245
+ ## Custom S3 Provider
246
+
247
+ Implement a custom storage provider:
248
+
249
+ ```typescript
250
+ import { S3, FileInfo } from "@zola_do/seaweed";
251
+
252
+ class CustomS3Provider extends S3 {
253
+ constructor() {
254
+ super({
255
+ region: "custom-region",
256
+ credentials: {
257
+ accessKeyId: process.env.CUSTOM_KEY!,
258
+ secretAccessKey: process.env.CUSTOM_SECRET!,
259
+ },
260
+ endpoint: process.env.CUSTOM_ENDPOINT,
261
+ });
262
+ }
263
+
264
+ async upload(
265
+ file: Express.Multer.File,
266
+ bucketName: string,
267
+ ): Promise<FileInfo> {
268
+ // Custom upload logic
269
+ const filepath = `${Date.now()}-${file.originalname}`;
270
+ await this.client.putObject({
271
+ Bucket: bucketName,
272
+ Key: filepath,
273
+ Body: file.buffer,
274
+ ContentType: file.mimetype,
275
+ });
276
+ return {
277
+ filepath,
278
+ bucketName,
279
+ contentType: file.mimetype,
280
+ originalname: file.originalname,
281
+ };
282
+ }
283
+ }
73
284
  ```
74
285
 
75
286
  ## Environment Variables
76
287
 
77
- | Variable | Description |
78
- |----------|-------------|
79
- | `AWS_ACCESS_KEY_ID` | S3/MinIO access key |
80
- | `AWS_SECRET_ACCESS_KEY` | S3/MinIO secret key |
81
- | `AWS_ENDPOINT` | S3-compatible endpoint URL |
82
- | `PRESIGNED_URL_EXPIRATION` | Presigned URL expiry in seconds |
288
+ | Variable | Description | Required |
289
+ | -------------------------- | ------------------------------- | ------------------------- |
290
+ | `AWS_ACCESS_KEY_ID` | S3/MinIO access key | Yes |
291
+ | `AWS_SECRET_ACCESS_KEY` | S3/MinIO secret key | Yes |
292
+ | `AWS_ENDPOINT` | S3-compatible endpoint URL | Yes |
293
+ | `AWS_REGION` | AWS region | No (default: `us-east-1`) |
294
+ | `PRESIGNED_URL_EXPIRATION` | Presigned URL expiry in seconds | No (default: `3600`) |
295
+
296
+ ## Supported Providers
297
+
298
+ | Provider | Endpoint Example |
299
+ | ------------------- | ------------------------------------- |
300
+ | AWS S3 | `https://s3.amazonaws.com` |
301
+ | MinIO | `http://localhost:9000` |
302
+ | SeaweedFS | `http://localhost:8888` |
303
+ | DigitalOcean Spaces | `https://nyc3.digitaloceanspaces.com` |
304
+ | Wasabi | `https://s3.wasabisys.com` |
83
305
 
84
- ## Exports
306
+ ## API Reference
85
307
 
86
- - `StorageModule` — Register the storage module
87
- - `StorageService` — Upload, download, presigned URLs
88
- - Types and exceptions for storage operations
89
- - Subpath entrypoints: `@zola_do/seaweed/module`, `@zola_do/seaweed/services`, `@zola_do/seaweed/types`, `@zola_do/seaweed/exceptions`
90
- - Root entrypoint: `@zola_do/seaweed` (supported for backward compatibility)
308
+ ### Module
309
+
310
+ ```typescript
311
+ StorageModule.forRoot(options?: StorageModuleOptions)
312
+ StorageModule.forRootAsync(options?: StorageModuleAsyncOptions)
313
+ ```
314
+
315
+ ### Service
316
+
317
+ ```typescript
318
+ class StorageService {
319
+ upload(file: Express.Multer.File, bucketName: string): Promise<FileInfo>;
320
+ uploadBuffer(
321
+ buffer: Buffer,
322
+ filename: string,
323
+ mimetype: string,
324
+ bucketName: string,
325
+ ): Promise<FileInfo>;
326
+ uploadStream(
327
+ stream: Readable,
328
+ filename: string,
329
+ mimetype: string,
330
+ bucketName: string,
331
+ ): Promise<FileInfo>;
332
+
333
+ download(fileInfo: FileInfo, response: Response): Promise<void>;
334
+ downloadBuffer(fileInfo: FileInfo): Promise<Buffer>;
335
+
336
+ generatePresignedUploadUrl(
337
+ fileInfo: Partial<FileInfo>,
338
+ expiresIn?: number,
339
+ ): Promise<string>;
340
+ generatePresignedDownloadUrl(
341
+ fileInfo: FileInfo,
342
+ expiresIn?: number,
343
+ ): Promise<string>;
344
+ }
345
+ ```
346
+
347
+ ### Types
348
+
349
+ ```typescript
350
+ interface FileInfo {
351
+ filepath: string;
352
+ bucketName: string;
353
+ contentType: string;
354
+ originalname: string;
355
+ }
356
+
357
+ class S3 {
358
+ constructor(config: S3ClientConfig);
359
+ // Override methods for custom implementation
360
+ }
361
+ ```
362
+
363
+ ### Exceptions
364
+
365
+ ```typescript
366
+ class FileNotFoundException extends NotFoundException {
367
+ constructor(message?: string);
368
+ }
369
+ ```
370
+
371
+ ## Recommended Imports
372
+
373
+ Subpath imports are recommended for tree-shaking:
374
+
375
+ ```typescript
376
+ import { StorageModule } from "@zola_do/seaweed/module";
377
+ import { StorageService, AwsS3 } from "@zola_do/seaweed/services";
378
+ import type { FileInfo } from "@zola_do/seaweed/types";
379
+ import { FileNotFoundException } from "@zola_do/seaweed/exceptions";
380
+ ```
381
+
382
+ Root import is supported for backward compatibility:
383
+
384
+ ```typescript
385
+ import { StorageModule, StorageService, FileInfo } from "@zola_do/seaweed";
386
+ ```
387
+
388
+ ## Troubleshooting
389
+
390
+ ### Q: Upload fails with CORS error?
391
+
392
+ Configure CORS on your S3 bucket:
393
+
394
+ ```json
395
+ {
396
+ "CORSRules": [
397
+ {
398
+ "AllowedHeaders": ["*"],
399
+ "AllowedMethods": ["GET", "PUT", "POST", "DELETE"],
400
+ "AllowedOrigins": ["*"]
401
+ }
402
+ ]
403
+ }
404
+ ```
405
+
406
+ ### Q: Presigned URL returns 403?
407
+
408
+ Check:
409
+
410
+ 1. IAM permissions for the bucket
411
+ 2. Correct access key and secret
412
+ 3. URL hasn't expired
413
+
414
+ ### Q: Connection timeout?
415
+
416
+ Verify `AWS_ENDPOINT` is correct and accessible from your server.
91
417
 
92
418
  ## Related Packages
93
419
 
94
420
  - [@zola_do/minio](../minio) — Alternative MinIO-specific module
95
421
 
422
+ ## License
423
+
424
+ ISC
425
+
96
426
  ## Community
97
427
 
98
428
  - [Contributing](../../CONTRIBUTING.md)
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
+ export * from './zola-object-storage';
1
2
  export * from './storage.module';
2
3
  export * from './types';
3
4
  export * from './services/storage.service';
5
+ export * from './services/seaweed.zola-object-storage';
4
6
  export * from './exceptions';
package/dist/index.js CHANGED
@@ -14,8 +14,10 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./zola-object-storage"), exports);
17
18
  __exportStar(require("./storage.module"), exports);
18
19
  __exportStar(require("./types"), exports);
19
20
  __exportStar(require("./services/storage.service"), exports);
21
+ __exportStar(require("./services/seaweed.zola-object-storage"), exports);
20
22
  __exportStar(require("./exceptions"), exports);
21
23
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAAiC;AACjC,0CAAwB;AACxB,6DAA2C;AAC3C,+CAA6B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wDAAsC;AACtC,mDAAiC;AACjC,0CAAwB;AACxB,6DAA2C;AAC3C,yEAAuD;AACvD,+CAA6B"}
@@ -1,2 +1,3 @@
1
1
  export * from './aws-s3.service';
2
2
  export * from './storage.service';
3
+ export * from './seaweed.zola-object-storage';
@@ -16,4 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./aws-s3.service"), exports);
18
18
  __exportStar(require("./storage.service"), exports);
19
+ __exportStar(require("./seaweed.zola-object-storage"), exports);
19
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAAiC;AACjC,oDAAkC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAAiC;AACjC,oDAAkC;AAClC,gEAA8C"}
@@ -0,0 +1,16 @@
1
+ import { ZolaObjectStorage, ZolaStoredFileRef } from '../zola-object-storage';
2
+ import { StorageService } from './storage.service';
3
+ export declare class SeaweedZolaObjectStorage implements ZolaObjectStorage {
4
+ private readonly storage;
5
+ constructor(storage: StorageService);
6
+ uploadFile(file: Express.Multer.File, bucketName: string, _metaData?: Record<string, string>): Promise<ZolaStoredFileRef>;
7
+ uploadBuffer(buffer: Buffer, originalname: string, mimetype: string, bucketName: string): Promise<ZolaStoredFileRef>;
8
+ generatePresignedUploadUrl(fileInfo: {
9
+ originalname: string;
10
+ contentType?: string;
11
+ }, bucketName: string): Promise<{
12
+ presignedUrl: string;
13
+ file: ZolaStoredFileRef;
14
+ }>;
15
+ generatePresignedDownloadUrl(fileInfo: Pick<ZolaStoredFileRef, 'bucketName' | 'filepath' | 'contentType' | 'originalname'>): Promise<string>;
16
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.SeaweedZolaObjectStorage = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ const storage_service_1 = require("./storage.service");
15
+ let SeaweedZolaObjectStorage = class SeaweedZolaObjectStorage {
16
+ constructor(storage) {
17
+ this.storage = storage;
18
+ }
19
+ uploadFile(file, bucketName, _metaData) {
20
+ return this.storage.upload(file, bucketName);
21
+ }
22
+ uploadBuffer(buffer, originalname, mimetype, bucketName) {
23
+ return this.storage.uploadBuffer(buffer, originalname, mimetype, bucketName);
24
+ }
25
+ async generatePresignedUploadUrl(fileInfo, bucketName) {
26
+ var _a;
27
+ const result = await this.storage.generatePresignedUploadUrlWithRef({
28
+ originalname: fileInfo.originalname,
29
+ contentType: (_a = fileInfo.contentType) !== null && _a !== void 0 ? _a : 'application/octet-stream',
30
+ bucketName,
31
+ filepath: '',
32
+ });
33
+ return {
34
+ presignedUrl: result.presignedUrl,
35
+ file: result.file,
36
+ };
37
+ }
38
+ async generatePresignedDownloadUrl(fileInfo) {
39
+ return this.storage.generatePresignedDownloadUrl(fileInfo);
40
+ }
41
+ };
42
+ exports.SeaweedZolaObjectStorage = SeaweedZolaObjectStorage;
43
+ exports.SeaweedZolaObjectStorage = SeaweedZolaObjectStorage = __decorate([
44
+ (0, common_1.Injectable)(),
45
+ __metadata("design:paramtypes", [storage_service_1.StorageService])
46
+ ], SeaweedZolaObjectStorage);
47
+ //# sourceMappingURL=seaweed.zola-object-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seaweed.zola-object-storage.js","sourceRoot":"","sources":["../../src/services/seaweed.zola-object-storage.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAE5C,uDAAmD;AAG5C,IAAM,wBAAwB,GAA9B,MAAM,wBAAwB;IACnC,YAA6B,OAAuB;QAAvB,YAAO,GAAP,OAAO,CAAgB;IAAG,CAAC;IAExD,UAAU,CACR,IAAyB,EACzB,UAAkB,EAClB,SAAkC;QAElC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAA+B,CAAC;IAC7E,CAAC;IAED,YAAY,CACV,MAAc,EACd,YAAoB,EACpB,QAAgB,EAChB,UAAkB;QAElB,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,CAC9B,MAAM,EACN,YAAY,EACZ,QAAQ,EACR,UAAU,CACmB,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,0BAA0B,CAC9B,QAAwD,EACxD,UAAkB;;QAElB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,iCAAiC,CAAC;YAClE,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,WAAW,EAAE,MAAA,QAAQ,CAAC,WAAW,mCAAI,0BAA0B;YAC/D,UAAU;YACV,QAAQ,EAAE,EAAE;SACb,CAAC,CAAC;QACH,OAAO;YACL,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,IAAI,EAAE,MAAM,CAAC,IAAyB;SACvC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,4BAA4B,CAChC,QAGC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,4BAA4B,CAAC,QAAQ,CAAC,CAAC;IAC7D,CAAC;CACF,CAAA;AAjDY,4DAAwB;mCAAxB,wBAAwB;IADpC,IAAA,mBAAU,GAAE;qCAE2B,gCAAc;GADzC,wBAAwB,CAiDpC"}
@@ -7,4 +7,9 @@ export declare class StorageService {
7
7
  download(fileInfo: FileInfo, response: Response): Promise<any>;
8
8
  generatePresignedDownloadUrl(fileInfo: FileInfo): Promise<string>;
9
9
  generatePresignedUploadUrl(fileInfo: FileInfo): Promise<string>;
10
+ generatePresignedUploadUrlWithRef(fileInfo: FileInfo): Promise<{
11
+ presignedUrl: string;
12
+ file: FileInfo;
13
+ }>;
14
+ uploadBuffer(buffer: Buffer, originalname: string, mimetype: string, bucketName: string): Promise<FileInfo>;
10
15
  }
@@ -44,6 +44,26 @@ let StorageService = class StorageService {
44
44
  const normalizedFileName = `${(0, crypto_1.randomUUID)()}${ext}`;
45
45
  return await this.s3.presignedPutObject(fileInfo.bucketName, normalizedFileName, fileInfo.contentType, +process.env.PRESIGNED_URL_EXPIRATION);
46
46
  }
47
+ async generatePresignedUploadUrlWithRef(fileInfo) {
48
+ const ext = (0, path_1.extname)(fileInfo.originalname);
49
+ const normalizedFileName = `${(0, crypto_1.randomUUID)()}${ext}`;
50
+ const presignedUrl = await this.s3.presignedPutObject(fileInfo.bucketName, normalizedFileName, fileInfo.contentType, +process.env.PRESIGNED_URL_EXPIRATION);
51
+ return {
52
+ presignedUrl,
53
+ file: Object.assign(Object.assign({}, fileInfo), { filepath: normalizedFileName }),
54
+ };
55
+ }
56
+ async uploadBuffer(buffer, originalname, mimetype, bucketName) {
57
+ const ext = (0, path_1.extname)(originalname);
58
+ const normalizedFileName = `${(0, crypto_1.randomUUID)()}${ext}`;
59
+ await this.s3.putObject(bucketName, normalizedFileName, buffer);
60
+ return {
61
+ filepath: normalizedFileName,
62
+ bucketName,
63
+ contentType: mimetype,
64
+ originalname,
65
+ };
66
+ }
47
67
  };
48
68
  exports.StorageService = StorageService;
49
69
  exports.StorageService = StorageService = __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"storage.service.js","sourceRoot":"","sources":["../../src/services/storage.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAE5C,oCAAwC;AACxC,mCAAoC;AACpC,+BAA+B;AAGxB,IAAM,cAAc,GAApB,MAAM,cAAc;IACzB,YAA6B,EAAM;QAAN,OAAE,GAAF,EAAE,CAAI;IAAG,CAAC;IAEvC,KAAK,CAAC,MAAM,CACV,IAAyB,EACzB,UAAkB;QAElB,MAAM,GAAG,GAAG,IAAA,cAAO,EAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAEvC,MAAM,kBAAkB,GAAG,GAAG,IAAA,mBAAU,GAAE,GAAG,GAAG,EAAE,CAAC;QAEnD,MAAM,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,kBAAkB,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAErE,OAAO;YACL,QAAQ,EAAE,kBAAkB;YAC5B,UAAU;YACV,WAAW,EAAE,IAAI,CAAC,QAAQ;YAC1B,YAAY,EAAE,IAAI,CAAC,YAAY;SAChC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAkB,EAAE,QAAkB;;QACnD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,SAAS,CACpC,QAAQ,CAAC,UAAU,EACnB,QAAQ,CAAC,QAAQ,CAClB,CAAC;QAEF,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;QACzD,QAAQ,CAAC,SAAS,CAChB,qBAAqB,EACrB,wBAAwB,MAAA,QAAQ,CAAC,YAAY,mCAAI,QAAQ,CAAC,QAAQ,EAAE,CACrE,CAAC;QAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,4BAA4B,CAAC,QAAkB;QACnD,OAAO,MAAM,IAAI,CAAC,EAAE,CAAC,kBAAkB,CACrC,QAAQ,CAAC,UAAU,EACnB,QAAQ,CAAC,QAAQ,EACjB,QAAQ,CAAC,WAAW,EACpB,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CACtC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,0BAA0B,CAAC,QAAkB;QACjD,MAAM,GAAG,GAAG,IAAA,cAAO,EAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAE3C,MAAM,kBAAkB,GAAG,GAAG,IAAA,mBAAU,GAAE,GAAG,GAAG,EAAE,CAAC;QAEnD,OAAO,MAAM,IAAI,CAAC,EAAE,CAAC,kBAAkB,CACrC,QAAQ,CAAC,UAAU,EACnB,kBAAkB,EAClB,QAAQ,CAAC,WAAW,EACpB,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CACtC,CAAC;IACJ,CAAC;CACF,CAAA;AAzDY,wCAAc;yBAAd,cAAc;IAD1B,IAAA,mBAAU,GAAE;qCAEsB,UAAE;GADxB,cAAc,CAyD1B"}
1
+ {"version":3,"file":"storage.service.js","sourceRoot":"","sources":["../../src/services/storage.service.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,7 @@ const client_s3_1 = require("@aws-sdk/client-s3");
12
12
  const storage_service_1 = require("./services/storage.service");
13
13
  const aws_s3_service_1 = require("./services/aws-s3.service");
14
14
  const types_1 = require("./types");
15
+ const seaweed_zola_object_storage_1 = require("./services/seaweed.zola-object-storage");
15
16
  let StorageModule = class StorageModule {
16
17
  };
17
18
  exports.StorageModule = StorageModule;
@@ -36,9 +37,10 @@ exports.StorageModule = StorageModule = __decorate([
36
37
  useClass: aws_s3_service_1.AwsS3,
37
38
  },
38
39
  storage_service_1.StorageService,
40
+ seaweed_zola_object_storage_1.SeaweedZolaObjectStorage,
39
41
  ],
40
42
  controllers: [],
41
- exports: [storage_service_1.StorageService],
43
+ exports: [storage_service_1.StorageService, seaweed_zola_object_storage_1.SeaweedZolaObjectStorage],
42
44
  })
43
45
  ], StorageModule);
44
46
  //# sourceMappingURL=storage.module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"storage.module.js","sourceRoot":"","sources":["../src/storage.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,kDAA8C;AAC9C,gEAA4D;AAC5D,8DAAkD;AAClD,mCAA6B;AA2BtB,IAAM,aAAa,GAAnB,MAAM,aAAa;CAAG,CAAA;AAAhB,sCAAa;wBAAb,aAAa;IAzBzB,IAAA,eAAM,EAAC;QACN,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,oBAAQ;gBACjB,UAAU,EAAE,GAAG,EAAE;oBACf,OAAO,IAAI,oBAAQ,CAAC;wBAClB,WAAW,EAAE;4BACX,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;4BAC1C,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB;yBACnD;wBACD,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;wBAClC,cAAc,EAAE,IAAI;qBACrB,CAAC,CAAC;gBACL,CAAC;aACF;YACD;gBACE,OAAO,EAAE,UAAE;gBACX,QAAQ,EAAE,sBAAK;aAChB;YAED,gCAAc;SACf;QACD,WAAW,EAAE,EAAE;QACf,OAAO,EAAE,CAAC,gCAAc,CAAC;KAC1B,CAAC;GACW,aAAa,CAAG"}
1
+ {"version":3,"file":"storage.module.js","sourceRoot":"","sources":["../src/storage.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,kDAA8C;AAC9C,gEAA4D;AAC5D,8DAAkD;AAClD,mCAA6B;AAC7B,wFAAkF;AA4B3E,IAAM,aAAa,GAAnB,MAAM,aAAa;CAAG,CAAA;AAAhB,sCAAa;wBAAb,aAAa;IA1BzB,IAAA,eAAM,EAAC;QACN,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,oBAAQ;gBACjB,UAAU,EAAE,GAAG,EAAE;oBACf,OAAO,IAAI,oBAAQ,CAAC;wBAClB,WAAW,EAAE;4BACX,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;4BAC1C,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB;yBACnD;wBACD,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;wBAClC,cAAc,EAAE,IAAI;qBACrB,CAAC,CAAC;gBACL,CAAC;aACF;YACD;gBACE,OAAO,EAAE,UAAE;gBACX,QAAQ,EAAE,sBAAK;aAChB;YAED,gCAAc;YACd,sDAAwB;SACzB;QACD,WAAW,EAAE,EAAE;QACf,OAAO,EAAE,CAAC,gCAAc,EAAE,sDAAwB,CAAC;KACpD,CAAC;GACW,aAAa,CAAG"}
@@ -0,0 +1,19 @@
1
+ export type ZolaStoredFileRef = {
2
+ filepath: string;
3
+ bucketName: string;
4
+ contentType: string;
5
+ originalname: string;
6
+ };
7
+ export interface ZolaObjectStorage {
8
+ uploadFile(file: Express.Multer.File, bucketName: string, metaData?: Record<string, string>): Promise<ZolaStoredFileRef>;
9
+ uploadBuffer(buffer: Buffer, originalname: string, mimetype: string, bucketName: string, metaData?: Record<string, string>): Promise<ZolaStoredFileRef>;
10
+ generatePresignedUploadUrl(fileInfo: {
11
+ originalname: string;
12
+ contentType?: string;
13
+ }, bucketName: string): Promise<{
14
+ presignedUrl: string;
15
+ file: ZolaStoredFileRef;
16
+ }>;
17
+ generatePresignedDownloadUrl(fileInfo: Pick<ZolaStoredFileRef, 'bucketName' | 'filepath' | 'contentType' | 'originalname'>): Promise<string>;
18
+ }
19
+ export declare const ZOLA_STORAGE_CONTRACT_VERSION: 1;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ZOLA_STORAGE_CONTRACT_VERSION = void 0;
4
+ exports.ZOLA_STORAGE_CONTRACT_VERSION = 1;
5
+ //# sourceMappingURL=zola-object-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zola-object-storage.js","sourceRoot":"","sources":["../src/zola-object-storage.ts"],"names":[],"mappings":";;;AA4Ca,QAAA,6BAA6B,GAAG,CAAU,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zola_do/seaweed",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "AWS S3-compatible storage for NestJS",
5
5
  "author": "zolaDO",
6
6
  "license": "ISC",