scorm-again
Version:
A modern SCORM JavaScript run-time library for SCORM 1.2 and SCORM 2004
3 lines (2 loc) • 2.84 kB
JavaScript
class e{_api;_origin;_rateLimit;_requestTimes=[];_destroyed=!1;_boundOnMessage;static ALLOWED_METHODS=new Set(["LMSInitialize","LMSFinish","LMSGetValue","LMSSetValue","LMSCommit","LMSGetLastError","LMSGetErrorString","LMSGetDiagnostic","Initialize","Terminate","GetValue","SetValue","Commit","GetLastError","GetErrorString","GetDiagnostic","getFlattenedCMI"]);constructor(e,s="*",t={}){this._api=e,this._origin=s,this._rateLimit=t.rateLimit??100,"*"===s&&console.warn("CrossFrameLMS: Using wildcard origin ('*') allows any origin to send messages. This is insecure for production use. Specify an explicit origin (e.g., 'https://content.example.com') to restrict message sources."),this._boundOnMessage=this._onMessage.bind(this),window.addEventListener("message",this._boundOnMessage)}destroy(){this._destroyed||(this._destroyed=!0,window.removeEventListener("message",this._boundOnMessage),this._requestTimes.length=0)}_isRateLimited(){const e=Date.now();return this._requestTimes=this._requestTimes.filter(s=>1e3>e-s),this._requestTimes.length>=this._rateLimit||(this._requestTimes.push(e),!1)}static _isValidMessageData(e){if("object"!=typeof e||null===e)return!1;const s=e;return!("string"!=typeof s.messageId||0===s.messageId.length||"string"!=typeof s.method||0===s.method.length||void 0!==s.params&&!Array.isArray(s.params)||void 0!==s.isHeartbeat&&"boolean"!=typeof s.isHeartbeat)}_onMessage(s){if(this._destroyed)return;if("*"!==this._origin&&s.origin!==this._origin)return;if(!e._isValidMessageData(s.data))return;const t=s.data;if(!s.source)return;if(!("postMessage"in s.source))return;const i=s.source;t.isHeartbeat?i.postMessage({messageId:t.messageId,isHeartbeat:!0},this._origin):this._isRateLimited()?i.postMessage({messageId:t.messageId,error:{message:"Rate limit exceeded",code:"101"}},this._origin):e.ALLOWED_METHODS.has(t.method)?this._process(t,i):i.postMessage({messageId:t.messageId,error:{message:"Method not allowed: "+t.method,code:"101"}},this._origin)}_process(e,s){const t=(result,t)=>{const i={messageId:e.messageId};void 0!==result&&(i.result=result),void 0!==t&&(i.error=t),s.postMessage(i,this._origin)};try{const s=this._api[e.method];if("function"!=typeof s)return void t(void 0,{message:`Method ${e.method} not found`});const result=s.apply(this._api,Array.isArray(e.params)?e.params:[]);result&&"function"==typeof result.then?result.then(e=>t(e)).catch(e=>{const s=e&&"object"==typeof e&&"code"in e&&"string"==typeof e.code?e.code:void 0,i={message:e instanceof Error?e.message:"Unknown error"};void 0!==s&&(i.code=s),t(void 0,i)}):t(result)}catch(e){const s=e&&"object"==typeof e&&"code"in e&&"string"==typeof e.code?e.code:void 0,i={message:e instanceof Error?e.message:"Unknown error"};void 0!==s&&(i.code=s),t(void 0,i)}}}export{e as CrossFrameLMS};
//# sourceMappingURL=cross-frame-lms.min.js.map