@sanvika/cloudinary 0.2.1 → 0.2.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/dist/index.js +98 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -512,10 +512,103 @@ function verifySanvikaWebhookSignature({ headers, rawBody, secret, toleranceSec
|
|
|
512
512
|
const ok = crypto2.timingSafeEqual(a, b);
|
|
513
513
|
return { valid: ok, reason: ok ? void 0 : "signature_mismatch" };
|
|
514
514
|
}
|
|
515
|
+
|
|
516
|
+
// src/cloudinaryValidation.js
|
|
517
|
+
var MAX_IMAGE_SIZE = 5 * 1024 * 1024;
|
|
518
|
+
var MAX_PROFILE_PIC_SIZE = 6 * 1024 * 1024;
|
|
519
|
+
var MAX_VIDEO_SIZE = 100 * 1024 * 1024;
|
|
520
|
+
var SUPPORTED_IMAGE_FORMATS = [".jpg", ".jpeg", ".png", ".webp"];
|
|
521
|
+
var SUPPORTED_PROFILE_MIME_TYPES = ["image/jpeg", "image/jpg", "image/png"];
|
|
522
|
+
var SUPPORTED_VIDEO_FORMATS = [".mp4", ".mov", ".avi", ".wmv", ".flv", ".mkv", ".webm", ".m4v"];
|
|
523
|
+
function splitFileName(name) {
|
|
524
|
+
const safe = typeof name === "string" && name.trim() ? name.trim() : "";
|
|
525
|
+
const dotIdx = safe.lastIndexOf(".");
|
|
526
|
+
if (dotIdx <= 0) return { ext: "", base: safe || "asset" };
|
|
527
|
+
return { ext: safe.slice(dotIdx).toLowerCase(), base: safe.slice(0, dotIdx) };
|
|
528
|
+
}
|
|
529
|
+
function normalizeFolderPath(value, fallback) {
|
|
530
|
+
if (typeof value !== "string") return fallback;
|
|
531
|
+
const sanitized = value.trim().replace(/\\/g, "/").split("/").filter(Boolean).join("/");
|
|
532
|
+
return sanitized || fallback;
|
|
533
|
+
}
|
|
534
|
+
function createScopedPublicId({ baseName, userPrefix, timestamp }) {
|
|
535
|
+
const safeBaseName = baseName && baseName.trim() ? baseName.trim() : "asset";
|
|
536
|
+
const safePrefix = userPrefix && userPrefix.trim() ? userPrefix.trim() : "anon";
|
|
537
|
+
const safeTimestamp = timestamp && timestamp.trim() ? timestamp.trim() : Date.now().toString().slice(-6);
|
|
538
|
+
return `${safePrefix}_${safeTimestamp}_${safeBaseName}`;
|
|
539
|
+
}
|
|
540
|
+
function validateImageFile(file) {
|
|
541
|
+
const { ext: extFromName } = splitFileName(file.name || "");
|
|
542
|
+
const mimeExt = file.type ? `.${file.type.split("/")[1]}`.toLowerCase() : "";
|
|
543
|
+
const finalExt = extFromName || mimeExt;
|
|
544
|
+
if (!SUPPORTED_IMAGE_FORMATS.includes(finalExt)) {
|
|
545
|
+
return {
|
|
546
|
+
valid: false,
|
|
547
|
+
status: 415,
|
|
548
|
+
error: "INVALID_FORMAT",
|
|
549
|
+
message: `Unsupported format: ${finalExt}. Allowed: ${SUPPORTED_IMAGE_FORMATS.join(", ")}`
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
if (file.size > MAX_IMAGE_SIZE) {
|
|
553
|
+
return {
|
|
554
|
+
valid: false,
|
|
555
|
+
status: 413,
|
|
556
|
+
error: "FILE_TOO_LARGE",
|
|
557
|
+
message: `File size (${(file.size / 1024 / 1024).toFixed(2)}MB) exceeds the ${MAX_IMAGE_SIZE / 1024 / 1024}MB limit`
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
return { valid: true };
|
|
561
|
+
}
|
|
562
|
+
function validateProfilePicFile(file) {
|
|
563
|
+
if (!SUPPORTED_PROFILE_MIME_TYPES.includes(file.type)) {
|
|
564
|
+
return {
|
|
565
|
+
valid: false,
|
|
566
|
+
status: 415,
|
|
567
|
+
error: "INVALID_FORMAT",
|
|
568
|
+
message: "Unsupported format. Only JPG, JPEG, and PNG are allowed."
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
if (file.size > MAX_PROFILE_PIC_SIZE) {
|
|
572
|
+
return {
|
|
573
|
+
valid: false,
|
|
574
|
+
status: 413,
|
|
575
|
+
error: "FILE_TOO_LARGE",
|
|
576
|
+
message: `File size too large. Maximum is ${MAX_PROFILE_PIC_SIZE / 1024 / 1024}MB.`
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
return { valid: true };
|
|
580
|
+
}
|
|
581
|
+
function validateVideoFile(file) {
|
|
582
|
+
const { ext } = splitFileName(file.name || "");
|
|
583
|
+
if (!SUPPORTED_VIDEO_FORMATS.includes(ext)) {
|
|
584
|
+
return {
|
|
585
|
+
valid: false,
|
|
586
|
+
status: 415,
|
|
587
|
+
error: "INVALID_FORMAT",
|
|
588
|
+
message: `Unsupported format: ${ext}. Allowed: ${SUPPORTED_VIDEO_FORMATS.join(", ")}`
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
if (file.size > MAX_VIDEO_SIZE) {
|
|
592
|
+
return {
|
|
593
|
+
valid: false,
|
|
594
|
+
status: 413,
|
|
595
|
+
error: "FILE_TOO_LARGE",
|
|
596
|
+
message: `File size (${(file.size / 1024 / 1024).toFixed(2)}MB) exceeds the ${MAX_VIDEO_SIZE / 1024 / 1024}MB limit`
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
return { valid: true };
|
|
600
|
+
}
|
|
515
601
|
export {
|
|
516
602
|
CloudinaryError,
|
|
603
|
+
MAX_IMAGE_SIZE,
|
|
604
|
+
MAX_PROFILE_PIC_SIZE,
|
|
605
|
+
MAX_VIDEO_SIZE,
|
|
606
|
+
SUPPORTED_IMAGE_FORMATS,
|
|
607
|
+
SUPPORTED_PROFILE_MIME_TYPES,
|
|
608
|
+
SUPPORTED_VIDEO_FORMATS,
|
|
517
609
|
TRANSFORM_PRESETS,
|
|
518
610
|
configureSanvikaCloudinary,
|
|
611
|
+
createScopedPublicId,
|
|
519
612
|
deleteImage,
|
|
520
613
|
deleteImages,
|
|
521
614
|
extractPublicId,
|
|
@@ -530,14 +623,19 @@ export {
|
|
|
530
623
|
isCloudinaryUrl,
|
|
531
624
|
isProxyMode,
|
|
532
625
|
isRetriableError,
|
|
626
|
+
normalizeFolderPath,
|
|
533
627
|
pingCloudinary,
|
|
534
628
|
runCloudinaryDiagnostics,
|
|
629
|
+
splitFileName,
|
|
535
630
|
testCloudinaryWebhookSignature,
|
|
536
631
|
uploadImage,
|
|
537
632
|
uploadImages,
|
|
538
633
|
uploadRawFile,
|
|
539
634
|
uploadVideo,
|
|
635
|
+
validateImageFile,
|
|
636
|
+
validateProfilePicFile,
|
|
540
637
|
validatePublicId,
|
|
638
|
+
validateVideoFile,
|
|
541
639
|
verifySanvikaWebhookSignature,
|
|
542
640
|
withRetry
|
|
543
641
|
};
|
package/package.json
CHANGED