nestjs-r2-storage 1.1.1 → 1.2.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 CHANGED
@@ -17,16 +17,61 @@ Production-ready NestJS module for Cloudflare R2 object storage management.
17
17
  - **Array Field Support** - Handle paths like `products[].image`, `gallery[].photo`
18
18
  - **Storage Usage Tracking** - Track storage used, increased, and decreased
19
19
  - **Full CRUD Lifecycle** - Create, Update, Delete file operations
20
+ - **Access Control Modes** - Control public vs signed URL access (`private`, `public-read`, `hybrid`)
20
21
 
21
- ## Requirements
22
+ ## Access Control Modes
22
23
 
23
- - Node.js >= 18
24
- - NestJS >= 10.0.0 or >= 11.0.0
24
+ Cloudflare R2 does NOT enforce ACLs like AWS S3 - the R2 API ignores ACL headers. True security is achieved by controlling URL exposure.
25
25
 
26
- ## Installation
26
+ ### Modes
27
27
 
28
- ```bash
29
- npm install nestjs-r2-storage
28
+ | Mode | Public URLs | Signed URLs | Use Case |
29
+ |------|-------------|-------------|----------|
30
+ | `private` | Not allowed | Required | Maximum security - only signed access |
31
+ | `public-read` | Allowed | Optional | Public files (e.g., static assets) |
32
+ | `hybrid` | Allowed | Allowed | Mixed content (default) |
33
+
34
+ ### Private Mode
35
+
36
+ Only presigned URLs are allowed. Public URL generation throws `AccessModeError`.
37
+
38
+ ```typescript
39
+ R2StorageModule.forRoot({
40
+ // ... other options
41
+ accessMode: 'private',
42
+ publicUrlBase: 'https://cdn.example.com', // still configured but not used
43
+ });
44
+ ```
45
+
46
+ Response in private mode:
47
+ ```json
48
+ {
49
+ "uploadUrl": "https://signed-url...",
50
+ "publicUrl": null
51
+ }
52
+ ```
53
+
54
+ ### Public-Read Mode
55
+
56
+ Public URLs are generated. Signed URLs are optional.
57
+
58
+ ```typescript
59
+ R2StorageModule.forRoot({
60
+ // ... other options
61
+ accessMode: 'public-read',
62
+ publicUrlBase: 'https://cdn.example.com',
63
+ });
64
+ ```
65
+
66
+ ### Hybrid Mode (Default)
67
+
68
+ Both public and signed access are allowed for backward compatibility.
69
+
70
+ ```typescript
71
+ R2StorageModule.forRoot({
72
+ // ... other options
73
+ accessMode: 'hybrid', // default
74
+ });
30
75
  ```
31
76
 
32
77
  ## Quick Start
@@ -144,6 +189,26 @@ await cloudflare.deleteFile('uploads/avatar.png');
144
189
  const exists = await cloudflare.fileExists('uploads/avatar.png');
145
190
  ```
146
191
 
192
+ ### Presigned URL Security
193
+
194
+ The module uses secure presigned URL generation:
195
+
196
+ - **Content-Length is NOT signed** - Prevents `SignatureDoesNotMatch` errors (browsers calculate it differently)
197
+ - **Checksum headers disabled** - Uses `requestChecksumCalculation: "WHEN_REQUIRED"` to avoid R2 compatibility issues
198
+ - **Minimal signing** - Only signs `host` and `content-type` headers
199
+
200
+ ```typescript
201
+ const result = await cloudflare.getUploadUrl('avatar.png', 1024000);
202
+
203
+ // result = {
204
+ // uploadUrl: "https://signed-url...",
205
+ // fileKey: "uploads/avatar_123.png",
206
+ // publicUrl: "https://cdn.example.com/uploads/avatar_123.png",
207
+ // mimeType: "image/png",
208
+ // sizeField: 1024000 // Use this for client-side validation before upload
209
+ // }
210
+ ```
211
+
147
212
  ### PhotoManagerService
148
213
 
149
214
  High-level photo management.
@@ -278,6 +343,25 @@ products[].images[] -> products[0].images[0], products[0].images[1], ...
278
343
  | `region` | string | No | AWS region (default: 'auto') |
279
344
  | `publicUrlBase` | string | No | Base URL for public access |
280
345
  | `signedUrlExpiry` | number | No | Signed URL expiry in seconds (default: 3600) |
