@cross-nft-marketplace/auction-house-nft-components
Version:
NFT Media Rendering Components
177 lines (176 loc) • 7.96 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchContentMimeTypes = exports.fetchContentMimeType = exports.resolveURIGateways = exports.getAppropriateMedia = exports.getMediaType = exports.getMediaSizeForRendering = void 0;
const auction_house_nft_hooks_1 = require("@cross-nft-marketplace/auction-house-nft-hooks");
const RendererConfig_1 = require("./RendererConfig");
const FetchWithTimeout_1 = require("@cross-nft-marketplace/auction-house-nft-hooks/dist/fetcher/FetchWithTimeout");
const TAKE_LEFT = -1;
const TAKE_RIGHT = 1;
const INDEX_MISSED = -1;
function getCdnIndex(uri, cdnHostsSortedByPriority) {
let url = new URL(uri);
let host = url.hostname;
//example: lh3.googleusercontent.com
return cdnHostsSortedByPriority.findIndex(cdn => host.endsWith(cdn));
}
function getMediaSizeForRendering(renderingContext) {
return renderingContext === "FULL" ? auction_house_nft_hooks_1.MediaSize.ORIGINAL : auction_house_nft_hooks_1.MediaSize.THUMBNAIL;
}
exports.getMediaSizeForRendering = getMediaSizeForRendering;
const MEDIA_TYPES_FULL = [
auction_house_nft_hooks_1.MediaType.MODEL,
auction_house_nft_hooks_1.MediaType.VIDEO,
auction_house_nft_hooks_1.MediaType.IMAGE,
auction_house_nft_hooks_1.MediaType.DOCUMENT,
auction_house_nft_hooks_1.MediaType.AUDIO,
auction_house_nft_hooks_1.MediaType.TEXT,
auction_house_nft_hooks_1.MediaType.UNKNOWN
];
const MEDIA_TYPES_PREVIEW = [
auction_house_nft_hooks_1.MediaType.VIDEO,
auction_house_nft_hooks_1.MediaType.IMAGE,
auction_house_nft_hooks_1.MediaType.DOCUMENT,
auction_house_nft_hooks_1.MediaType.AUDIO,
auction_house_nft_hooks_1.MediaType.MODEL,
auction_house_nft_hooks_1.MediaType.TEXT,
auction_house_nft_hooks_1.MediaType.UNKNOWN
];
function getMediaType(mimeType) {
if (mimeType.startsWith(RendererConfig_1.MIME_TYPES_CONTENT.IMAGE_GIF) || mimeType.startsWith(RendererConfig_1.MIME_TYPES_CONTENT.VIDEO)) {
return auction_house_nft_hooks_1.MediaType.VIDEO; //todo rename to "ANIMATION"
}
if (mimeType.startsWith(RendererConfig_1.MIME_TYPES_CONTENT.IMAGE)) {
return auction_house_nft_hooks_1.MediaType.IMAGE;
}
if (mimeType.startsWith(RendererConfig_1.MIME_TYPES_CONTENT.AUDIO)) {
return auction_house_nft_hooks_1.MediaType.AUDIO;
}
if (mimeType.startsWith(RendererConfig_1.MIME_TYPES_CONTENT.HTML) || mimeType.startsWith(RendererConfig_1.MIME_TYPES_CONTENT.PDF_DOCUMENT)) {
return auction_house_nft_hooks_1.MediaType.DOCUMENT;
}
if (mimeType.startsWith(RendererConfig_1.MIME_TYPES_CONTENT.MODEL)) {
return auction_house_nft_hooks_1.MediaType.MODEL;
}
if (mimeType.startsWith(RendererConfig_1.MIME_TYPES_CONTENT.TEXT)) {
return auction_house_nft_hooks_1.MediaType.TEXT;
}
return auction_house_nft_hooks_1.MediaType.UNKNOWN;
}
exports.getMediaType = getMediaType;
//todo support unknown size
// Stages:
// 1) Filter by supported mimeTypes
// 2) Do not give preference big medias for preview and preview media for full
// 3) Sort by MediaType
// 4) Sort by CDN
function getAppropriateMedia(medias, target, options) {
let mediasWithMediaType = medias.filter((media) => {
if (media.meta.mimeType == "") {
return false;
}
return target.mimeTypes.some(mimeType => media.meta.mimeType.startsWith(mimeType));
});
if (mediasWithMediaType.length == 0) {
//todo handle no mimeType (ex: cors), possible use mediaType instead.
}
let sortedMedias = mediasWithMediaType.sort((first, second) => {
if (target.mediaSize == auction_house_nft_hooks_1.MediaSize.THUMBNAIL) {
if (first.meta.sizeInBytes != null) {
if (second.meta.sizeInBytes != null) {
if (first.meta.sizeInBytes < options.maxPreviewSizeInBytes && second.meta.sizeInBytes > options.maxPreviewSizeInBytes) {
return TAKE_LEFT;
}
if (first.meta.sizeInBytes > options.maxPreviewSizeInBytes && second.meta.sizeInBytes < options.maxPreviewSizeInBytes) {
return TAKE_RIGHT;
}
}
else {
//todo
}
}
else {
//todo
}
}
//sort by MediaSize
//dont use preview for nft-full
if (target.mediaSize == auction_house_nft_hooks_1.MediaSize.ORIGINAL) {
if (first.mediaSize != auction_house_nft_hooks_1.MediaSize.THUMBNAIL && second.mediaSize == auction_house_nft_hooks_1.MediaSize.THUMBNAIL) {
return TAKE_LEFT;
}
if (first.mediaSize == auction_house_nft_hooks_1.MediaSize.THUMBNAIL && second.mediaSize != auction_house_nft_hooks_1.MediaSize.THUMBNAIL) {
return TAKE_RIGHT;
}
}
//sort by MediaType
//todo only from supported renderers
let mediaTypeFirst = getMediaType(first.meta.mimeType);
let mediaTypeSecond = getMediaType(second.meta.mimeType);
let priorityList = target.mediaSize == auction_house_nft_hooks_1.MediaSize.THUMBNAIL
? MEDIA_TYPES_PREVIEW
: MEDIA_TYPES_FULL;
let mediaTypeIndexFirst = priorityList.indexOf(mediaTypeFirst);
let mediaTypeIndexSecond = priorityList.indexOf(mediaTypeSecond);
if (mediaTypeIndexFirst < mediaTypeIndexSecond) {
return TAKE_LEFT;
}
else if (mediaTypeIndexFirst > mediaTypeIndexSecond) {
return TAKE_RIGHT;
}
//sort by CDN
let cdnIndexFirst = getCdnIndex(first.url, options.cdnHosts);
let cdnIndexSecond = getCdnIndex(second.url, options.cdnHosts);
if (cdnIndexFirst != INDEX_MISSED && cdnIndexSecond == INDEX_MISSED) {
return TAKE_LEFT;
}
else if (cdnIndexFirst == INDEX_MISSED && cdnIndexSecond != INDEX_MISSED) {
return TAKE_RIGHT;
}
else if (cdnIndexFirst != cdnIndexSecond) {
return cdnIndexFirst - cdnIndexSecond;
}
else {
return 0;
}
});
return sortedMedias[0];
}
exports.getAppropriateMedia = getAppropriateMedia;
function resolveURIGateways(uri, preferredIPFSGateway) {
if (uri.startsWith("ipfs://")) {
return uri.replace("ipfs://", preferredIPFSGateway || "https://ipfs.io/ipfs/");
}
if (uri.includes("/ipfs/") && preferredIPFSGateway) {
return `${preferredIPFSGateway}${uri.replace(/^.+\/ipfs\//, "")}`;
}
if (uri.startsWith("ar://")) {
return uri.replace("ar://", "https://arweave.net/");
}
return uri;
}
exports.resolveURIGateways = resolveURIGateways;
async function fetchContentMimeType(url, preferredIPFSGateway) {
const response = await new FetchWithTimeout_1.FetchWithTimeout(2000).fetch(resolveURIGateways(url, preferredIPFSGateway), {
method: 'HEAD',
});
const mimeType = response.headers.get('content-type');
let size = undefined;
let sizeHeader = response.headers.get('content-length');
if (sizeHeader) {
let parsedSize = parseInt(sizeHeader);
if (!isNaN(parsedSize)) {
size = parsedSize;
}
}
return {
mimeType: mimeType || "",
sizeInBytes: size
};
}
exports.fetchContentMimeType = fetchContentMimeType;
async function fetchContentMimeTypes(urls, preferredIPFSGateway) {
let promises = urls.map(url => fetchContentMimeType(url, preferredIPFSGateway).catch(_ => { return { mimeType: "" }; }));
let mimeTypes = await Promise.all(promises);
return mimeTypes;
}
exports.fetchContentMimeTypes = fetchContentMimeTypes;