nestjs-r2-storage 1.4.0 → 1.4.2
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
|
@@ -332,48 +332,6 @@ const result = await photoManager.deletePhotosFromObject(product, photoFields);
|
|
|
332
332
|
// }
|
|
333
333
|
```
|
|
334
334
|
|
|
335
|
-
## Upload Detection (Update Operations)
|
|
336
|
-
|
|
337
|
-
The `updateObjectWithPhotos()` method uses intelligent upload detection to prevent unnecessary uploads and file deletions.
|
|
338
|
-
|
|
339
|
-
### Dual-Mode Detection
|
|
340
|
-
|
|
341
|
-
**Mode 1: Explicit Size Detection (when `sizeField` is defined)**
|
|
342
|
-
- Only treats a field as a new upload if `sizeField > 0`
|
|
343
|
-
- If `sizeField` is missing, null, or 0 → treats as existing file (no upload)
|
|
344
|
-
|
|
345
|
-
**Mode 2: Filename Comparison (when `sizeField` is NOT defined)**
|
|
346
|
-
- Compares base filenames between existing fileKey and incoming filename
|
|
347
|
-
- Strips path, extension, and trailing timestamps before comparing
|
|
348
|
-
- Only uploads if the base name differs
|
|
349
|
-
|
|
350
|
-
```typescript
|
|
351
|
-
// Example: existing fileKey = "product_1776949996526.png"
|
|
352
|
-
// Incoming filename = "product.png"
|
|
353
|
-
// extractBaseFilename returns "product" for both → no upload
|
|
354
|
-
|
|
355
|
-
// Example: existing fileKey = "product_1776949996526.png"
|
|
356
|
-
// Incoming filename = "new-product.png"
|
|
357
|
-
// extractBaseFilename returns "product" vs "new-product" → upload
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
### Detection Matrix
|
|
361
|
-
|
|
362
|
-
| Scenario | `sizeField` defined | Result |
|
|
363
|
-
|----------|---------------------|--------|
|
|
364
|
-
| Existing file unchanged | yes (size=0) | No upload, no delete |
|
|
365
|
-
| Existing file unchanged | no (same base) | No upload, no delete |
|
|
366
|
-
| Same filename resent | yes (size=0) | No upload |
|
|
367
|
-
| Same filename resent | no (same base) | No upload |
|
|
368
|
-
| New file uploaded | yes (size > 0) | Upload + replace old |
|
|
369
|
-
| New file (no sizeField) | no (different base) | Upload + replace old |
|
|
370
|
-
|
|
371
|
-
### Backward Compatibility
|
|
372
|
-
|
|
373
|
-
- Existing clients that send `sizeField > 0` continue to work as before
|
|
374
|
-
- Clients that don't send `sizeField` get automatic fallback to filename comparison
|
|
375
|
-
- No changes to DTO structure or API required
|
|
376
|
-
|
|
377
335
|
## Field Path Syntax
|
|
378
336
|
|
|
379
337
|
### Simple Nested Fields
|
|
@@ -448,16 +406,7 @@ R2StorageModule.forRootAsync({
|
|
|
448
406
|
|
|
449
407
|
## Changelog
|
|
450
408
|
|
|
451
|
-
### v1.
|
|
452
|
-
|
|
453
|
-
- **Dual-mode upload detection** for `updateObjectWithPhotos()`:
|
|
454
|
-
- Mode 1: Explicit size detection when `sizeField` is defined (size > 0 = new upload)
|
|
455
|
-
- Mode 2: Base filename comparison when `sizeField` is NOT defined
|
|
456
|
-
- **Deterministic file replacement** using `extractBaseFilename()` helper
|
|
457
|
-
- **Backward compatible**: Existing clients work unchanged, clients without `sizeField` get automatic fallback
|
|
458
|
-
- Removed heuristic-based upload detection (no longer relies on filename patterns or "/" presence)
|
|
459
|
-
|
|
460
|
-
### v1.3.4 (2026-04-23)
|
|
409
|
+
### v1.2.6 (2025-04-20)
|
|
461
410
|
|
|
462
411
|
- Refactored getNestedValue: access key first, then handle array segments
|
|
463
412
|
- Refactored setNestedValue: proper handling of empty brackets [] and indexed arrays [0]
|
|
@@ -1,55 +1,54 @@
|
|
|
1
|
-
import { CloudflareService } from "./cloudflare.service";
|
|
2
|
-
export interface PhotoField {
|
|
3
|
-
field: string;
|
|
4
|
-
urlField?: string;
|
|
5
|
-
sizeField?: string;
|
|
6
|
-
}
|
|
7
|
-
export interface PhotoUploadRequest {
|
|
8
|
-
field: string;
|
|
9
|
-
filename: string;
|
|
10
|
-
size: number;
|
|
11
|
-
prefix?: string;
|
|
12
|
-
}
|
|
13
|
-
export interface PhotoUploadResponse {
|
|
14
|
-
field: string;
|
|
15
|
-
fileKey: string;
|
|
16
|
-
uploadUrl: string;
|
|
17
|
-
publicUrl: string | null;
|
|
18
|
-
filename?: string;
|
|
19
|
-
}
|
|
20
|
-
export interface CreatePhotosResult<T extends Record<string, any>> {
|
|
21
|
-
updatedPayload: T;
|
|
22
|
-
uploadUrls: PhotoUploadResponse[];
|
|
23
|
-
totalStorageUsed: number;
|
|
24
|
-
}
|
|
25
|
-
export interface UpdatePhotosResult<T extends Record<string, any>> {
|
|
26
|
-
updatedPayload: T;
|
|
27
|
-
uploadUrls: PhotoUploadResponse[];
|
|
28
|
-
storageIncrease: number;
|
|
29
|
-
storageDecrease: number;
|
|
30
|
-
deletedFiles: string[];
|
|
31
|
-
}
|
|
32
|
-
export interface DeletePhotosResult {
|
|
33
|
-
deletedFiles: string[];
|
|
34
|
-
totalStorageFreed: number;
|
|
35
|
-
}
|
|
36
|
-
export interface AppendUrlsOptions {
|
|
37
|
-
urlField?: (field: string) => string;
|
|
38
|
-
}
|
|
39
|
-
export declare class PhotoManagerService {
|
|
40
|
-
private readonly cloudflareService;
|
|
41
|
-
constructor(cloudflareService: CloudflareService);
|
|
42
|
-
appendPhotoUrls<T extends Record<string, any>>(payload: T[], photoFields: PhotoField[]): Promise<T[]>;
|
|
43
|
-
private handleSingleFieldUrl;
|
|
44
|
-
private handleArrayFieldUrls;
|
|
45
|
-
createObjectWithPhotos<T extends Record<string, any>>(payload: T, photoFields: PhotoField[], filePrefix?: string): Promise<CreatePhotosResult<T>>;
|
|
46
|
-
updateObjectWithPhotos<T extends Record<string, any>>(payload: T, existingObject: T, photoFields: PhotoField[], filePrefix?: string): Promise<UpdatePhotosResult<T>>;
|
|
47
|
-
deletePhotosFromObject<T extends Record<string, any>>(object: T, photoFields: PhotoField[]): Promise<DeletePhotosResult>;
|
|
48
|
-
private extractPhotoUploadRequests;
|
|
49
|
-
private extractArrayFieldUploadRequests;
|
|
50
|
-
private extractExistingFiles;
|
|
51
|
-
|
|
52
|
-
private
|
|
53
|
-
private
|
|
54
|
-
|
|
55
|
-
}
|
|
1
|
+
import { CloudflareService } from "./cloudflare.service";
|
|
2
|
+
export interface PhotoField {
|
|
3
|
+
field: string;
|
|
4
|
+
urlField?: string;
|
|
5
|
+
sizeField?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface PhotoUploadRequest {
|
|
8
|
+
field: string;
|
|
9
|
+
filename: string;
|
|
10
|
+
size: number;
|
|
11
|
+
prefix?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface PhotoUploadResponse {
|
|
14
|
+
field: string;
|
|
15
|
+
fileKey: string;
|
|
16
|
+
uploadUrl: string;
|
|
17
|
+
publicUrl: string | null;
|
|
18
|
+
filename?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface CreatePhotosResult<T extends Record<string, any>> {
|
|
21
|
+
updatedPayload: T;
|
|
22
|
+
uploadUrls: PhotoUploadResponse[];
|
|
23
|
+
totalStorageUsed: number;
|
|
24
|
+
}
|
|
25
|
+
export interface UpdatePhotosResult<T extends Record<string, any>> {
|
|
26
|
+
updatedPayload: T;
|
|
27
|
+
uploadUrls: PhotoUploadResponse[];
|
|
28
|
+
storageIncrease: number;
|
|
29
|
+
storageDecrease: number;
|
|
30
|
+
deletedFiles: string[];
|
|
31
|
+
}
|
|
32
|
+
export interface DeletePhotosResult {
|
|
33
|
+
deletedFiles: string[];
|
|
34
|
+
totalStorageFreed: number;
|
|
35
|
+
}
|
|
36
|
+
export interface AppendUrlsOptions {
|
|
37
|
+
urlField?: (field: string) => string;
|
|
38
|
+
}
|
|
39
|
+
export declare class PhotoManagerService {
|
|
40
|
+
private readonly cloudflareService;
|
|
41
|
+
constructor(cloudflareService: CloudflareService);
|
|
42
|
+
appendPhotoUrls<T extends Record<string, any>>(payload: T[], photoFields: PhotoField[]): Promise<T[]>;
|
|
43
|
+
private handleSingleFieldUrl;
|
|
44
|
+
private handleArrayFieldUrls;
|
|
45
|
+
createObjectWithPhotos<T extends Record<string, any>>(payload: T, photoFields: PhotoField[], filePrefix?: string): Promise<CreatePhotosResult<T>>;
|
|
46
|
+
updateObjectWithPhotos<T extends Record<string, any>>(payload: T, existingObject: T, photoFields: PhotoField[], filePrefix?: string): Promise<UpdatePhotosResult<T>>;
|
|
47
|
+
deletePhotosFromObject<T extends Record<string, any>>(object: T, photoFields: PhotoField[]): Promise<DeletePhotosResult>;
|
|
48
|
+
private extractPhotoUploadRequests;
|
|
49
|
+
private extractArrayFieldUploadRequests;
|
|
50
|
+
private extractExistingFiles;
|
|
51
|
+
private determineFilesToDelete;
|
|
52
|
+
private normalizeFilename;
|
|
53
|
+
private updateArrayFieldWithNewFileKey;
|
|
54
|
+
}
|