346
+ | `accessMode` | string | No | Access mode: `private`, `public-read`, `hybrid` (default: `hybrid`) |
347
+
348
+ ## Error Handling
349
+
350
+ ### AccessModeError
351
+
352
+ Thrown when attempting to generate public URLs in `private` access mode.
353
+
354
+ ```typescript
355
+ import { AccessModeError } from 'nestjs-r2-storage';
356
+
357
+ try {
358
+ const result = await cloudflare.getUploadUrl('file.png', 1024);
359
+ } catch (error) {
360
+ if (error instanceof AccessModeError) {
361
+ console.log(error.message); // "Public URL generation is not allowed in 'private' access mode..."
362
+ }
363
+ }
364
+ ```
281
365
 
282
366
  ## Async Configuration
283
367
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { StorageOptions, FileFieldConfig, PhotoFieldConfig, StorageModuleOptions, } from './r2-storage/interfaces/storage-options.interface';
2
- export { CloudflareService, UploadUrlResult, DownloadUrlResult, FileInfo, } from './r2-storage/cloudflare.service';
1
+ export { StorageOptions, FileFieldConfig, PhotoFieldConfig, StorageModuleOptions, AccessMode, } from './r2-storage/interfaces/storage-options.interface';
2
+ export { CloudflareService, UploadUrlResult, DownloadUrlResult, FileInfo, AccessModeError, } from './r2-storage/cloudflare.service';
3
3
  export { PhotoManagerService, PhotoField, PhotoUploadRequest, PhotoUploadResponse, CreatePhotosResult, UpdatePhotosResult, DeletePhotosResult, AppendUrlsOptions, } from './r2-storage/photo-manager.service';
4
4
  export { R2StorageModule, } from './r2-storage/r2-storage.module';
5
5
  export { PhotoFields, UploadUrls, StorageInfo, } from './r2-storage/decorators/photo-fields.decorator';
package/dist/index.js CHANGED
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getAllArrayItemPaths = exports.getArrayElementPath = exports.getArrayBasePath = exports.isArrayPath = exports.collectNestedValues = exports.setNestedValue = exports.getNestedValue = exports.parseFieldPath = exports.StorageInfo = exports.UploadUrls = exports.PhotoFields = exports.R2StorageModule = exports.PhotoManagerService = exports.CloudflareService = void 0;
3
+ exports.getAllArrayItemPaths = exports.getArrayElementPath = exports.getArrayBasePath = exports.isArrayPath = exports.collectNestedValues = exports.setNestedValue = exports.getNestedValue = exports.parseFieldPath = exports.StorageInfo = exports.UploadUrls = exports.PhotoFields = exports.R2StorageModule = exports.PhotoManagerService = exports.AccessModeError = exports.CloudflareService = void 0;
4
4
  var cloudflare_service_1 = require("./r2-storage/cloudflare.service");
5
5
  Object.defineProperty(exports, "CloudflareService", { enumerable: true, get: function () { return cloudflare_service_1.CloudflareService; } });
6
+ Object.defineProperty(exports, "AccessModeError", { enumerable: true, get: function () { return cloudflare_service_1.AccessModeError; } });
6
7
  var photo_manager_service_1 = require("./r2-storage/photo-manager.service");
7
8
  Object.defineProperty(exports, "PhotoManagerService", { enumerable: true, get: function () { return photo_manager_service_1.PhotoManagerService; } });
8
9
  var r2_storage_module_1 = require("./r2-storage/r2-storage.module");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAOA,sEAKyC;AAJvC,uHAAA,iBAAiB,OAAA;AAMnB,4EAS4C;AAR1C,4HAAA,mBAAmB,OAAA;AAUrB,oEAEwC;AADtC,oHAAA,eAAe,OAAA;AAGjB,yFAIwD;AAHtD,qHAAA,WAAW,OAAA;AACX,oHAAA,UAAU,OAAA;AACV,qHAAA,WAAW,OAAA;AAGb,0EAW8C;AAV5C,mHAAA,cAAc,OAAA;AACd,mHAAA,cAAc,OAAA;AACd,mHAAA,cAAc,OAAA;AACd,wHAAA,mBAAmB,OAAA;AACnB,gHAAA,WAAW,OAAA;AACX,qHAAA,gBAAgB,OAAA;AAChB,wHAAA,mBAAmB,OAAA;AACnB,yHAAA,oBAAoB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAQA,sEAMyC;AALvC,uHAAA,iBAAiB,OAAA;AAIjB,qHAAA,eAAe,OAAA;AAGjB,4EAS4C;AAR1C,4HAAA,mBAAmB,OAAA;AAUrB,oEAEwC;AADtC,oHAAA,eAAe,OAAA;AAGjB,yFAIwD;AAHtD,qHAAA,WAAW,OAAA;AACX,oHAAA,UAAU,OAAA;AACV,qHAAA,WAAW,OAAA;AAGb,0EAW8C;AAV5C,mHAAA,cAAc,OAAA;AACd,mHAAA,cAAc,OAAA;AACd,mHAAA,cAAc,OAAA;AACd,wHAAA,mBAAmB,OAAA;AACnB,gHAAA,WAAW,OAAA;AACX,qHAAA,gBAAgB,OAAA;AAChB,wHAAA,mBAAmB,OAAA;AACnB,yHAAA,oBAAoB,OAAA"}
