@elchinabilov/nestjs-media-library 1.0.3 → 1.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 +106 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ Complete NestJS media management library with S3 integration, automatic image op
|
|
|
7
7
|
✅ **Database Migrations** - TypeORM migrations included
|
|
8
8
|
✅ **Single/Multiple File Upload** - Support for both single and multiple file uploads
|
|
9
9
|
✅ **Retrieve Files** - Get files as objects or arrays
|
|
10
|
+
✅ **Custom Meta Data** - Add custom metadata (userId, organizationId, etc.) to each file
|
|
10
11
|
✅ **Automatic Image Optimization** - Built-in image compression to WebP format
|
|
11
12
|
✅ **Multiple Conversions** - Generate thumbnails, medium, large sizes automatically
|
|
12
13
|
✅ **AWS S3 Integration** - Seamless S3 upload support
|
|
@@ -92,24 +93,44 @@ import { MediaService } from "@elchinabilov/nestjs-media-library";
|
|
|
92
93
|
export class YourService {
|
|
93
94
|
constructor(private mediaService: MediaService) {}
|
|
94
95
|
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
// Upload with custom meta data
|
|
97
|
+
async uploadFile(file: Express.Multer.File, userId: string, orgId: string) {
|
|
98
|
+
const media = await this.mediaService.uploadSingle(file, {
|
|
99
|
+
userId: userId,
|
|
100
|
+
organizationId: orgId,
|
|
101
|
+
category: "document",
|
|
102
|
+
uploadedBy: "admin",
|
|
103
|
+
});
|
|
104
|
+
|
|
97
105
|
console.log("Original:", media.url);
|
|
98
106
|
console.log("Thumbnail:", media.conversions.thumbnail);
|
|
99
|
-
console.log("
|
|
107
|
+
console.log("Meta:", media.meta);
|
|
100
108
|
return media;
|
|
101
109
|
}
|
|
102
110
|
|
|
103
|
-
async uploadMultiple(files: Express.Multer.File[]) {
|
|
104
|
-
return await this.mediaService.uploadMultiple(files
|
|
111
|
+
async uploadMultiple(files: Express.Multer.File[], projectId: string) {
|
|
112
|
+
return await this.mediaService.uploadMultiple(files, {
|
|
113
|
+
projectId: projectId,
|
|
114
|
+
type: "gallery",
|
|
115
|
+
});
|
|
105
116
|
}
|
|
106
117
|
|
|
107
118
|
async getMedia(id: string) {
|
|
108
119
|
return await this.mediaService.findOne(id);
|
|
109
120
|
}
|
|
110
121
|
|
|
111
|
-
|
|
112
|
-
|
|
122
|
+
// Filter by meta data
|
|
123
|
+
async getOrganizationMedia(orgId: string) {
|
|
124
|
+
return await this.mediaService.findAll({ organizationId: orgId });
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Update meta data
|
|
128
|
+
async approveDocument(mediaId: string, adminId: string) {
|
|
129
|
+
return await this.mediaService.updateMeta(mediaId, {
|
|
130
|
+
status: "approved",
|
|
131
|
+
approvedBy: adminId,
|
|
132
|
+
approvedAt: new Date().toISOString(),
|
|
133
|
+
});
|
|
113
134
|
}
|
|
114
135
|
|
|
115
136
|
async deleteMedia(id: string) {
|
|
@@ -127,7 +148,14 @@ The package provides ready-to-use REST endpoints:
|
|
|
127
148
|
```bash
|
|
128
149
|
POST /media/upload
|
|
129
150
|
Content-Type: multipart/form-data
|
|
130
|
-
Body:
|
|
151
|
+
Body:
|
|
152
|
+
- file (form-data)
|
|
153
|
+
- meta (optional JSON string)
|
|
154
|
+
|
|
155
|
+
# Example with cURL:
|
|
156
|
+
curl -X POST http://localhost:3000/media/upload \
|
|
157
|
+
-F "file=@photo.jpg" \
|
|
158
|
+
-F 'meta={"userId":"123","organizationId":"org_456","category":"profile"}'
|
|
131
159
|
```
|
|
132
160
|
|
|
133
161
|
Response:
|
|
@@ -146,6 +174,11 @@ Response:
|
|
|
146
174
|
"medium": "https://bucket.s3.amazonaws.com/media/uuid-medium.webp",
|
|
147
175
|
"large": "https://bucket.s3.amazonaws.com/media/uuid-large.webp"
|
|
148
176
|
},
|
|
177
|
+
"meta": {
|
|
178
|
+
"userId": "123",
|
|
179
|
+
"organizationId": "org_456",
|
|
180
|
+
"category": "profile"
|
|
181
|
+
},
|
|
149
182
|
"disk": "s3",
|
|
150
183
|
"createdAt": "2024-01-01T00:00:00.000Z"
|
|
151
184
|
}
|
|
@@ -156,13 +189,17 @@ Response:
|
|
|
156
189
|
```bash
|
|
157
190
|
POST /media/upload-multiple
|
|
158
191
|
Content-Type: multipart/form-data
|
|
159
|
-
Body:
|
|
192
|
+
Body:
|
|
193
|
+
- files (form-data, multiple)
|
|
194
|
+
- meta (optional JSON string)
|
|
160
195
|
```
|
|
161
196
|
|
|
162
|
-
### Get All Media
|
|
197
|
+
### Get All Media (with optional filter)
|
|
163
198
|
|
|
164
199
|
```bash
|
|
165
200
|
GET /media
|
|
201
|
+
GET /media?organizationId=org_123
|
|
202
|
+
GET /media?userId=user_456&category=profile
|
|
166
203
|
```
|
|
167
204
|
|
|
168
205
|
### Get Single Media
|
|
@@ -171,6 +208,18 @@ GET /media
|
|
|
171
208
|
GET /media/:id
|
|
172
209
|
```
|
|
173
210
|
|
|
211
|
+
### Update Meta Data
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
PATCH /media/:id/meta
|
|
215
|
+
Content-Type: application/json
|
|
216
|
+
|
|
217
|
+
{
|
|
218
|
+
"status": "approved",
|
|
219
|
+
"approvedBy": "admin_123"
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
174
223
|
### Delete Media
|
|
175
224
|
|
|
176
225
|
```bash
|
|
@@ -244,15 +293,61 @@ export class CustomController {
|
|
|
244
293
|
@Post("avatar")
|
|
245
294
|
@UseInterceptors(FileInterceptor("avatar"))
|
|
246
295
|
async uploadAvatar(@UploadedFile() file: Express.Multer.File) {
|
|
247
|
-
const media = await this.mediaService.uploadSingle(file
|
|
296
|
+
const media = await this.mediaService.uploadSingle(file, {
|
|
297
|
+
type: "avatar",
|
|
298
|
+
category: "profile",
|
|
299
|
+
});
|
|
300
|
+
|
|
248
301
|
return {
|
|
249
302
|
avatarUrl: media.url,
|
|
250
303
|
thumbnailUrl: media.conversions?.thumbnail,
|
|
304
|
+
metadata: media.meta,
|
|
251
305
|
};
|
|
252
306
|
}
|
|
253
307
|
}
|
|
254
308
|
```
|
|
255
309
|
|
|
310
|
+
### Meta Data Usage Examples
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
// E-commerce: Product image with metadata
|
|
314
|
+
await this.mediaService.uploadSingle(file, {
|
|
315
|
+
productId: "prod_123",
|
|
316
|
+
category: "product-image",
|
|
317
|
+
sku: "SKU-12345",
|
|
318
|
+
color: "red",
|
|
319
|
+
position: 0,
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
// SaaS: Company logo
|
|
323
|
+
await this.mediaService.uploadSingle(file, {
|
|
324
|
+
organizationId: "org_456",
|
|
325
|
+
companyName: "Acme Corp",
|
|
326
|
+
type: "logo",
|
|
327
|
+
planType: "premium",
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
// Social Media: Post images
|
|
331
|
+
await this.mediaService.uploadMultiple(files, {
|
|
332
|
+
userId: "user_789",
|
|
333
|
+
postId: "post_123",
|
|
334
|
+
hashtags: ["travel", "nature"],
|
|
335
|
+
location: "Baku, Azerbaijan",
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// Filter by meta
|
|
339
|
+
const orgMedia = await this.mediaService.findAll({
|
|
340
|
+
organizationId: "org_456",
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
// Update meta
|
|
344
|
+
await this.mediaService.updateMeta("media-id", {
|
|
345
|
+
status: "approved",
|
|
346
|
+
approvedBy: "admin_123",
|
|
347
|
+
approvedAt: new Date().toISOString(),
|
|
348
|
+
});
|
|
349
|
+
```
|
|
350
|
+
|
|
256
351
|
### Direct S3 Service Usage
|
|
257
352
|
|
|
258
353
|
```typescript
|
package/package.json
CHANGED