storemw-core-api 1.0.123 → 1.0.124

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.
@@ -36,13 +36,25 @@ const FileAwsS3StorageProvider = (options) => {
36
36
  if (!basePath && dirParts.length <= 0) {
37
37
  finalBasePath = ``;
38
38
  }
39
- finalPublicBaseUrl = [finalPublicBaseUrl, basePath, ...dirParts].filter(Boolean).join('/');
39
+ // finalPublicBaseUrl = [finalPublicBaseUrl, basePath, ...dirParts].filter(Boolean).join('/');
40
+ // ✅ Cross-platform safe public URL
41
+ finalPublicBaseUrl = [finalPublicBaseUrl, basePath, ...dirParts]
42
+ .filter(Boolean)
43
+ .map(p => p.replace(/\\/g, '/')) // converts Windows '\' to '/'
44
+ .join('/');
40
45
  const uniqueId = (0, crypto_1.randomUUID)();
41
46
  const ext = path_1.default.extname(fileName);
42
47
  const uniqueName = `${uniqueId}${ext}`;
43
48
  const uniqueNameThumbnail = `${uniqueId}${thumbnailOptions.suffix}.${thumbnailOptions.ext}`;
44
- const objectPath = finalBasePath ? `${finalBasePath}/${uniqueName}` : uniqueName;
45
- const objectThumbnailPath = finalBasePath ? `${finalBasePath}/${uniqueNameThumbnail}` : uniqueNameThumbnail;
49
+ // const objectPath = finalBasePath ? `${finalBasePath}/${uniqueName}` : uniqueName;
50
+ // const objectThumbnailPath = finalBasePath ? `${finalBasePath}/${uniqueNameThumbnail}` : uniqueNameThumbnail;
51
+ // ✅ Cross-platform safe object paths for S3
52
+ const objectPath = finalBasePath
53
+ ? path_1.default.posix.join(finalBasePath.split(path_1.default.sep).join('/'), uniqueName)
54
+ : uniqueName;
55
+ const objectThumbnailPath = finalBasePath
56
+ ? path_1.default.posix.join(finalBasePath.split(path_1.default.sep).join('/'), uniqueNameThumbnail)
57
+ : uniqueNameThumbnail;
46
58
  // Upload main file
47
59
  await s3.send(new client_s3_1.PutObjectCommand({
48
60
  Bucket: bucketName,
@@ -1 +1 @@
1
- {"version":3,"file":"FileAwsS3StorageProvider.js","sourceRoot":"","sources":["../../../src/services/file/FileAwsS3StorageProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { S3Client, PutObjectCommand, DeleteObjectCommand } from \"@aws-sdk/client-s3\";\nimport path from \"path\";\nimport { randomUUID } from \"crypto\";\nimport { dayjs } from \"@/utils\";\nimport { FileModuleRef } from \"./FileService\";\nimport { FileStorageProviderResult } from \"./FileStorageProviderRegistry\";\n\nexport type FileAwsS3ProviderOptions = {\n bucketName: string;\n region?: string; // AWS region\n basePath?: string; // optional folder prefix\n skipFoldernameByModuleRef?: boolean;\n skipFoldernameByDate?: boolean;\n publicBaseUrl?: string; // optional, e.g., https://bucket-name.s3.amazonaws.com\n credentials?: {\n accessKeyId: string;\n secretAccessKey: string;\n sessionToken?: string;\n }\n}\n\nexport type FileAwsS3UploadFileProps = {\n buffer: Buffer;\n bufferThumbnail: Buffer;\n thumbnailOptions: {\n suffix: string;\n ext: string;\n mimeType: string;\n };\n mimeType: string;\n foldernameDate?: string;\n fileName: string;\n}\n\nexport const FileAwsS3StorageProvider = (options: FileAwsS3ProviderOptions) => {\n const {\n bucketName,\n region,\n basePath = \"\",\n skipFoldernameByModuleRef = false,\n skipFoldernameByDate = false,\n publicBaseUrl,\n credentials,\n } = options;\n\n const s3 = new S3Client({ region, credentials });\n\n const uploadFile = async <T extends FileModuleRef>({\n field_ref,\n field_module,\n buffer,\n bufferThumbnail,\n thumbnailOptions,\n mimeType,\n foldernameDate,\n fileName,\n }: T & FileAwsS3UploadFileProps): Promise<FileStorageProviderResult> => {\n\n // const now = dayjs(foldernameDate).isValid() ? dayjs(foldernameDate) : dayjs();\n // const year = now.format(\"YYYY\");\n // const month = now.format(\"MM\");\n // const day = now.format(\"DD\");\n\n // const dirParts = [];\n // if (!skipFoldernameByModuleRef) dirParts.push(field_ref, field_module);\n // if (!skipFoldernameByDate) dirParts.push(year, month, day);\n\n const now = dayjs(foldernameDate).isValid() ? dayjs(foldernameDate) : dayjs();\n const year = now.format(\"YYYY\");\n const month = now.format(\"MM\");\n const day = now.format(\"DD\");\n\n let finalPublicBaseUrl = `${publicBaseUrl}`\n let dirParts = []\n\n if (skipFoldernameByModuleRef === false) {\n dirParts.push(field_ref, field_module)\n }\n\n if (skipFoldernameByDate === false) {\n dirParts.push(year, month, day)\n }\n\n let finalBasePath = path.join(basePath, ...dirParts)\n\n // basePath is empty & dirParts are nothing\n if (!basePath && dirParts.length <= 0) {\n finalBasePath = ``\n }\n\n finalPublicBaseUrl = [finalPublicBaseUrl, basePath, ...dirParts].filter(Boolean).join('/');\n\n const uniqueId = randomUUID();\n const ext = path.extname(fileName);\n const uniqueName = `${uniqueId}${ext}`;\n const uniqueNameThumbnail = `${uniqueId}${thumbnailOptions.suffix}.${thumbnailOptions.ext}`;\n\n const objectPath = finalBasePath ? `${finalBasePath}/${uniqueName}` : uniqueName;\n const objectThumbnailPath = finalBasePath ? `${finalBasePath}/${uniqueNameThumbnail}` : uniqueNameThumbnail;\n\n // Upload main file\n await s3.send(new PutObjectCommand({\n Bucket: bucketName,\n Key: objectPath,\n Body: buffer,\n ContentType: mimeType,\n // ACL: \"public-read\"\n }));\n\n let thumbnailUrl = ``;\n\n // Upload thumbnail if exists\n if (bufferThumbnail) {\n await s3.send(new PutObjectCommand({\n Bucket: bucketName,\n Key: objectThumbnailPath,\n Body: bufferThumbnail,\n ContentType: thumbnailOptions.mimeType,\n // ACL: \"public-read\"\n }));\n thumbnailUrl = `${finalPublicBaseUrl}/${uniqueNameThumbnail}`;\n }\n\n const assetUrl = `${finalPublicBaseUrl}/${uniqueName}`;\n\n return {\n assetPath: objectPath,\n assetUrl,\n thumbnailUrl,\n filename: uniqueName,\n basePath: finalBasePath,\n ...(skipFoldernameByDate === false ? {\n folderName: { day: Number(day), month: Number(month), year: Number(year) }\n } : {})\n };\n\n };\n\n const removeFile = async (assetUrl: string, thumbnailUrl?: string) => {\n const removeObject = async (url: string) => {\n const key = url.split(`/${bucketName}/`)[1]; // naive extraction\n if (!key) return;\n await s3.send(new DeleteObjectCommand({ Bucket: bucketName, Key: key }));\n }\n\n await removeObject(assetUrl);\n if (thumbnailUrl) await removeObject(thumbnailUrl);\n\n return { success: true };\n };\n\n return { uploadFile, removeFile };\n}"]}
1
+ {"version":3,"file":"FileAwsS3StorageProvider.js","sourceRoot":"","sources":["../../../src/services/file/FileAwsS3StorageProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { S3Client, PutObjectCommand, DeleteObjectCommand } from \"@aws-sdk/client-s3\";\nimport path from \"path\";\nimport { randomUUID } from \"crypto\";\nimport { dayjs } from \"@/utils\";\nimport { FileModuleRef } from \"./FileService\";\nimport { FileStorageProviderResult } from \"./FileStorageProviderRegistry\";\n\nexport type FileAwsS3ProviderOptions = {\n bucketName: string;\n region?: string; // AWS region\n basePath?: string; // optional folder prefix\n skipFoldernameByModuleRef?: boolean;\n skipFoldernameByDate?: boolean;\n publicBaseUrl?: string; // optional, e.g., https://bucket-name.s3.amazonaws.com\n credentials?: {\n accessKeyId: string;\n secretAccessKey: string;\n sessionToken?: string;\n }\n}\n\nexport type FileAwsS3UploadFileProps = {\n buffer: Buffer;\n bufferThumbnail: Buffer;\n thumbnailOptions: {\n suffix: string;\n ext: string;\n mimeType: string;\n };\n mimeType: string;\n foldernameDate?: string;\n fileName: string;\n}\n\nexport const FileAwsS3StorageProvider = (options: FileAwsS3ProviderOptions) => {\n const {\n bucketName,\n region,\n basePath = \"\",\n skipFoldernameByModuleRef = false,\n skipFoldernameByDate = false,\n publicBaseUrl,\n credentials,\n } = options;\n\n const s3 = new S3Client({ region, credentials });\n\n const uploadFile = async <T extends FileModuleRef>({\n field_ref,\n field_module,\n buffer,\n bufferThumbnail,\n thumbnailOptions,\n mimeType,\n foldernameDate,\n fileName,\n }: T & FileAwsS3UploadFileProps): Promise<FileStorageProviderResult> => {\n\n // const now = dayjs(foldernameDate).isValid() ? dayjs(foldernameDate) : dayjs();\n // const year = now.format(\"YYYY\");\n // const month = now.format(\"MM\");\n // const day = now.format(\"DD\");\n\n // const dirParts = [];\n // if (!skipFoldernameByModuleRef) dirParts.push(field_ref, field_module);\n // if (!skipFoldernameByDate) dirParts.push(year, month, day);\n\n const now = dayjs(foldernameDate).isValid() ? dayjs(foldernameDate) : dayjs();\n const year = now.format(\"YYYY\");\n const month = now.format(\"MM\");\n const day = now.format(\"DD\");\n\n let finalPublicBaseUrl = `${publicBaseUrl}`\n let dirParts = []\n\n if (skipFoldernameByModuleRef === false) {\n dirParts.push(field_ref, field_module)\n }\n\n if (skipFoldernameByDate === false) {\n dirParts.push(year, month, day)\n }\n\n let finalBasePath = path.join(basePath, ...dirParts)\n\n // basePath is empty & dirParts are nothing\n if (!basePath && dirParts.length <= 0) {\n finalBasePath = ``\n }\n\n // finalPublicBaseUrl = [finalPublicBaseUrl, basePath, ...dirParts].filter(Boolean).join('/');\n\n // ✅ Cross-platform safe public URL\n finalPublicBaseUrl = [finalPublicBaseUrl, basePath, ...dirParts]\n .filter(Boolean)\n .map(p => p.replace(/\\\\/g, '/')) // converts Windows '\\' to '/'\n .join('/');\n\n const uniqueId = randomUUID();\n const ext = path.extname(fileName);\n const uniqueName = `${uniqueId}${ext}`;\n const uniqueNameThumbnail = `${uniqueId}${thumbnailOptions.suffix}.${thumbnailOptions.ext}`;\n\n // const objectPath = finalBasePath ? `${finalBasePath}/${uniqueName}` : uniqueName;\n // const objectThumbnailPath = finalBasePath ? `${finalBasePath}/${uniqueNameThumbnail}` : uniqueNameThumbnail;\n\n // ✅ Cross-platform safe object paths for S3\n const objectPath = finalBasePath\n ? path.posix.join(finalBasePath.split(path.sep).join('/'), uniqueName)\n : uniqueName;\n\n const objectThumbnailPath = finalBasePath\n ? path.posix.join(finalBasePath.split(path.sep).join('/'), uniqueNameThumbnail)\n : uniqueNameThumbnail;\n\n // Upload main file\n await s3.send(new PutObjectCommand({\n Bucket: bucketName,\n Key: objectPath,\n Body: buffer,\n ContentType: mimeType,\n // ACL: \"public-read\"\n }));\n\n let thumbnailUrl = ``;\n\n // Upload thumbnail if exists\n if (bufferThumbnail) {\n await s3.send(new PutObjectCommand({\n Bucket: bucketName,\n Key: objectThumbnailPath,\n Body: bufferThumbnail,\n ContentType: thumbnailOptions.mimeType,\n // ACL: \"public-read\"\n }));\n thumbnailUrl = `${finalPublicBaseUrl}/${uniqueNameThumbnail}`;\n }\n\n const assetUrl = `${finalPublicBaseUrl}/${uniqueName}`;\n\n return {\n assetPath: objectPath,\n assetUrl,\n thumbnailUrl,\n filename: uniqueName,\n basePath: finalBasePath,\n ...(skipFoldernameByDate === false ? {\n folderName: { day: Number(day), month: Number(month), year: Number(year) }\n } : {})\n };\n\n };\n\n const removeFile = async (assetUrl: string, thumbnailUrl?: string) => {\n const removeObject = async (url: string) => {\n const key = url.split(`/${bucketName}/`)[1]; // naive extraction\n if (!key) return;\n await s3.send(new DeleteObjectCommand({ Bucket: bucketName, Key: key }));\n }\n\n await removeObject(assetUrl);\n if (thumbnailUrl) await removeObject(thumbnailUrl);\n\n return { success: true };\n };\n\n return { uploadFile, removeFile };\n}"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "storemw-core-api",
3
- "version": "1.0.123",
3
+ "version": "1.0.124",
4
4
  "description": "STOREMW Core API",
5
5
  "main": "dist/app.js",
6
6
  "types": "dist/app.d.ts",