@@ -1,14 +1,18 @@
1
- import { OnModuleInit, OnModuleDestroy } from '@nestjs/common';
1
+ import { OnModuleInit, OnModuleDestroy, BadRequestException } from '@nestjs/common';
2
2
  import { StorageOptions } from './interfaces/storage-options.interface';
3
+ export declare class AccessModeError extends BadRequestException {
4
+ constructor(message: string);
5
+ }
3
6
  export interface UploadUrlResult {
4
7
  uploadUrl: string;
5
8
  fileKey: string;
6
- publicUrl?: string;
9
+ publicUrl: string | null;
7
10
  mimeType: string;
11
+ sizeField?: number;
8
12
  }
9
13
  export interface DownloadUrlResult {
10
14
  downloadUrl: string;
11
- publicUrl?: string;
15
+ publicUrl: string | null;
12
16
  }
13
17
  export interface FileInfo {
14
18
  size: number;
@@ -20,7 +24,11 @@ export declare class CloudflareService implements OnModuleInit, OnModuleDestroy
20
24
  private s3Client;
21
25
  private options;
22
26
  private readonly defaultExpiry;
27
+ private readonly defaultAccessMode;
23
28
  constructor(storageOptions: StorageOptions);
29
+ private get accessMode();
30
+ private isPublicAccessAllowed;
31
+ private ensurePublicAccessAllowed;
24
32
  onModuleInit(): void;
25
33
  onModuleDestroy(): void;
26
34
  private initializeClient;
@@ -45,19 +45,38 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
45
45
  return function (target, key) { decorator(target, key, paramIndex); }
46
46
  };
47
47
  Object.defineProperty(exports, "__esModule", { value: true });
48
- exports.CloudflareService = void 0;
48
+ exports.CloudflareService = exports.AccessModeError = void 0;
49
49
  const common_1 = require("@nestjs/common");
50
50
  const client_s3_1 = require("@aws-sdk/client-s3");
51
51
  const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
52
52
  const path = __importStar(require("path"));
53
53
  const mime = __importStar(require("mime-types"));
54
54
  const constants_1 = require("./constants");
55
+ class AccessModeError extends common_1.BadRequestException {
56
+ constructor(message) {
57
+ super(message);
58
+ this.name = 'AccessModeError';
59
+ }
60
+ }
61
+ exports.AccessModeError = AccessModeError;
55
62
  let CloudflareService = class CloudflareService {
56
63
  constructor(storageOptions) {
57
64
  this.storageOptions = storageOptions;
58
65
  this.defaultExpiry = 3600;
66
+ this.defaultAccessMode = 'hybrid';
59
67
  this.options = storageOptions;
60
68
  }
69
+ get accessMode() {
70
+ return this.options.accessMode || this.defaultAccessMode;
71
+ }
72
+ isPublicAccessAllowed() {
73
+ return this.accessMode === 'public-read' || this.accessMode === 'hybrid';
74
+ }
75
+ ensurePublicAccessAllowed() {
76
+ if (this.accessMode === 'private') {
77
+ throw new AccessModeError('Public URL generation is not allowed in "private" access mode. Use presigned URLs for file access.');
78
+ }
79
+ }
61
80
  onModuleInit() {
62
81
  this.initializeClient();
63
82
  }
@@ -75,6 +94,7 @@ let CloudflareService = class CloudflareService {
75
94
  secretAccessKey: this.options.secretAccessKey,
76
95
  },
77
96
  forcePathStyle: true,
97
+ requestChecksumCalculation: 'WHEN_REQUIRED',
78
98
  });
79
99
  }
80
100
  setOptions(options) {
@@ -106,12 +126,14 @@ let CloudflareService = class CloudflareService {
106
126
  Bucket: this.options.bucketName,
107
127
  Key: finalFileKey,
108
128
  ContentType: mimeType,
109
- ContentLength: fileSize,
110
129
  });
