@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.
Files changed (2) hide show
  1. package/dist/index.js +98 -0
  2. 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanvika/cloudinary",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Centralized Cloudinary SDK for the Sanvika ecosystem — proxy gateway mode (zero credentials) + legacy direct mode",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",