-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhcs-recursion-sdk.js
1 lines (1 loc) · 14 KB
/
hcs-recursion-sdk.js
1
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).HCSRecusionSDK={})}(this,(function(t){"use strict";class e{constructor(){this.modelViewerLoaded=!1,this.modelViewerLoading=null,this.config={cdnUrl:"https://kiloscribe.com/api/inscription-cdn/",network:"mainnet",retryAttempts:3,retryBackoff:300,debug:!1,showLoadingIndicator:!1,loadingCallbackName:null},this.configMapping={hcsCdnUrl:"cdnUrl",hcsNetwork:"network",hcsRetryAttempts:"retryAttempts",hcsRetryBackoff:"retryBackoff",hcsDebug:"debug",hcsShowLoadingIndicator:"showLoadingIndicator",hcsLoadingCallbackName:"loadingCallbackName"},this.LoadedScripts={},this.LoadedWasm={},this.LoadedImages={},this.LoadedVideos={},this.LoadedAudios={},this.LoadedAudioUrls={},this.LoadedGLBs={},this.scriptLoadedEvent=new Event("HCSScriptLoaded"),this.loadQueue=[],this.isProcessingQueue=!1}log(...t){this.config.debug&&console.log("[HCS SDK]",...t)}error(...t){console.error("[HCS SDK]",...t)}loadConfigFromHTML(){const t=document.querySelector("script[data-hcs-config]");t&&Object.keys(this.configMapping).forEach((e=>{if(t.dataset[e]){const i=this.configMapping[e];let a=t.dataset[e];"true"===a&&(a=!0),"false"===a&&(a=!1),isNaN(Number(a))||""===a||(a=Number(a)),this.config[i]=a}})),this.log("Loaded config:",this.config)}updateLoadingStatus(t,e){if("loaded"!==this.LoadedScripts[t]&&(this.config.showLoadingIndicator&&console.log("[HCS Loading] "+t+" : "+e),this.LoadedScripts[t]=e,this.config.loadingCallbackName&&"function"==typeof window[this.config.loadingCallbackName])){const i=window[this.config.loadingCallbackName];"function"==typeof i&&i(t,e)}}async fetchWithRetry(t,e=this.config.retryAttempts,i=this.config.retryBackoff){try{const e=await fetch(t);if(!e.ok)throw new Error("HTTP error! status: "+e.status);return e}catch(a){if(e>0)return this.log("Retrying fetch for "+t+" Attempts left: "+(e-1)),await this.sleep(i),this.fetchWithRetry(t,e-1,2*i);throw a}}sleep(t){return new Promise((e=>setTimeout(e,t)))}isDuplicate(t){return!!this.LoadedScripts[t]}async retrieveHCS1Data(t,e=this.config.cdnUrl,i=this.config.network){const a=i.replace(/['"]+/g,""),s=await this.fetchWithRetry(e+t+"?network="+a);return await s.blob()}async loadScript(t){const e=t.getAttribute("data-src"),i=t.getAttribute("data-script-id"),a=null==e?void 0:e.split("/").pop(),s=t.getAttribute("type"),o=t.hasAttribute("data-required"),d="module"===t.getAttribute("type");if(!this.isDuplicate(a||"")){this.updateLoadingStatus(i,"loading");try{const e=t.getAttribute("data-cdn-url")||this.config.cdnUrl,r=t.getAttribute("data-network")||this.config.network,c=await this.retrieveHCS1Data(a,e,r);if("wasm"===s){const e=await c.arrayBuffer(),a=await WebAssembly.compile(e);this.LoadedWasm[i]=await WebAssembly.instantiate(a,{env:{},...t.dataset}),this.updateLoadingStatus(i,"loaded"),window.dispatchEvent(this.scriptLoadedEvent),this.log("Loaded wasm: "+i)}else{const t=await c.text(),e=document.createElement("script");if(e.textContent=t,e.className="hcs-inline-script",i&&e.setAttribute("data-loaded-script-id",i),d){e.type="module";const i=new Blob([t],{type:"application/javascript"});e.src=URL.createObjectURL(i)}document.body.appendChild(e),this.updateLoadingStatus(i,"loaded"),window.dispatchEvent(this.scriptLoadedEvent),this.log("Loaded script: "+i),e.onerror=t=>{if(this.error("Failed to load "+s+": "+i,t),this.updateLoadingStatus(i,"failed"),o)throw t}}}catch(r){if(this.error("Failed to load "+s+": "+i,r),this.updateLoadingStatus(i,"failed"),o)throw r}}}async loadModuleExports(t){const e=document.querySelector('script[data-loaded-script-id="'+t+'"]');if(!e)throw new Error("Module script with id "+t+" not found");const i=e.getAttribute("src");if(!i)throw new Error("Module script "+t+" has no src attribute");return await import(i)}async loadStylesheet(t){const e=t.getAttribute("data-src"),i=t.getAttribute("data-script-id"),a=null==e?void 0:e.split("/").pop(),s=t.hasAttribute("data-required");if(!this.isDuplicate(a||"")){this.updateLoadingStatus(i,"loading");try{const e=t.getAttribute("data-cdn-url")||this.config.cdnUrl,s=t.getAttribute("data-network")||this.config.network,o=await this.retrieveHCS1Data(a,e,s),d=await o.text(),r=document.createElement("style");r.textContent=d,document.head.appendChild(r),this.updateLoadingStatus(i,"loaded"),window.dispatchEvent(this.scriptLoadedEvent),this.log("Loaded and inlined stylesheet: "+i)}catch(o){if(this.error("Failed to load stylesheet: "+i,o),this.updateLoadingStatus(i,"failed"),s)throw o}}}async loadImage(t){const e=t.getAttribute("data-src"),i=null==e?void 0:e.split("/").pop();this.log("Loading image: "+i),this.updateLoadingStatus("Image: "+i,"loaded");try{const e=t.getAttribute("data-cdn-url")||this.config.cdnUrl,a=t.getAttribute("data-network")||this.config.network,s=await this.retrieveHCS1Data(i,e,a),o=URL.createObjectURL(s);t.src=o,this.LoadedImages[i]=o,this.updateLoadingStatus("Image: "+i,"loaded"),this.log("Loaded image: "+i)}catch(a){this.error("Failed to load image: "+i,a),this.updateLoadingStatus("Image: "+i,"failed")}}async loadMedia(t,e){const i=t.getAttribute("data-src"),a=null==i?void 0:i.split("/").pop();this.log("Loading "+e+": "+a),this.updateLoadingStatus(e+": "+a,"loading");try{const i=t.getAttribute("data-cdn-url")||this.config.cdnUrl,s=t.getAttribute("data-network")||this.config.network,o=await this.retrieveHCS1Data(a,i,s),d=URL.createObjectURL(o);t.src=d,"video"===e?this.LoadedVideos[a]=d:this.LoadedAudioUrls[a]=d,this.updateLoadingStatus(e+": "+a,"loaded"),this.log("Loaded "+e+": "+a)}catch(s){this.error("Failed to load "+e+": "+a,s),this.updateLoadingStatus(e+": "+a,"failed")}}async loadModelViewer(){return this.modelViewerLoading?this.modelViewerLoading:this.modelViewerLoaded?Promise.resolve():(this.modelViewerLoading=new Promise((t=>{const e=document.createElement("script");e.setAttribute("data-src","hcs://1/0.0.7293044"),e.setAttribute("data-script-id","model-viewer"),e.setAttribute("type","module"),window.addEventListener("HCSScriptLoaded",(()=>{this.modelViewerLoaded=!0,t()}),{once:!0}),this.loadScript(e)})),this.modelViewerLoading)}async loadGLB(t){var e;await this.loadModelViewer();const i=t.getAttribute("data-src"),a=null==i?void 0:i.split("/").pop();this.log("Loading GLB: "+a),this.updateLoadingStatus("GLB: "+a,"loading");try{const i=t.getAttribute("data-cdn-url")||this.config.cdnUrl,s=t.getAttribute("data-network")||this.config.network;let o;"model-viewer"!==t.tagName.toLowerCase()?(o=document.createElement("model-viewer"),Array.from(t.attributes).forEach((t=>{o.setAttribute(t.name,t.value)})),o.setAttribute("camera-controls",""),o.setAttribute("auto-rotate",""),o.setAttribute("ar",""),null==(e=t.parentNode)||e.replaceChild(o,t)):o=t;const d=await this.retrieveHCS1Data(a,i,s),r=URL.createObjectURL(d);o.setAttribute("src",r),this.LoadedGLBs[a]=r,this.updateLoadingStatus("GLB: "+a,"loaded"),this.log("Loaded GLB: "+a)}catch(s){this.error("Failed to load GLB: "+a,s),this.updateLoadingStatus("GLB: "+a,"failed")}}async loadResource(t,e,i){return new Promise((a=>{this.loadQueue.push({element:t,type:e,order:i,resolve:a}),this.processQueue()}))}async processQueue(){if(!this.isProcessingQueue){for(this.isProcessingQueue=!0;this.loadQueue.length>0;){const e=this.loadQueue.shift();try{"script"===e.type?await this.loadScript(e.element):"image"===e.type?await this.loadImage(e.element):"video"===e.type||"audio"===e.type?await this.loadMedia(e.element,e.type):"glb"===e.type?await this.loadGLB(e.element):"css"===e.type&&await this.loadStylesheet(e.element),e.resolve()}catch(t){if(this.error("Error processing queue item:",t),"script"===e.type&&e.element.hasAttribute("data-required"))break}}this.isProcessingQueue=!1}}async replaceHCSInStyle(t){let e=t,i=e.indexOf("hcs://");for(;-1!==i;){let t=i;for(;t<e.length&&!["'",'"'," ",")"].includes(e[t]);)t++;const s=e.substring(i,t),o=s.split("/").pop();try{const a=this.config.cdnUrl,d=this.config.network,r=await this.retrieveHCS1Data(o,a,d),c=URL.createObjectURL(r);e=e.substring(0,i)+c+e.substring(t),this.LoadedImages[o]=c,this.log("Replaced CSS HCS URL: "+s+" with "+c)}catch(a){this.error("Failed to load CSS image: "+o,a)}i=e.indexOf("hcs://",i+1)}return e}async processInlineStyles(){var t;const e=document.querySelectorAll('[style*="hcs://"]');this.log("Found "+e.length+" elements with HCS style references");for(const a of Array.from(e)){const t=a.getAttribute("style");if(t){this.log("Processing style: "+t);const e=await this.replaceHCSInStyle(t);t!==e&&(a.setAttribute("style",e),this.log("Updated style to: "+e))}}const i=document.querySelectorAll("style");for(const a of Array.from(i))if(null==(t=a.textContent)?void 0:t.includes("hcs://")){const t=await this.replaceHCSInStyle(a.textContent);a.textContent!==t&&(a.textContent=t)}}async init(){return this.loadConfigFromHTML(),new Promise((t=>{const e=async()=>{const e=document.querySelectorAll('script[data-src^="hcs://"]'),i=document.querySelectorAll('img[data-src^="hcs://"], img[src^="hcs://"]'),a=document.querySelectorAll('video[data-src^="hcs://"], video[src^="hcs://"]'),s=document.querySelectorAll('audio[data-src^="hcs://"], audio[src^="hcs://"]'),o=document.querySelectorAll('model-viewer[data-src^="hcs://"]'),d=document.querySelectorAll('link[data-src^="hcs://"]');document.querySelectorAll('[src^="hcs://"]').forEach((t=>{const e=t.getAttribute("src");e&&(t.setAttribute("data-src",e),t.removeAttribute("src"))})),await this.processInlineStyles();const r=[];[{elements:e,type:"script"},{elements:i,type:"image"},{elements:a,type:"video"},{elements:s,type:"audio"},{elements:o,type:"glb"},{elements:d,type:"css"}].forEach((({elements:t,type:e})=>{t.forEach((t=>{const i=parseInt(t.getAttribute("data-load-order")||"")||1/0;r.push(this.loadResource(t,e,i))}))})),await Promise.all(r);const c=new MutationObserver((t=>{t.forEach((t=>{var e;if(t.addedNodes.forEach((t=>{var e,i,a;if(t.nodeType===Node.ELEMENT_NODE){const s=t;if((null==(e=s.getAttribute("style"))?void 0:e.includes("hcs://"))&&this.processInlineStyles(),"style"===s.tagName.toLowerCase()&&(null==(i=s.textContent)?void 0:i.includes("hcs://"))&&this.processInlineStyles(),null==(a=s.getAttribute("src"))?void 0:a.startsWith("hcs://")){const t=s.getAttribute("src");s.setAttribute("data-src",t),s.removeAttribute("src");switch(s.tagName.toLowerCase()){case"img":this.loadResource(s,"image",1/0);break;case"video":this.loadResource(s,"video",1/0);break;case"audio":this.loadResource(s,"audio",1/0);break;case"script":this.loadResource(s,"script",1/0)}}s.matches('script[data-src^="hcs://"]')?this.loadResource(s,"script",1/0):s.matches('img[data-src^="hcs://"]')?this.loadResource(s,"image",1/0):s.matches('video[data-src^="hcs://"]')?this.loadResource(s,"video",1/0):s.matches('audio[data-src^="hcs://"]')?this.loadResource(s,"audio",1/0):s.matches('model-viewer[data-src^="hcs://"]')?this.loadResource(s,"glb",1/0):s.matches('link[data-src^="hcs://"]')&&this.loadResource(s,"css",1/0);s.querySelectorAll('[data-src^="hcs://"], [src^="hcs://"]').forEach((t=>{const e=t,i=e.tagName.toLowerCase(),a=e.getAttribute("src");switch((null==a?void 0:a.startsWith("hcs://"))&&(e.setAttribute("data-src",a),e.removeAttribute("src")),i){case"script":this.loadResource(e,"script",1/0);break;case"img":this.loadResource(e,"image",1/0);break;case"video":this.loadResource(e,"video",1/0);break;case"audio":this.loadResource(e,"audio",1/0);break;case"model-viewer":this.loadResource(e,"glb",1/0);break;case"link":this.loadResource(e,"css",1/0)}}))}})),"attributes"===t.type){const i=t.target;if("style"===t.attributeName&&(null==(e=i.getAttribute("style"))?void 0:e.includes("hcs://")))this.processInlineStyles();else if("src"===t.attributeName){const t=i.getAttribute("src");if(null==t?void 0:t.startsWith("hcs://")){i.setAttribute("data-src",t),i.removeAttribute("src");const e=i.tagName.toLowerCase();["img","video","audio"].includes(e)&&this.loadResource(i,e,1/0)}}}}))}));document.body?c.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["style","src","data-src"]}):document.addEventListener("DOMContentLoaded",(()=>{c.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["style","src","data-src"]})})),t()};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e()}))}async preloadImage(t){this.log("Loading image:"+t),this.updateLoadingStatus("image: "+t,"loading");const e=await this.retrieveHCS1Data(t),i=URL.createObjectURL(e);return this.LoadedImages[t]=i,this.updateLoadingStatus("image: "+t,"loaded"),i}async preloadAudio(t){const e=document.createElement("audio");e.setAttribute("data-topic-id",t),e.setAttribute("data-src","hcs://1/"+t),document.body.appendChild(e),await this.loadMedia(e,"audio");const i=document.querySelector('audio[data-topic-id="'+t+'"]');return i?this.LoadedAudioUrls[t]=i.src:console.error("Failed to preload audio: "+t),this.LoadedAudioUrls[t]}async playAudio(t,e=1){const i=this.LoadedAudioUrls[t];if(i){const a=new Audio(i);a.volume=e,this.LoadedAudios[t]=a,a.play().catch((t=>{console.error("Failed to play audio:",t)})),a.addEventListener("ended",(()=>{a.remove(),delete this.LoadedAudios[t]}))}else console.error("Audio not preloaded: "+t)}async pauseAudio(t){var e,i;const a=document.querySelector('audio[data-topic-id="'+t+'"]');a?(console.log("found element",a),a.pause(),null==(e=this.LoadedAudios[t])||e.pause()):null==(i=this.LoadedAudios[t])||i.pause()}async loadAndPlayAudio(t,e=!1,i=1){let a=document.querySelector('audio[data-topic-id="'+t+'"]');if(a)a.volume=i,await a.play();else{const s=document.createElement("audio");s.volume=i,e&&s.setAttribute("autoplay","autoplay"),s.setAttribute("data-topic-id",t),s.setAttribute("data-src","hcs://1/"+t),document.body.appendChild(s),await this.loadMedia(s,"audio"),a=document.querySelector('audio[data-topic-id="'+t+'"]'),e||await a.play()}}}window.HCS=new e,window.HCS.init().then((()=>{console.log("All HCS resources loaded"),"function"==typeof window.HCSReady&&(console.log("Running HCSReady..."),window.HCSReady())}));const i=window.HCS;t.HCS=e,t.default=i,t.sleep=t=>new Promise((e=>setTimeout(e,t))),Object.defineProperties(t,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));