111
130
  const expiry = this.options.signedUrlExpiry || this.defaultExpiry;
112
- const uploadUrl = await (0, s3_request_presigner_1.getSignedUrl)(this.s3Client, command, { expiresIn: expiry });
113
- let publicUrl;
114
- if (this.options.publicUrlBase) {
131
+ const uploadUrl = await (0, s3_request_presigner_1.getSignedUrl)(this.s3Client, command, {
132
+ expiresIn: expiry,
133
+ signableHeaders: new Set(['host', 'content-type']),
134
+ });
135
+ let publicUrl = null;
136
+ if (this.options.publicUrlBase && this.isPublicAccessAllowed()) {
115
137
  publicUrl = `${this.options.publicUrlBase}/${finalFileKey}`;
116
138
  }
117
139
  return {
@@ -119,6 +141,7 @@ let CloudflareService = class CloudflareService {
119
141
  fileKey: finalFileKey,
120
142
  publicUrl,
121
143
  mimeType,
144
+ sizeField: fileSize,
122
145
  };
123
146
  }
124
147
  async getDownloadUrl(fileKey) {
@@ -128,8 +151,8 @@ let CloudflareService = class CloudflareService {
128
151
  });
129
152
  const expiry = this.options.signedUrlExpiry || this.defaultExpiry;
130
153
  const downloadUrl = await (0, s3_request_presigner_1.getSignedUrl)(this.s3Client, command, { expiresIn: expiry });
131
- let publicUrl;
132
- if (this.options.publicUrlBase) {
154
+ let publicUrl = null;
155
+ if (this.options.publicUrlBase && this.isPublicAccessAllowed()) {
133
156
  publicUrl = `${this.options.publicUrlBase}/${fileKey}`;
134
157
  }
135
158
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"cloudflare.service.js","sourceRoot":"","sources":["../../src/r2-storage/cloudflare.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cloudflare.service.js","sourceRoot":"","sources":["../../src/r2-storage/cloudflare.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAwG;AACxG,kDAA0H;AAC1H,wEAA6D;AAC7D,2CAA6B;AAC7B,iDAAmC;AAEnC,2CAA8C;AAE9C,MAAa,eAAgB,SAAQ,4BAAmB;IACtD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AALD,0CAKC;AA2BM,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAM5B,YAC2B,cAA+C;QAA9B,mBAAc,GAAd,cAAc,CAAgB;QAJzD,kBAAa,GAAG,IAAI,CAAC;QACrB,sBAAiB,GAAe,QAAQ,CAAC;QAKxD,IAAI,CAAC,OAAO,GAAG,cAAc,CAAC;IAChC,CAAC;IAED,IAAY,UAAU;QACpB,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC,iBAAiB,CAAC;IAC3D,CAAC;IAEO,qBAAqB;QAC3B,OAAO,IAAI,CAAC,UAAU,KAAK,aAAa,IAAI,IAAI,CAAC,UAAU,KAAK,QAAQ,CAAC;IAC3E,CAAC;IAEO,yBAAyB;QAC/B,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAClC,MAAM,IAAI,eAAe,CACvB,oGAAoG,CACrG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,YAAY;QACV,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC1B,CAAC;IAED,eAAe;QACb,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC;IAEO,gBAAgB;QAUtB,IAAI,CAAC,QAAQ,GAAG,IAAI,oBAAQ,CAAC;YAC3B,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;YAC/B,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,MAAM;YACrC,WAAW,EAAE;gBACX,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW;gBACrC,eAAe,EAAE,IAAI,CAAC,OAAO,CAAC,eAAe;aAC9C;YACD,cAAc,EAAE,IAAI;YACpB,0BAA0B,EAAE,eAAe;SAC5C,CAAC,CAAC;IACL,CAAC;IAED,UAAU,CAAC,OAAuB;QAChC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC1B,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAEO,gBAAgB,CAAC,QAAgB;QACvC,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC/C,OAAO,GAAG,QAAQ,IAAI,SAAS,GAAG,GAAG,EAAE,CAAC;IAC1C,CAAC;IAEO,cAAc,CAAC,QAAgB,EAAE,sBAA8B,0BAA0B;QAC/F,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACvC,OAAO,QAAQ,IAAI,mBAAmB,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,YAAY,CAChB,OAAe,EACf,QAAgB,EAChB,cAAuB,EACvB,WAAoB;QAEpB,MAAM,QAAQ,GAAG,cAAc,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC1D,MAAM,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC1D,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;YACxC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,iBAAiB,EAAE;YACjD,CAAC,CAAC,iBAAiB,CAAC;QAEtB,MAAM,QAAQ,GAAG,WAAW,IAAI,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;QAYvE,MAAM,OAAO,GAAG,IAAI,4BAAgB,CAAC;YACnC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU;YAC/B,GAAG,EAAE,YAAY;YACjB,WAAW,EAAE,QAAQ;SACtB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,IAAI,IAAI,CAAC,aAAa,CAAC;QAMlE,MAAM,SAAS,GAAG,MAAM,IAAA,mCAAY,EAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE;YAC3D,SAAS,EAAE,MAAM;YACjB,eAAe,EAAE,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;SACnD,CAAC,CAAC;QAEH,IAAI,SAAS,GAAkB,IAAI,CAAC;QACpC,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,IAAI,CAAC,qBAAqB,EAAE,EAAE,CAAC;YAC/D,SAAS,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,YAAY,EAAE,CAAC;QAC9D,CAAC;QAED,OAAO;YACL,SAAS;YACT,OAAO,EAAE,YAAY;YACrB,SAAS;YACT,QAAQ;YACR,SAAS,EAAE,QAAQ;SACpB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,OAAe;QAClC,MAAM,OAAO,GAAG,IAAI,4BAAgB,CAAC;YACnC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU;YAC/B,GAAG,EAAE,OAAO;SACb,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,IAAI,IAAI,CAAC,aAAa,CAAC;QAClE,MAAM,WAAW,GAAG,MAAM,IAAA,mCAAY,EAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAEtF,IAAI,SAAS,GAAkB,IAAI,CAAC;QACpC,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,IAAI,CAAC,qBAAqB,EAAE,EAAE,CAAC;YAC/D,SAAS,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,OAAO,EAAE,CAAC;QACzD,CAAC;QAED,OAAO;YACL,WAAW;YACX,SAAS;SACV,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAAe;QAC9B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,+BAAmB,CAAC;gBACtC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU;gBAC/B,GAAG,EAAE,OAAO;aACb,CAAC,CAAC;YAEH,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,yBAAyB,OAAO,GAAG,EAAE,KAAK,CAAC,CAAC;YAC1D,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,QAAkB;QAClC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC7B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YAC/C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;QAC9B,CAAC,CAAC,CACH,CAAC;QAEF,OAAO;YACL,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/D,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;SAChE,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAe;QAC/B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,6BAAiB,CAAC;gBACpC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU;gBAC/B,GAAG,EAAE,OAAO;aACb,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACnD,OAAO;gBACL,IAAI,EAAE,QAAQ,CAAC,aAAa,IAAI,CAAC;gBACjC,YAAY,EAAE,QAAQ,CAAC,YAAY;gBACnC,WAAW,EAAE,QAAQ,CAAC,WAAW;aAClC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAAe;QAC9B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACjD,OAAO,QAAQ,KAAK,IAAI,CAAC;IAC3B,CAAC;IAED,eAAe,CAAC,MAAc,EAAE,QAAgB;QAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC1D,OAAO,GAAG,MAAM,IAAI,SAAS,IAAI,iBAAiB,EAAE,CAAC;IACvD,CAAC;CACF,CAAA;AAtNY,8CAAiB;4BAAjB,iBAAiB;IAD7B,IAAA,mBAAU,GAAE;IAQR,WAAA,IAAA,eAAM,EAAC,2BAAe,CAAC,CAAA;;GAPf,iBAAiB,CAsN7B"}
@@ -1,3 +1,4 @@
1
+ export type AccessMode = 'private' | 'public-read' | 'hybrid';
1
2
  export interface StorageOptions {
2
3
  endpoint: string;
3
4
  accessKeyId: string;
@@ -6,6 +7,7 @@ export interface StorageOptions {
6
7
  region?: string;
7
8
  publicUrlBase?: string;
8
9
  signedUrlExpiry?: number;
10
+ accessMode?: AccessMode;
9
11
  }
10
12
  export interface FileFieldConfig {
11
13
  field: string;
@@ -14,7 +14,7 @@ export interface PhotoUploadResponse {
14
14
  field: string;
15
15
  fileKey: string;
16
16
  uploadUrl: string;
17
- publicUrl?: string;
17
+ publicUrl: string | null;
18
18
  filename?: string;
19
19
  }
20
20
  export interface CreatePhotosResult<T extends Record<string, any>> {