@pelatform/storage 1.0.6 → 1.0.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.
@@ -1,11 +1,5 @@
1
1
  // src/helpers.ts
2
2
  import { lookup } from "mime-types";
3
- function getSupabasePublicUrl(key) {
4
- const bucket = process.env.PELATFORM_S3_BUCKET || "";
5
- const endpoint = process.env.PELATFORM_S3_ENDPOINT || "";
6
- const publicUrl = endpoint.replace(/\.storage/, "").replace(/\/storage\/v1\/s3$/, "");
7
- return `${publicUrl}/storage/v1/object/public/${bucket}/${key}?v=${Date.now()}`;
8
- }
9
3
  function generateFileKey(originalName, prefix) {
10
4
  const timestamp = Date.now();
11
5
  const random = Math.random().toString(36).substring(2, 8);
@@ -89,10 +83,15 @@ function parseS3Url(url) {
89
83
  return {};
90
84
  }
91
85
  }
92
- function buildPublicUrl(baseUrl, bucket, key) {
93
- const cleanBaseUrl = baseUrl.replace(/\/$/, "");
86
+ function buildPublicUrl(baseUrl, bucket, key, supabase) {
87
+ let cleanBaseUrl;
88
+ cleanBaseUrl = baseUrl.replace(/\/$/, "");
94
89
  const cleanKey = key.replace(/^\//, "");
95
- return `${cleanBaseUrl}/${bucket}/${cleanKey}`;
90
+ if (supabase) {
91
+ cleanBaseUrl = cleanBaseUrl.replace(/\.storage/, "").replace(/\/storage\/v1\/s3$/, "");
92
+ cleanBaseUrl = `${cleanBaseUrl}/storage/v1/object/public`;
93
+ }
94
+ return `${cleanBaseUrl}/${bucket === "" ? "" : `${bucket}/`}${cleanKey}`;
96
95
  }
97
96
  function validateS3Key(key) {
98
97
  if (!key || key.length === 0) {
@@ -384,7 +383,6 @@ function detectFileTypeFromContent(buffer) {
384
383
  }
385
384
 
386
385
  export {
387
- getSupabasePublicUrl,
388
386
  generateFileKey,
389
387
  getMimeType,
390
388
  validateFileSize,
@@ -38,12 +38,12 @@ declare class CloudinaryService implements StorageInterface {
38
38
  downloadFile(key: string): Promise<DownloadResult>;
39
39
  deleteFile(key: string): Promise<DeleteResult>;
40
40
  deleteFiles(keys: string[]): Promise<BatchDeleteResult>;
41
+ listFiles(prefix?: string, maxKeys?: number): Promise<ListResult>;
41
42
  fileExists(key: string): Promise<boolean>;
42
43
  copyFile(sourceKey: string, destinationKey: string, metadata?: Record<string, string>): Promise<CopyResult>;
43
44
  moveFile(sourceKey: string, destinationKey: string, metadata?: Record<string, string>): Promise<MoveResult>;
44
45
  duplicateFile(sourceKey: string, destinationKey: string, metadata?: Record<string, string>): Promise<DuplicateResult>;
45
46
  renameFile(sourceKey: string, destinationKey: string, metadata?: Record<string, string>): Promise<MoveResult>;
46
- listFiles(prefix?: string, maxKeys?: number): Promise<ListResult>;
47
47
  getDownloadUrl(key: string, expiresIn?: number): Promise<PresignedUrlResult>;
48
48
  getUploadUrl(key: string, contentType?: string, expiresIn?: number): Promise<PresignedUrlResult>;
49
49
  createFolderPath(path: string): Promise<CreateFolderResult>;
@@ -32,10 +32,13 @@ var CloudinaryProvider = class {
32
32
  }
33
33
  const keyParts = options.key.split("/");
34
34
  let folder = "";
35
- let publicId = options.key;
35
+ let publicId = keyParts[keyParts.length - 1];
36
36
  if (keyParts.length > 1) {
37
37
  folder = keyParts.slice(0, -1).join("/");
38
- publicId = keyParts[keyParts.length - 1];
38
+ }
39
+ const dotIndex = publicId.lastIndexOf(".");
40
+ if (dotIndex > 0) {
41
+ publicId = publicId.slice(0, dotIndex);
39
42
  }
40
43
  const uploadOptions = {
41
44
  public_id: publicId,
@@ -47,8 +50,11 @@ var CloudinaryProvider = class {
47
50
  if (folder) {
48
51
  uploadOptions.folder = folder;
49
52
  }
53
+ if (this.config.folder) {
54
+ uploadOptions.folder = `${this.config.folder}/${folder}`;
55
+ }
50
56
  const result = await cloudinary.uploader.upload(fileData, uploadOptions);
51
- const publicUrl = this.getPublicUrl(result.public_id);
57
+ const publicUrl = this.getPublicUrl(result.public_id, result.format);
52
58
  return {
53
59
  success: true,
54
60
  key: result.public_id,
@@ -102,6 +108,13 @@ var CloudinaryProvider = class {
102
108
  const filename = keyParts[keyParts.length - 1];
103
109
  publicId = `${folder}/${filename}`;
104
110
  }
111
+ const dotIndex = publicId.lastIndexOf(".");
112
+ if (dotIndex > 0) {
113
+ publicId = publicId.slice(0, dotIndex);
114
+ }
115
+ if (this.config.folder) {
116
+ publicId = `${this.config.folder}/${publicId}`;
117
+ }
105
118
  let resourceType = "raw";
106
119
  try {
107
120
  await cloudinary.api.resource(publicId, { resource_type: "image" });
@@ -254,11 +267,11 @@ var CloudinaryProvider = class {
254
267
  };
255
268
  }
256
269
  }
257
- getPublicUrl(key) {
270
+ getPublicUrl(key, extension) {
258
271
  const protocol = this.config.secure !== false ? "https" : "http";
259
272
  const baseUrl = `${protocol}://res.cloudinary.com/${this.config.cloudName}`;
260
273
  const publicId = key;
261
- return `${baseUrl}/image/upload/${publicId}`;
274
+ return `${baseUrl}/image/upload/${publicId}${extension ? `.${extension}` : ""}`;
262
275
  }
263
276
  // Folder operations
264
277
  async createFolder(options) {
@@ -433,6 +446,9 @@ var CloudinaryService = class {
433
446
  async deleteFiles(keys) {
434
447
  return this.batchDelete({ keys });
435
448
  }
449
+ async listFiles(prefix, maxKeys) {
450
+ return this.list({ prefix, maxKeys });
451
+ }
436
452
  async fileExists(key) {
437
453
  const result = await this.exists(key);
438
454
  return result.exists;
@@ -449,9 +465,6 @@ var CloudinaryService = class {
449
465
  async renameFile(sourceKey, destinationKey, metadata) {
450
466
  return this.moveFile(sourceKey, destinationKey, metadata);
451
467
  }
452
- async listFiles(prefix, maxKeys) {
453
- return this.list({ prefix, maxKeys });
454
- }
455
468
  async getDownloadUrl(key, expiresIn) {
456
469
  return this.getPresignedUrl({ key, operation: "get", expiresIn });
457
470
  }
package/dist/helpers.d.ts CHANGED
@@ -2,19 +2,6 @@
2
2
  * Storage helper utilities
3
3
  * Provides utility functions for file operations, MIME type detection, and path manipulation
4
4
  */
5
- /**
6
- * Generate public URL for a storage key using environment variables
7
- * @param key The storage key/path
8
- * @returns Constructed public URL with timestamp versioning
9
- * @public
10
- *
11
- * @example
12
- * ```typescript
13
- * // Requires env vars: PELATFORM_S3_BUCKET, PELATFORM_S3_ENDPOINT
14
- * const url = getSupabasePublicUrl('folder/image.png');
15
- * ```
16
- */
17
- declare function getSupabasePublicUrl(key: string): string;
18
5
  /**
19
6
  * Generate a unique file key with timestamp and random string
20
7
  * @param originalName Original file name
@@ -234,7 +221,7 @@ declare function parseS3Url(url: string): {
234
221
  * // Returns: "https://storage.example.com/assets/images/logo.png"
235
222
  * ```
236
223
  */
237
- declare function buildPublicUrl(baseUrl: string, bucket: string, key: string): string;
224
+ declare function buildPublicUrl(baseUrl: string, bucket: string, key: string, supabase?: boolean): string;
238
225
  /**
239
226
  * Validate S3 key format according to AWS S3 naming rules
240
227
  * @param key S3 object key to validate
@@ -772,4 +759,4 @@ declare function validateBatchFiles(files: File[], options: {
772
759
  */
773
760
  declare function detectFileTypeFromContent(buffer: Buffer): string;
774
761
 
775
- export { base64ToBuffer, bufferToBase64, buildPublicUrl, detectFileTypeFromContent, extractS3Info, fileToBuffer, formatFileSize, generateBatchKeys, generateCacheControl, generateFileHash, generateFileKey, generateUniqueKey, getContentDisposition, getFileExtension, getFileInfo, getFileName, getMimeType, getParentPath, getSupabasePublicUrl, isAudioFile, isDocumentFile, isImageFile, isVideoFile, joinPath, normalizePath, parseS3Url, sanitizeFileName, validateBatchFiles, validateBucketName, validateFileSize, validateFileType, validateS3Config, validateS3Key };
762
+ export { base64ToBuffer, bufferToBase64, buildPublicUrl, detectFileTypeFromContent, extractS3Info, fileToBuffer, formatFileSize, generateBatchKeys, generateCacheControl, generateFileHash, generateFileKey, generateUniqueKey, getContentDisposition, getFileExtension, getFileInfo, getFileName, getMimeType, getParentPath, isAudioFile, isDocumentFile, isImageFile, isVideoFile, joinPath, normalizePath, parseS3Url, sanitizeFileName, validateBatchFiles, validateBucketName, validateFileSize, validateFileType, validateS3Config, validateS3Key };
package/dist/helpers.js CHANGED
@@ -17,7 +17,6 @@ import {
17
17
  getFileName,
18
18
  getMimeType,
19
19
  getParentPath,
20
- getSupabasePublicUrl,
21
20
  isAudioFile,
22
21
  isDocumentFile,
23
22
  isImageFile,
@@ -32,7 +31,7 @@ import {
32
31
  validateFileType,
33
32
  validateS3Config,
34
33
  validateS3Key
35
- } from "./chunk-CT5YOIGU.js";
34
+ } from "./chunk-7IPYXDG4.js";
36
35
  export {
37
36
  base64ToBuffer,
38
37
  bufferToBase64,
@@ -52,7 +51,6 @@ export {
52
51
  getFileName,
53
52
  getMimeType,
54
53
  getParentPath,
55
- getSupabasePublicUrl,
56
54
  isAudioFile,
57
55
  isDocumentFile,
58
56
  isImageFile,
package/dist/s3.d.ts CHANGED
@@ -41,6 +41,7 @@ declare class S3Service implements StorageInterface {
41
41
  downloadFile(key: string): Promise<DownloadResult>;
42
42
  deleteFile(key: string): Promise<DeleteResult>;
43
43
  deleteFiles(keys: string[]): Promise<BatchDeleteResult>;
44
+ listFiles(prefix?: string, maxKeys?: number): Promise<ListResult>;
44
45
  fileExists(key: string): Promise<boolean>;
45
46
  copyFile(sourceKey: string, destinationKey: string, options?: Partial<CopyOptions>): Promise<CopyResult>;
46
47
  moveFile(sourceKey: string, destinationKey: string, options?: Partial<MoveOptions>): Promise<MoveResult>;
package/dist/s3.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  buildPublicUrl,
3
3
  getMimeType
4
- } from "./chunk-CT5YOIGU.js";
4
+ } from "./chunk-7IPYXDG4.js";
5
5
  import {
6
6
  loadS3Config
7
7
  } from "./chunk-ZTZZCC52.js";
@@ -291,11 +291,18 @@ var FileOperations = class {
291
291
  }
292
292
  }
293
293
  getPublicUrl(key) {
294
+ const isCloudflare = this.config.provider === "cloudflare-r2";
295
+ const isSupabase = this.config.provider === "supabase";
294
296
  if (this.config.publicUrl) {
295
- return buildPublicUrl(this.config.publicUrl, this.config.bucket, key);
297
+ return buildPublicUrl(
298
+ this.config.publicUrl,
299
+ isCloudflare ? "" : this.config.bucket,
300
+ key,
301
+ isSupabase
302
+ );
296
303
  }
297
304
  if (this.config.endpoint) {
298
- return buildPublicUrl(this.config.endpoint, this.config.bucket, key);
305
+ return buildPublicUrl(this.config.endpoint, this.config.bucket, key, isSupabase);
299
306
  }
300
307
  return `https://${this.config.bucket}.s3.${this.config.region}.amazonaws.com/${key}`;
301
308
  }
@@ -723,6 +730,9 @@ var S3Service = class {
723
730
  async deleteFiles(keys) {
724
731
  return this.batchDelete({ keys });
725
732
  }
733
+ async listFiles(prefix, maxKeys) {
734
+ return this.list({ prefix, maxKeys });
735
+ }
726
736
  async fileExists(key) {
727
737
  const result = await this.exists(key);
728
738
  return result.exists;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pelatform/storage",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Storage utilities for SaaS applications.",
5
5
  "author": "Pelatform",
6
6
  "license": "MIT",