sanity-plugin-s3-media 2.0.0 → 2.0.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.
@@ -454,9 +454,66 @@ const createThrottler = (concurrency = DEFAULT_CONCURRENCY) => {
454
454
  if (context === void 0)
455
455
  throw new Error("useAssetSourceActions must be used within an AssetSourceDispatchProvider");
456
456
  return context;
457
- }, fileAssetIdPattern = /^s3File-([a-zA-Z0-9_-]+)-([a-z0-9]+)$/, imageAssetIdPattern = /^s3Image-([a-zA-Z0-9_-]+)-(\d+)x(\d+)-([a-z0-9]+)$/, videoAssetIdPattern = /^s3Video-([a-zA-Z0-9_-]+)-(\d+)x(\d+)-([a-z0-9]+)$/;
458
- function parseFileAssetId(documentId) {
459
- const match = fileAssetIdPattern.exec(documentId);
457
+ }, s3FileAssetIdPattern = /^s3File-([a-zA-Z0-9_-]+)-([a-z0-9]+)$/, s3ImageAssetIdPattern = /^s3Image-([a-zA-Z0-9_-]+)-(\d+)x(\d+)-([a-z0-9]+)$/, s3VideoAssetIdPattern = /^s3Video-([a-zA-Z0-9_-]+)-(\d+)x(\d+)-([a-z0-9]+)$/, s3FileAssetFilenamePattern = /^([a-zA-Z0-9_-]+)\.([a-z0-9]+)$/i, s3ImageAssetFilenamePattern = /^([a-zA-Z0-9_-]+)-(\d+)x(\d+)\.([a-z0-9]+)$/i, s3VideoAssetFilenamePattern = /^([a-zA-Z0-9_-]+)-(\d+)x(\d+)\.([a-z0-9]+)$/i, s3AssetFilenamePattern = /^([a-zA-Z0-9_-]+)(?:-(\d+)x(\d+))?\.([a-z0-9]+)$/i, s3AssetIdPattern = new RegExp(`^(?:${S3AssetType.IMAGE}-[a-zA-Z0-9_-]+-\\d+x\\d+-[a-z0-9]+|${S3AssetType.VIDEO}-[a-zA-Z0-9_-]+-\\d+x\\d+-[a-z0-9]+|${S3AssetType.FILE}-[a-zA-Z0-9_-]+-[a-z0-9]+)$`), s3InProgressAssetId = "upload-in-progress-placeholder", s3VideoExtensions = /* @__PURE__ */ new Set(["mp4", "webm", "mov", "m4v", "avi", "mkv", "wmv", "flv", "mpeg", "mpg", "3gp", "ogv"]);
458
+ class UnresolvableError extends Error {
459
+ unresolvable = !0;
460
+ // The input may not be a valid source, so let's not type it as one
461
+ constructor(inputSource, message = "Failed to resolve asset ID from source") {
462
+ super(message), this.input = inputSource;
463
+ }
464
+ }
465
+ function isUnresolvableError(err) {
466
+ const error = err;
467
+ return !!(error.unresolvable && "input" in error);
468
+ }
469
+ function getForgivingResolver(method) {
470
+ return (...args) => {
471
+ try {
472
+ return method(...args);
473
+ } catch (err) {
474
+ if (isUnresolvableError(err))
475
+ return;
476
+ throw err;
477
+ }
478
+ };
479
+ }
480
+ function isObject$1(obj) {
481
+ return obj !== null && !Array.isArray(obj) && typeof obj == "object";
482
+ }
483
+ function isReference(ref) {
484
+ return isObject$1(ref) && typeof ref._ref == "string";
485
+ }
486
+ function isS3AssetObjectStub(stub) {
487
+ const item = stub;
488
+ return isObject$1(item) && !!item.asset && typeof item.asset == "object";
489
+ }
490
+ function isInProgressUpload(stub) {
491
+ const item = stub;
492
+ return isObject$1(item) && !!item._upload && !("asset" in item);
493
+ }
494
+ function isS3FileAsset(asset) {
495
+ return asset._type === "s3FileAsset";
496
+ }
497
+ function isS3ImageAsset(asset) {
498
+ return asset._type === "s3ImageAsset";
499
+ }
500
+ function isS3VideoAsset(asset) {
501
+ return asset._type === "s3VideoAsset";
502
+ }
503
+ function getFilename(input) {
504
+ if (!input)
505
+ return "";
506
+ let raw = input;
507
+ if (/^[a-zA-Z][a-zA-Z\d+.-]*:/.test(raw))
508
+ try {
509
+ raw = new URL(raw).pathname;
510
+ } catch {
511
+ }
512
+ const [withoutQuery = ""] = raw.split("?"), [withoutHash = ""] = withoutQuery.split("#"), parts = withoutHash.replace(/^\/+/, "").split("/").filter(Boolean);
513
+ return parts[parts.length - 1] ?? "";
514
+ }
515
+ function parseS3FileAssetId(documentId) {
516
+ const match = s3FileAssetIdPattern.exec(documentId);
460
517
  if (!match)
461
518
  throw new Error(`Malformed file asset ID '${documentId}'.`);
462
519
  const [, assetId, extension] = match;
@@ -466,8 +523,8 @@ function parseFileAssetId(documentId) {
466
523
  extension
467
524
  };
468
525
  }
469
- function parseImageAssetId(documentId) {
470
- const match = imageAssetIdPattern.exec(documentId);
526
+ function parseS3ImageAssetId(documentId) {
527
+ const match = s3ImageAssetIdPattern.exec(documentId);
471
528
  if (!match)
472
529
  throw new Error(`Malformed asset ID '${documentId}'.`);
473
530
  const [, assetId, widthString, heightString, extension] = match, width = Number(widthString), height = Number(heightString);
@@ -481,8 +538,8 @@ function parseImageAssetId(documentId) {
481
538
  extension
482
539
  };
483
540
  }
484
- function parseVideoAssetId(documentId) {
485
- const match = videoAssetIdPattern.exec(documentId);
541
+ function parseS3VideoAssetId(documentId) {
542
+ const match = s3VideoAssetIdPattern.exec(documentId);
486
543
  if (!match)
487
544
  throw new Error(`Malformed asset ID '${documentId}'.`);
488
545
  const [, assetId, widthString, heightString, extension] = match, width = Number(widthString), height = Number(heightString);
@@ -496,15 +553,50 @@ function parseVideoAssetId(documentId) {
496
553
  extension
497
554
  };
498
555
  }
556
+ function parseS3FileAssetFilename(filename) {
557
+ const file = getFilename(filename), match = s3FileAssetFilenamePattern.exec(file);
558
+ if (!match || s3ImageAssetFilenamePattern.test(file))
559
+ throw new Error(`Malformed file asset filename '${filename}'.`);
560
+ const [, assetId, extension] = match;
561
+ return parseS3FileAssetId(`${S3AssetType.FILE}-${assetId}-${extension.toLowerCase()}`);
562
+ }
563
+ function parseS3ImageAssetFilename(filename) {
564
+ const file = getFilename(filename), match = s3ImageAssetFilenamePattern.exec(file);
565
+ if (!match)
566
+ throw new Error(`Malformed image asset filename '${filename}'.`);
567
+ const [, assetId, width, height, extension] = match;
568
+ return parseS3ImageAssetId(`${S3AssetType.IMAGE}-${assetId}-${width}x${height}-${extension.toLowerCase()}`);
569
+ }
570
+ function parseS3VideoAssetFilename(filename) {
571
+ const file = getFilename(filename), match = s3VideoAssetFilenamePattern.exec(file);
572
+ if (!match)
573
+ throw new Error(`Malformed video asset filename '${filename}'.`);
574
+ const [, assetId, width, height, extension] = match;
575
+ return parseS3VideoAssetId(`${S3AssetType.VIDEO}-${assetId}-${width}x${height}-${extension.toLowerCase()}`);
576
+ }
577
+ function parseS3AssetFilename(filename) {
578
+ const file = getFilename(filename);
579
+ if (!s3AssetFilenamePattern.test(file))
580
+ throw new Error(`Malformed asset filename '${filename}'.`);
581
+ const match = s3ImageAssetFilenamePattern.exec(file);
582
+ if (match) {
583
+ const extension = match[4].toLowerCase();
584
+ return s3VideoExtensions.has(extension) ? parseS3VideoAssetFilename(file) : parseS3ImageAssetFilename(file);
585
+ }
586
+ return parseS3FileAssetFilename(file);
587
+ }
588
+ function isAbsoluteUrl(value) {
589
+ return /^[a-zA-Z][a-zA-Z\d+.-]*:/.test(value);
590
+ }
499
591
  function buildS3FilePath(documentId) {
500
592
  const {
501
593
  assetId,
502
594
  extension
503
- } = parseFileAssetId(documentId);
595
+ } = parseS3FileAssetId(documentId);
504
596
  return `${assetId}.${extension}`;
505
597
  }
506
- function buildS3FileUrl(assetId, options) {
507
- return `${options.baseUrl}/${buildS3FilePath(assetId)}`;
598
+ function buildS3FileUrl(documentId, options) {
599
+ return `${options.baseUrl}/${buildS3FilePath(documentId)}`;
508
600
  }
509
601
  function buildS3ImagePath(documentId) {
510
602
  const {
@@ -512,11 +604,11 @@ function buildS3ImagePath(documentId) {
512
604
  width,
513
605
  height,
514
606
  extension
515
- } = parseImageAssetId(documentId);
607
+ } = parseS3ImageAssetId(documentId);
516
608
  return `${assetId}-${width}x${height}.${extension}`;
517
609
  }
518
- function buildS3ImageUrl(assetId, options) {
519
- return `${options.baseUrl}/${buildS3ImagePath(assetId)}`;
610
+ function buildS3ImageUrl(documentId, options) {
611
+ return `${options.baseUrl}/${buildS3ImagePath(documentId)}`;
520
612
  }
521
613
  function buildS3VideoPath(documentId) {
522
614
  const {
@@ -524,95 +616,36 @@ function buildS3VideoPath(documentId) {
524
616
  width,
525
617
  height,
526
618
  extension
527
- } = parseVideoAssetId(documentId);
619
+ } = parseS3VideoAssetId(documentId);
528
620
  return `${assetId}-${width}x${height}.${extension}`;
529
621
  }
530
- function buildS3VideoUrl(assetId, options) {
531
- return `${options.baseUrl}/${buildS3VideoPath(assetId)}`;
532
- }
533
- function isObject$1(obj) {
534
- return obj !== null && !Array.isArray(obj) && typeof obj == "object";
622
+ function buildS3VideoUrl(documentId, options) {
623
+ return `${options.baseUrl}/${buildS3VideoPath(documentId)}`;
535
624
  }
536
- const idPattern = new RegExp(`^(?:${S3AssetType.IMAGE}-(?:[a-zA-Z0-9_]{24,40}|[a-f0-9]{40})+-\\d+x\\d+-[a-z0-9]+|${S3AssetType.VIDEO}-(?:[a-zA-Z0-9_]{24,40}|[a-f0-9]{40})+-\\d+x\\d+-[a-z0-9]+|${S3AssetType.FILE}-(?:[a-zA-Z0-9_]{24,40}|[a-f0-9]{40})+-[a-z0-9]+)$`), inProgressAssetId = "upload-in-progress-placeholder";
537
- function isReferenceLike(source) {
538
- return isObject$1(source) && typeof source._ref == "string";
625
+ function isValidS3Filename(filename) {
626
+ return !filename || filename.includes("/") ? !1 : s3AssetFilenamePattern.test(filename);
539
627
  }
540
- class UnresolvableError extends Error {
541
- unresolvable = !0;
542
- // The input may not be a valid source, so let's not type it as one
543
- constructor(inputSource, message = "Failed to resolve asset ID from source") {
544
- super(message), this.input = inputSource;
628
+ function getS3UrlPath(urlOrPath) {
629
+ if (typeof urlOrPath != "string" || !urlOrPath.trim())
630
+ throw new UnresolvableError(urlOrPath, "Failed to resolve path from URL/path");
631
+ if (isAbsoluteUrl(urlOrPath)) {
632
+ const pathname = new URL(urlOrPath).pathname.replace(/^\/+/, "");
633
+ if (!pathname)
634
+ throw new UnresolvableError(urlOrPath, "Failed to resolve path from URL/path");
635
+ return pathname;
545
636
  }
637
+ const normalized = urlOrPath.split("?")[0]?.split("#")[0]?.replace(/^\/+/, "") || urlOrPath.replace(/^\/+/, "");
638
+ if (!normalized)
639
+ throw new UnresolvableError(urlOrPath, "Failed to resolve path from URL/path");
640
+ return normalized;
546
641
  }
547
- function isUnresolvableError(err) {
548
- const error = err;
549
- return !!(error.unresolvable && "input" in error);
550
- }
551
- function getForgivingResolver(method) {
552
- return (...args) => {
553
- try {
554
- return method(...args);
555
- } catch (err) {
556
- if (isUnresolvableError(err))
557
- return;
558
- throw err;
559
- }
560
- };
561
- }
562
- function isInProgressUpload(stub) {
563
- const item = stub;
564
- return isObject$1(item) && !!item._upload && !("asset" in item);
565
- }
566
- function isS3AssetObjectStub(stub) {
567
- const item = stub;
568
- return isObject$1(item) && !!item.asset && typeof item.asset == "object";
569
- }
570
- function getS3AssetDocumentId(src) {
571
- if (isInProgressUpload(src))
572
- return inProgressAssetId;
573
- const source = isS3AssetObjectStub(src) ? src.asset : src;
574
- let id = "";
575
- if (isReferenceLike(source) ? id = source._ref : id = source._id || "", !(id && idPattern.test(id)))
576
- throw new UnresolvableError(src);
577
- return id;
578
- }
579
- const tryGetS3AssetDocumentId = getForgivingResolver(getS3AssetDocumentId);
580
- function getS3ImageDimensions(src) {
581
- if (isInProgressUpload(src))
582
- return {
583
- width: 0,
584
- height: 0,
585
- aspectRatio: 0,
586
- _type: "s3ImageDimensions"
587
- };
588
- const imageId = getS3AssetDocumentId(src), {
589
- width,
590
- height
591
- } = parseImageAssetId(imageId), aspectRatio = width / height;
592
- return {
593
- width,
594
- height,
595
- aspectRatio,
596
- _type: "s3ImageDimensions"
597
- };
598
- }
599
- const forgivingGetS3ImageDimensions = getForgivingResolver(getS3ImageDimensions);
600
- function tryGetS3ImageDimensions(src) {
601
- return forgivingGetS3ImageDimensions(src);
602
- }
603
- function isS3FileSource(src) {
604
- const assetId = tryGetS3AssetDocumentId(src);
605
- return assetId ? assetId.startsWith(`${S3AssetType.FILE}-`) : !1;
606
- }
607
- function isS3ImageSource(src) {
608
- const assetId = tryGetS3AssetDocumentId(src);
609
- return assetId ? assetId.startsWith(`${S3AssetType.IMAGE}-`) : !1;
610
- }
611
- function isS3VideoSource(src) {
612
- const assetId = tryGetS3AssetDocumentId(src);
613
- return assetId ? assetId.startsWith(`${S3AssetType.VIDEO}-`) : !1;
642
+ function getS3UrlFilename(urlOrPath) {
643
+ const parts = getS3UrlPath(urlOrPath).split("/").filter(Boolean), filename = parts[parts.length - 1];
644
+ if (!isValidS3Filename(filename))
645
+ throw new UnresolvableError(urlOrPath, `Failed to resolve filename from URL/path '${urlOrPath}'`);
646
+ return filename;
614
647
  }
615
- const isS3FileAsset = (asset) => asset._type === "s3FileAsset", isS3ImageAsset = (asset) => asset._type === "s3ImageAsset", isS3VideoAsset = (asset) => asset._type === "s3VideoAsset", MAX_CONCURRENT_UPLOADS = 4, fetchExistingAsset = (client, assetType, id) => client.observable.fetch("*[_type == $documentType && _id == $id][0]", {
648
+ const tryGetS3UrlFilename = getForgivingResolver(getS3UrlFilename), MAX_CONCURRENT_UPLOADS = 4, fetchExistingAsset = (client, assetType, id) => client.observable.fetch("*[_type == $documentType && _id == $id][0]", {
616
649
  documentType: `${assetType}Asset`,
617
650
  id
618
651
  }, {
@@ -3542,6 +3575,7 @@ exports.SUPPORTED_ASSET_TYPES = SUPPORTED_ASSET_TYPES;
3542
3575
  exports.TableHeader = TableHeader;
3543
3576
  exports.TableRowAsset = TableRowAsset;
3544
3577
  exports.UPLOAD_STATUS_KEY = UPLOAD_STATUS_KEY;
3578
+ exports.UnresolvableError = UnresolvableError;
3545
3579
  exports.UploadDropDownMenu = UploadDropDownMenu;
3546
3580
  exports.UploadDropzone = UploadDropzone;
3547
3581
  exports.UploadPlaceholder = UploadPlaceholder;
@@ -3555,25 +3589,29 @@ exports.createS3Client = createS3Client;
3555
3589
  exports.createUploadEvent = createUploadEvent;
3556
3590
  exports.dialogActions = dialogActions;
3557
3591
  exports.getAssetResolution = getAssetResolution;
3592
+ exports.getForgivingResolver = getForgivingResolver;
3558
3593
  exports.getOrderTitle = getOrderTitle;
3559
3594
  exports.getSchemeColor = getSchemeColor;
3560
3595
  exports.getUniqueDocuments = getUniqueDocuments;
3561
3596
  exports.initialState = initialState$4;
3562
3597
  exports.isInProgressUpload = isInProgressUpload;
3598
+ exports.isReference = isReference;
3599
+ exports.isS3AssetObjectStub = isS3AssetObjectStub;
3563
3600
  exports.isS3FileAsset = isS3FileAsset;
3564
- exports.isS3FileSource = isS3FileSource;
3565
3601
  exports.isS3ImageAsset = isS3ImageAsset;
3566
- exports.isS3ImageSource = isS3ImageSource;
3567
3602
  exports.isS3VideoAsset = isS3VideoAsset;
3568
- exports.isS3VideoSource = isS3VideoSource;
3603
+ exports.parseS3AssetFilename = parseS3AssetFilename;
3604
+ exports.parseS3ImageAssetId = parseS3ImageAssetId;
3569
3605
  exports.rootEpic = rootEpic;
3570
3606
  exports.rootReducer = rootReducer;
3607
+ exports.s3AssetIdPattern = s3AssetIdPattern;
3608
+ exports.s3InProgressAssetId = s3InProgressAssetId;
3571
3609
  exports.searchActions = searchActions;
3572
3610
  exports.selectAssetById = selectAssetById;
3573
3611
  exports.selectAssetsPicked = selectAssetsPicked;
3574
3612
  exports.selectCombinedItems = selectCombinedItems;
3575
3613
  exports.selectUploadById = selectUploadById;
3576
- exports.tryGetS3ImageDimensions = tryGetS3ImageDimensions;
3614
+ exports.tryGetS3UrlFilename = tryGetS3UrlFilename;
3577
3615
  exports.uploadS3Asset = uploadS3Asset;
3578
3616
  exports.uploadsActions = uploadsActions;
3579
3617
  exports.useAssetSourceActions = useAssetSourceActions;